Writing a bluetooth service is like wading through shit

· nat's blog


It's like every little thing conspires against you to not have any success. If you don't have nrf Connect on your phone or pad, you can just about give up now.

Your laptop hates your service #

So you think you got everything working but the client app just wont connect to your service ? It could be that your laptop is helpfully powering down USB to save some precious power.

Bluetooth lag

Your bluetooth server hates your service #

Just write a GATT service and expect it to work ? Fool! Start configuring first. When you made any change, say sudo systemctl restart bluetooth then check what nrf Connect tells you about your service. In times of desparation remove everything under /var/lib/bluetooth and restart, see Server Setting Dance.

Configuring bluez bluetooth server #

You probably want 'LE' enabled, but depending on circumstances do not enable it with le. It works when you're controller can do both, but NOT if your controller can do just LE, then you need dual although it doesn't make sense:

ControllerMode = dual

If you want to provide your own 0x180A service, you need to disable the builtin one with the intuitive:

DeviceID = false

If you want to use the JustWorks pairing feature, you need to enable it, otherwise your client will be sucessful once, but then stall on the second attempt. The default value is just there to fuck with you. Bluetooth is hard, and you shouldn't have it any easier then your predecessors:

JustWorksRepairing = always

Alright I would do this for development, but I am not that opinioned on it:

[GATT]

Cache = no

These defaults supposedly make your service discoverable. It's a lie:

AutoEnable=true
DiscoverableTimeout=0

On my laptop i have to manually turn on bluetoothctl discovery on. Not on the desktop though. I have no idea why. Remember, if your Flags are missing in the advertisement, not having discover on is probably the reason. And them noone will want to connect with you.

0x1800 Characteristics you can set via client #

You can set the name. You can set service data. You can set the service UUIDs. You can not set "Device type", "Advertising type", "Flags". You may be able to set "Manufacturer data" but I don't know how. Also you probably don't have any manufacturer data.

Server Setting Dance #

1sudo killall myserver
2...
3sudo systemctl stop bluetooth
4sudo rm -rf /var/lib/bluetooth/*
5sudo vi /etc/bluetooth/main.conf
6sudo systemctl restart bluetooth
7sudo bluetoothctl discovery on
8...
9sudo myserver 

Other Tips #

Wireshark with usb dump to scrutinize the bluetooth traffic. Wireshark can tell you about all the crazy bits and pieces in the data.

Do not dick with the Privacy setting it just makes things worse.

Have another bluetooth dongle, so you can give it to a virtual machine so you can test on one machine ? Didn't work for me. I don't know why. Windows didn't like my Cambridge bluetooth dongle. I remember it did work, when I used it as the bluetooth device for the host and had internal bluetooth turned off. If I then passed it to the VM it worked. Weird.

Tried turning off the usb bluetooth controller from udev with:

# cat /etc/udev/rules.d/81-bluetooth-vm.rules 
SUBSYSTEM=="usb", ATTRS{idVendor}=="0a12", ATTRS{idProduct}=="0001", ATTR{authorized}="0"