Implementation


 

The idea of this project, or should I say the basic model, is to send an indiscriminate file or message with variable size through a point-to-point bluetooth connection, from one computer to another. Only minimal  error handling features is expected.

 

However we recently discovered that the message to be sent was a command which would start up the program on the RCX (the Russian Spaceship). Nonetheless we will try to achieve to full goal, that is, the handling of a variable size file or message.

 

To achieve this goal we had many approaches:

[ First approach ] [ Second approach ] [ Third approach ]

 

First Approach:

^TOP

In order to fulfill the second part of the project we tried on a numerous of Bluetooth stack implementations, in this order:

 

- Bluetooth tty driver

 

The very first we tried, it comes with the linux kernel and its a simple implementation of a serial interface. However the code is somewhat confusing and didn't work as expected.

 

- BlueZ

 

The second one we started to see. We delve deep in to this one but could make it work at first. We understood that the implementation of the bluetooth stack was quite huge and mostly unnecessary for our class project. Understanding the code seemed difficult and after taking the advice of the professor we for a while.

 

- Billotooth

 

The third protocol stack implementation we tried. This implementation was devised by the student Fernando Billo as a Final Project for his Course. And though the thesis was well written, the lack o f fundamental information, such as how and for what version of the kernel did he compile, caused an immediate frustration. This was due to the fact that this was the most promising implementation, because it was simple and compact. Have we more experience in driver programming or even linux, we might discovered how to use it. Or not. He seemed happy to help us in the first response, but when asked about more specific question he was unable to respond (he is probably busy, so we do not complain)

 

- Affix

 

The forth implementation we tried. This one also seemed simpler than the Bluez implantation, and was better commented. It had comprehensive Manuals with to-the-point examples. However, when we tried to recompile the kernel to install it caused a crash in the Mandrake installation. Forcing us to restore to the previous setup.

 

- BlueZ

 

After the failure in installing the affix protocol stack, we resorted to the BlueZ implementation since it had its kernel already as part of the linux kernel. The Debian install on the xbox has a 2.4.20 kernel, and our mandrake distribution (9.1) has 2.4.21. Both had up-to-date versions of the bluez kernel.

We proceeded installing the minimal tools to set a connection between to computers. That was the libs and the utils packages, the later contains libraries for bluetooth development and the utils package contains utilities and examples to use and set up a Bluetooth connection, such as hciconfig and l2test.

Since on of our computers had broke down, with only tested the connection between two adapters in the same computer. Each adapter was set in a different USB port. After that we followed this steps:

 

>modprobe hci_usb

>hciconfig

>hcid

>hciconfig

 

we open up a second terminal window, on the first we typed:

 

>./l2test -r 00:60:57:09:92:88

 

this set the device with BD_ADDR 00:60:57:09:92:88 listening for any incoming signal.

on the second window we typed:

 

>./l2test -s 00:60:57:09:92:88

 

this told the available adapter to connect to the adapter with the address 00:60:57:09:92:88 and send data packets.

 

Second Approach:

^TOP

- First phase: Studying USB device drivers with:

 

Programming Guide to Linux USB device drivers

Linux Device Drivers

Others (Google search, USB specifications, etc.)

 

- Second Phase: Attempting to develop simple USB drivers, focusing on the bluetooth functions.

(Getting BD_ADDR, sending Packets, receiving packets (events))

 As we understand now, we would not need to implement inquiry function. If the device assumes there's another bluetooth device in range, it does not need to inquire for other devices. Neither would be essential the Pairing function (PIN code setting).

 

Basic Device model:

Mainly it's going to have four functions:

- connect function (sends connection request specifying the BD_ADDR)

- accept connection (Accepts a incoming connection request)

probably there will be no need to reject a connection request, if we assume we would not send one. ;) But can be implemented if not too much of a hassle.

- Send function (Sends a packet)

- Receive Function (Waits for a incoming packet, and reads it once it arrives)

 As we understand the adapter reads the incoming signal, analyze it to find out if its addressed for it, and if so sends an event to the module.

 

A server program would have this behavior:

Starts.

waits for incoming connection request, and accepts it as soon as it gets it. once incoming request arrives, set timeout for a number of milliseconds).

wait for incoming packet.

while receiving packets restart the timer.

if the timer goes off, or receives a disconnect request, build the file joining the received packets, in the order they were received (Do not check for right order).

Builds the file.

waits for disconnection request (if not received before). Then exists.

 

The client program would have this behavior:

Starts.

asks for file to transfer.

initiate connection request.

When connected, breaks down the file in packets and sends them in set intervals (do not wait for ACK).

upon finishing the file transfer, send disconnect request and exit.

 

Obviously the server program would have to be started first.

 

The filename could be sent as part of the transfer. Like the first N char, received are assigned for filename purpose, the rest is related to the actual file.

 

 

Third Approach:

^TOP

After much discussion we perceived that the second approach, creating the interaction directly through the USB functions, would be very much time consuming, and it was already done for the bluez driver. So we then made a effort to talk to Eduardo Afonso Billo, the creator of the Billotooth Stack. We asked how did he interact s with the device and why it was so different from our USB approach. He explained that what we were doing wasn't the hci layer, we were programming de hci interface to the USB layer and that was what caused the confusion.

 

What he did was implement the hci core layer, though a very compact one, which connects to the device through the hci usb interface. This hci_usb is the same used in the bluez stack, with just one or two functions with changed names.

 

So the implementation model is this:

 

Module

Observation

Server Module

The module responsible for receiving and assemble the data. Communicates with the HCI_CORE module.

Client Module

The module responsible for sending the data appropriately to the server side. Also communicates with the HCI_Core.

HCI_CORE, HCI_USB, USBCORE and OHCI_USB

They mediate the communication between the application and the device

 

HCI_CORE

Responsible for handling the high level HCI layer. Packs commands, events and data accordingly to the specification.

HCI_USB

Responsible for handling the low level hci interface with the USB standard. Handles the USB specific functions, but also receives hci packages and transforms in URBs, and vice-versa.

USBCORE

Responsible for the communication with the device. They talk via PCI.

OHCI_USB/UHCI_USB/EHCI_USB

This is the usb controller located in the PCI bus, it translate the incoming PCI stream into urbs that the device understands.

 

The server and client modules will be the real entities responsible for the transmission from one end to another. The client module will break apart the file and the server module will receive packets and assemble the file back to what it was.

The hci_core will be adapted from the billotooth stack. Since this stack is designed to be compact and only have the minimal set of functions to establish a connection and transfer data, only minimal changes, if any, will be made.

The hci_usb module will be taken from the hci_usb template from the most recent bluez stack distribution.

The rest comes with the kernel distribution.

 

Here are some examples of the message path.

>> inquiring surrounding devices

>> establishing an acl connection

>> transmitting a data packet

 

Right now we're capable of transmitting a single character from one point to another and vice-versa. To meet the newfound criteria we only need to handle variable size massages or phrases, and this is the first step. The next consists in not only treating multiple packets, but disassemble and reassemble files in the binary level, even if in the end it's just a text file.

 

For the first stage we were thinking in separating firstly the packets in the character-by-character basis. Then after we succeeded in handling multiple packets, we move on to the second stage.

The second stage would be increasing the size of the packet to the full 64 bytes, and since we have 32 bytes in the data field, we can essentially put up to 16 characters, increasing the overall speed.

The third stage would be using the data field to store binary data, instead of character data.

 

We accomplished the first stage reading a string of characters passed to the driver and sending it character by character through the bluetooth connection. However, the implementation of the protocol led to outstanding errors such as Computer freezes, system forced to reboot, conflict to other hardware. Mostly because they way we implemented the protocol, and later the misuse of user and kernel space memory.

 

Of course this also led to an incredible waste of time, trying to discover and fix the problems, and having the computer reboot every time it failed the test was no help either. Fortunately we overcame the problem.

 

This is the final version of the protocol we used:

To do this the module has two buffers, an out buffer, which saves the message to send, and an in buffer, which saves the massage coming through. Every time the state-machine receives a packet it sends a ACK signal back. This way, by the passing of messages back and forth the actual message can be sent and recover on the other end.

The state-machine is set on the connected state by an innocuous echo command. This way we give time to the bluetooth driver to locate the other bluetooth device and establish the link. After properly connected, it only required to give an echo or cat command on the device nod, like so:

> echo message > /dev/myBlueDev

or

> cat file > /dev/myBlueDev

the message is sent and you can check it in the logs, by typing dmesg. On the server side, after you received the message you can collect it by typing:

> cat /dev/myBlueDev

or you can let the buffer get the next message and print it together. Each buffer has an arbitrary size of 80 characters, chosen for no particular reason. If the buffer fills, the rest of the packets are ignored.

later on we found out that on the lab's computers running RedHat with kernel version 2.4.18-10, the cat command did not work properly. It would not write the data extracted from the IN_BUFFER into the console, only into a text file. So the command on those computer had to be:

> cat /dev/myBlueDev > outputfile

And the incoming message is then read from the file.

 

 
Source Code

This is the latest stable source code used in this project

>>dev_driver/