This article is about the local low-speed network of interaction between BMW control units - I / K-bus. Or rather, how applications from under Linux can interact with it. In the pictures I will illustrate the version created by me.
So, I was faced with the task of expanding the functionality of my car in the field of infotainment system. I just really wanted it. The car is good, but elderly. It was created at a time when even mp3 was not widely used. Therefore, it lacks many modern amenities. In addition, there are additional ideas in my head, embodying which, I can emphasize my individuality.
The infotainment system runs on devices based on embedded program controllers. I will here call these devices control units. Each such control unit carries its own functional load, whether it is maintaining the temperature of the passenger compartment, adjusting the position of the seats, playing music and video, navigation, and so on. This entire set of control units must interact with each other, be controlled from the driver's and passengers seat, and transmit diagnostic data. For this purpose, the I-bus network was developed. Subsequently, a technically identical K-bus network and their I / K-bus association emerged.
The architecture of the I-bus network is made according to the “common bus” scheme, i.e., data pulses from nodes (control units) are transmitted over ordinary copper wire connected at one point. Therefore, nodes must share a common medium and transmit data in turn. I don’t know how this queue or priority is determined, I suppose it’s just that the bus is tapped for availability, and taking into account the guard interval and the bus idleness, the decision to transfer is made. In the "silent" state, the potential level on the tire relative to the body is from 7 V to the vehicle supply voltage. When feeding the dominant bit to the bus, the potential is reduced to 2 V and below. The bit rate of interaction between the nodes is constant and is 9600 bps. Digit familiar from UART. But not only in the transmission speed there are similarities, the format of symbols in the I-bus corresponds to one of the variations available in the UART. The symbol consists of 11 bits: the start bit, 8 data bits, the parity bit, the stop bit. These features allow you to physically connect to the bus via UART or RS-232 interfaces. It is only necessary to take care of the conversion of signal levels using a simple circuit or a ready-made converter. For this purpose, the k-line adapter known in diagnostic interfaces will completely disappear. On the physical level, they are fully compatible. By the way, I use it.
')
I generally told about the physical layer of the I-bus network, now I will briefly describe the link layer, this is if you follow the sequence of the multi-level OSI model. So it will be more logical. As I mentioned earlier, a common medium is used for transmission, which should be divided over time and transmit data to different recipients. Here you can draw an analogy with Ethernet - the data is transmitted in frames containing the sender's address, the recipient's address, the payload (data) and the checksum. The frame does not have a fixed size and lies within 5 - 37 characters. The frame format I drew below:

Here TX ID - the address of the sender, 1 character;
LEN - frame size minus the first two characters, 1 character;
RX ID - the address of the recipient, 1 character;
DATA - payload, 1 - 33 characters;
CK SUM - checksum, 1 character.
The correctness of the received frame is determined by the checksum symbol. The sender does not check the correctness of the received frame by the recipient. Perhaps this is done at the level of receiving its own frame. If there were no collisions and other failures on the bus, the sender will correctly receive its own frame and will not attempt retransmission. According to the information I found on the World Wide Web, it says that the sender is waiting for a 100 ms positive receipt from the recipient. Alas, in practice I have not seen this. Perhaps this applies to particularly important messages and higher level protocols.
What is included in the frame payload refers to the next layer protocol. Work with this protocol is best left to the application layer and work with it in applications. Once again, I’m looking for an I / K-bus networking application on the Linux kernel operating system. The functions of the control units will be executed by applications in user space. Inside the operating system, it is not difficult to organize interactions between applications, there are inter-process communication mechanisms (IPC). But the main task is to link them with the processes of the vehicle control units. For an example, let us turn to the more well-known version of the network of interaction between controllers - CAN. In Linux, this technology is being developed in two projects: SocketCAN and can4linux. The first project is based on the network device driver and protocols that perform frame pre-processing and connect the network device to the socket interface. The second option is based on a character device; I don’t know the details of the implementation of this project, since I didn’t work with it. But I think the analogue can4linux for I / K-bus is the tty driver. It is enough to adjust the speed, the character format of the serial port and by reading / writing the ttyS file, data will be sent / received to the bus. Of course, if it is connected to the serial port adapter.
It seemed to me a more attractive option SocketCAN, and I went the same way. I will explain why. The driver is made of two independent parts: a network device and a network protocol. The network device solves the issues of interaction with the hardware and multiple access, and the network protocol module - filtering messages and interaction with user processes. Applications are connected to the I / K-bus network through sockets, and the tasks of multiple access and filtering are removed. In principle, it is possible to assign filtering and multiple access to any server connected to a tty device and not to go into the kernel. In general, yes, but you still can’t do without interprocessor interaction, and this is, as a variant, the same socket. In addition, many tasks with queues of messages that have to be implemented in the server are solved in the Linux network stack. And to all this, the use of a network device harmoniously fits into the operating system administration philosophy. For example, using the command ifconfig, you can view the status of the interface, stop it or start it.
I implemented the network driver for I / K-bus based on slcan, which is based on SLIP. I did not catch the time when IP packets were transmitted between computers via a serial port. They can now be transferred in this way, but this is not relevant. But to transfer I / K-bus frames in this way is a good option. The tty driver is complex and access to its low-level part can be obtained through the line discipline. This is done in SLIP and slcan, so I did, writing the slibus driver. When the created line discipline is activated through the tty device, the ibusN network device will appear in the system, where N is 0,1,2 ... In order to make the scheme clearer. In it green squares are marked, the functions of which are performed by the slibus core module.

Orange color indicates functionality of the network protocol module. Again, I didn’t reinvent the wheel and, by analogy with the can and can_raw modules, created the af_ibus_raw module. When loaded, this module registers a new family of PF_IBUS protocols, and it also implements a RAW socket for full access to the frame. By calling the setsockopt, you can enable the filter of received messages by sender and recipient identifiers. By default, the socket accepts all messages from the bus.
I must say that there is one trouble, and it lies in the fact that in order to be able to load these modules it is necessary to patch the kernel.
And now let's see how it all works. Load the kernel modules, initialize the line discipline under the number corresponding to slibus, and raise the ibus0 network interface. The ifconfig command in the terminal will show us something like this:

As you can see, the network interface has been successfully launched and has traffic statistics. Before taking a screenshot, I specifically drove the data on the interface. I use the drivers for several months, there were no failures. But there are flaws that have not yet been eliminated. I'll get back to them later, but for now I'm working on applications as I have free time.
The strengths of this approach lie in a number of aspects. Applications running in the operating system have full access to the bus and through it interact with each other. Suppose there is no CD changer in the configuration of my car. It's enough for me to write an application that emulates this device. In doing so, it will play various file formats and online radio. Then I want to complete the telephone module, which I don’t have or don’t like the staff one. I'll just write another program that connects to the smartphone via bluetooth and performs input and output of voice and information in regular places. Or create something of your own, for example, play with e-light lights. Thus, applications are developed independently of each other, can be installed and removed at the request of the owner.
The figure below shows the operation of the ibusdump and ibussend programs. What do these teams do, I think it is clear from the name. The last two lines of ibusdump show that messages that I sent via ibussend were sent across the bus.

At this stop, perhaps. That is transmitted in the frame payload and for which control units I will tell you another time.