wiki:Software/Gateway

Version 31 (modified by art, 13 years ago) (diff)

--

Software

IBus Gateway

OpenBM-Gateway is a linux daemon running in the background and acting as a gateway between BMW's IBus and local clients connected over a network TCP stack. In this case an IBus interface is connected to the PC's serial port. The interface must support CTS line. Hence some hardware collision detection, or at least a simple bit comparator must be implemented. This function is provided for example by the  TH3122 ic, which I am also using in this project.

The software exists as a Debian package for simple installation in my own small repository. In order to install it, either download it directly from the repository or add the repository address into the list of repository servers on your system. Currently there is only Debian packages available. The package consists of only one executable file.

The repository where to find the openbm-gateway package is (or download it  here):

deb http://deb.tevs.eu/ binary/

For information about parameters use

openbm-gateway -h

Features

  • low CPU and memory usage (one thread per client + 4 server threads)
  • forward IBus messages to connected clients over TCP/IPv4 and vice versa
  • retransmit messages on collision
  • completely asynchronous (receive and send messages over IBus and TCP/IP without blocking or intercepting)
  • can act as a simple IBus logger
  • code is actually platform independent (except of some extensions I had to made for  boost's asio library). So there is a possibility to implement this on Windows too.

IBus logger functionality

The daemon can also act as a simple IBus logger. This can be usefull if you just want to log ibus messages passend on the bus. In order to run the daemon as simple logger execute it as

openbm-gateway -l 4 -f ibus.log

Which will protocol ibus actions to the ibus.log file. The log file will look like this:

...
2010-Jul-20 10:07:00.767817: C0 04 68 32 11 8F
2010-Jul-20 10:07:00.891897: C0 04 68 32 11 8F
2010-Jul-20 10:07:00.928066: C0 04 68 32 10 8E
2010-Jul-20 10:07:00.943753: C0 04 68 32 10 8E
2010-Jul-20 10:07:01.116929: C0 03 68 01 AA
2010-Jul-20 10:07:01.140001: 68 04 BF 02 00 D1
...

Note there is currently no analysis going on, just a simple logging.

TCP/IP protocol

In order to be able to connect to the gateway server we have to make sure that server and client speaks the same language. The low-level protocol used for communication between the server (OpenBM-Gateway) and any client is TCP. On top of this a simple, really simple protocol is used to understand sent messages. Here is a small overview over the protocol:

Header:

  Ident:
src dst len lenx priority x x
1 2 3 4 5 6 7 8
  Byte:

Data:

  Ident:
data
1 ... len
  Byte:

Every message sent over the network and to/from the server must have this form. Here x indicates reserved/non-used bytes (lenx is a second reserved byte for the length indication). src and dst are the IBus-Device identifiers (i.e. 0x18 for CD-Changer, 0x00 for GM, 0x68 for Radio, etc...) for source and destination respectively. len indicates the amount of bytes passed in the data field. Data field can be send in another TCP frame or together with the header. priority sets the priority of a message to be sent over IBus.

There are also exists special messages sent between server and the client. This special messages are required for establishing communication and checking if client is still alive for example. Every message in which header len is set to 0, is a special message. There are currently exist following special message types:

  • Ping: src=0xAA, dst=0xAA - is sent by a client every 3 seconds to indicate that the client is still alive
  • Hello: src='h' , dst='i' - is sent by a client to the server before any other message. Server response to this message with a Connect message and creates a socket connection on a reserved port.
  • Connect: src='c' , dst='t' - is sent by a server to client to indicate that connection is established. The priority field of the header contains the port number to which client's socket has to connect to.
  • Disconnect: src=0, dst=0 - is sent by a client to the server, to indicate that client is disconnecting. Server will free resources and mark the used port as free again.

To establish communication between a client and OpenBM-Gateway server following steps has to be done:

 1. Client opens a socket to server's IP-address and port (i.e. 127.0.0.1:4287)
 2. Client send '''Hello''' message and wait for replay from server for 3-5 seconds 
 3. React depending on situation:
    * server did not responded -> server is busy
    * server response with '''Disconnect''' -> there are no free client slots available
    * server response with '''Connect''' -> client's socket has to reconnect to the port received in the ''priority'' field of '''Connect''' message (connection established)
 4. If connection established, client send every 3 seconds '''Ping''' message
 5. Server responses with '''Ping''' message
 6. If server didn't responded, client retries to send a '''Ping''' next two times. If still no response -> connection died
 7. In order to stop connection, client send '''Disconnect''' message and closes its socket.

Once the connection is either closed by the client or lost (server did not respond to ping) the connection must be reestablished again -> goto 1. If server does not receive any ping message within certain amount of time (i.e. 10 sec), then the connection to the client will be closed.

Server

Per default server accept up-to 8 client connections and bind itself to 127.0.0.1:4287. Here the port number 4287 corresponds to IBUS as if it were typed with phone keys. Any clients connected to the server will communicate with the server over consecutive port number, i.e. client 0 communicate through 4288, client 5 through 4293 and so on. In order to bind the server on another address and port, you can do following:

openbm-gateway -p 33001 -i 192.168.0.1

This will bind the server to address 192.168.0.1:33001. Usually the server is only used for local process communication and it does not make much sense to bind the server to any other address rather than 127.0.0.1.

WARNING: Currently server does not support any authentication mechanism, so be aware to bind the server to external addresses or to global address 0.0.0.0 for example. This will make your IBus traffic visible to the outside world and is very dangerous if somebody get used to hack it.

Client

Client can be any application or an external computer communicating over TCP with the machine running the server. A client must send Ping messages every 3 seconds to the server, otherwise server will discard the connection. Client application might be for example a plugin controlling your preferred multimedia application (as I do with XBMC for example). A client can also parse IBus messages and translate them to keyboard presses for example. There is actually nothing really more to say about clients. Maybe someday I will present here a default client which for example send keyboard events on certain ibus messages.


High Level

Since a Gateway is sitting on the hardware IBus and provides a service of connecting to this bus through network, I decided to extend its functionality to some high level services. Here is a list of supported high level services and protocol how to use them.

Firmware Update

An OpenBM-Gateway can also be used to update the firmware on the OpenBM device. The firmware update is done by the protocol described here. The OpenBM-Gateway server takes care of the low-level implementation of that protocol. A client application need just to initiate an update and check result from the server.

Firmware Version

In order to check currently installed firmware version OpenBM need to be reset. Hence on the low level side, the gateway send a reset message over the ibus and receive from the OpenBM's bootloader the currently installed firmware version. This version is passed then back to the client connected over the network.

In order to initiate firmware version check a client need send a message:

  • GetFirmwareVersion: src='f' , dst='g' - Server will answer with the same message after some amount of time, where the current version is stored in the priority field of the header (high byte for major version and low byte for minor version)

Afterwards an update of the firmware can be initiated by the following protocol:

  * send '''InitFirmwareUpdate''': ''src='f' '', ''dst='i' '' - which will cause server to initiate firmware update. The message must contain in the priority field the 32bit password which is specific to the flashed unit and the firmware. 
  * receive '''InitFirmwareUpdate''' - wait for max 3sec. until server response with this message indicating that firmware can be now uploaded. 
  * send '''UploadFirmware''': ''src='f' '', ''dst='u' '' - here the len:lenx is a 16bit number indicating the length in bytes of the data (i.e. firmware) following in the data part of the message. The priority field must contain the checksum (16 bit) delivered with the firmware data. And finally both last reserved bytes in the header must contain the firmware version we are uploading. The data field of this message must contain the full firmware data which will be directly uploaded to the unit.
  * receive '''UploadFirmware''' - server responses with this message every time when next chunk of bytes has been uploaded to the device. 
     * Client application can use the response in order to indicate how much of the data has been already uploaded. 
     * The len:lenx field contains number of bytes already uploaded to the device.
     * The priority field contains 16 bit error code if upload failed (0=NO ERROR, ...)

Pay methods