Dr. Bluetooth Jan. 8, 2017, 9:26 a.m.
Tags: { , , } Category: Programming

or How I Learned to Stop Worrying and Love the Hacking

The story begins when my main laptop broke so I had to use another one which doesn’t have an out-of-the-box driver for the Bluetooth hardware. Lurking on the internet I found some pieces of already hacked yet still outdated code. The code wasn’t working properly with the actual kernel version. With the next kernel version even compilation was broken. That’s where I decided to hack a kernel module and it was a quite interesting experience.

Driver state

The initial state of the code was quite awful (and still is :) ). It looks like the driver was being ported from NT OSes to Linux and this process was never finished. Current version can be barely described as a “technical preview”, not even an alpha. Power management support is far from done for example.

Some of the problematic parts:

  1. lots of redundant code which was never used / or is some sort of legacy / or does not make sense at all;
  2. tabs being used along with spaces for indentation everywhere (ugh);
  3. awkward stuff like the code below.

Code:

int CopyMemory(...) {
    return (int)memcpy(Destination, Source, Length);
}
// HINT: mem copy function returns nothing (or void) //

Also I found that the firmware being used along with the driver is pretty outdated (like 5 years old atm). The worst part here is that the firmware is embedded into a binary blob. Therefore in order to get the new firmware you need to patch the blob with a newer image like so:

dd if=new_firmware.bin of=evil_blob obs=1 seek=$((0xF4320)) conv=notrunc

Here 0xF4320 is the offset inside the blob where the firmware code begins. A little bit more information on this topic was published on Github.

What have been accomplished

First of all it wouldn’t be a huge lie if I’d say that now I uderstand the most part of the code no matter how messy it is. The driver code consists of the following main components: a counterpart to the kernel’s bluetooth inteface, a counterpart to the kernel’s PCI interface, a userspace part and some remains of the OS abstraction layer. Now to what was done already:

Highlights:

  1. hacked to work on all 3.x and 4.x kernels and some of the 2.6.x;
  2. all the compilation warnings were fixed;
  3. added new (and better) firmware which is still optional.

Also driver’s debug output is now less noisy and more readable as well as some parts of the driver’s code.

ToDo (or not to do)

What needs to be done to get the driver in shape:

  1. lots of cleaning and polishing work;
  2. suspend/resume support, because, currently device is not being powered off during sleep, unless you do it yourself;
  3. getting rid of the helpers (rtbth_hlpr_linux.c, rtbth_hlpr_hw.c etc.);
  4. getting rid of the userspace part of the driver (rtbt binary blob and the corresponding driver interface).

It’s a huge amount of work and it requires a high quality manpower as well as enough time and motivation. Unfortunately I don’t have enough time to invest into the development so the most part of the above mentioned goals will never be reached.

Tools being used

I decided to use KDevelop and it was pretty decent experience. KDevelop is quite good for all of the languages it does support and C is not an exception. You just need to create a new project and then to add some include paths:

Kdevelop Project configuration

Then you’ll get everything highlighted nicely and the code can be easily navigated. Without KDevelop it wouldn’t be so fun. So my sincere kudos is going to the KDevelop team. :)

KDevelop screenshot

Usage of KDevelop for debugging in such cases needs a further investigation however.

Code

Project on the Github: link

Thank you for reading.