Bluez L2CAP CoC to Android / iOS Credit based flow failing - bluetooth

I've been trying to get a connection from Android using createL2capChannel or createInsecureL2capChannel (and iOS) to a Raspberry Pi which has created a BTPROTO_L2CAP SOCK_SEQPACKET Bluetooth socket which it is accepting, running Bluez 5.50 but they are failing at the LE Credit Based Flow step.
Running WireShark with a nRF BLE sniffer I see it is failing at the LE Credit Based Connection Response with LE_PSM not supported:
Command: LE Credit Based Connection Response
Command Code: LE Credit Based Connection Response (0x15)
Command Identifier: 0x02
Command Length: 10
Destination CID: Null identifier (0x0000)
MTU: 0
MPS: 0
Initial Credits: 0
LE Result: Connection Refused - LE_PSM Not Supported (0x0002)
I've tried various PSMs: 0x1001, 0xf3, 0x25 without any difference.
I have also seen that BlueKitche BTStack works, so I know the iOS / Android code is OK.
Does anyone know how to actually configure Bluez to correctly support LE L2Cap CoC credit based flow on the Pi?

Solved thanks to the Bluez Slack channel.
I followed https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/l2test.c#n573 to get the correct settings from do_listen().

Related

Which BluetoothLE handle do I need to write on to enable notifications?

This is my first shot working with bluetooth and I'm confused about which channel I should be sending my write packet to enable notifications. I'm working with the Fitness Machine 0x1826 service and I'm trying to get the data from the 0x2AD2 characteristic, specifically the 0x0030 handle.
When I run "sudo gatttool -t random -b [MAC ADDRESS] -I --char-write-req -a 0x0030 - 0300 --listen" I get no response so I'm led to believe that I'm sending the packet to the wrong handle, as the device should be sending notifications with my actions.
Thanks for any help!
You should send your write packet to Client Characteristic Configuration Descriptor (CCCD), which has a UUID 0x2902. You first need to find the handle of that CCCD within the fitness machine service. You can find more information here:-
Reading Thermometer Data with BlueZ
Bluetooth Low Energy: listening for notifications/indications in linux
However, as ukBaz mentioned, gatttool is deprecated so you should look into using bluetoothctl instead. More information on using bluetoothctl as a gatt client is found here:-
bluetoothctl write on descriptor to enable notification
Using acquire-write and acquire-notify in bluetoothctl

Connecting to BT LE device using org.bluez.Adapter.CreateDevice fails with org.bluez.Error.Failed: Operation canceled Error

I'm trying to set up a connection to a Bluetooth 4.0 LE device on Linux using the BlueZ 4.X DBus interface.
To test this I use the following command:
dbus-send --system --dest=org.bluez --print-reply /org/bluez/<PID of bluetoothd>/hci0 org.bluez.Adapter.CreateDevice string:<MAC of BT device>
This command seems to work most times, giving a result like:
method return sender=:1.238 -> dest=:1.262 reply_serial=2
object path "/org/bluez/9652/hci1/dev_BC_6A_29_26_C2_1C"
and enabling me to interact with the device DBus object.
However, starting from yesterday, this seems to fail very frequently returning the following error:
Error org.bluez.Error.Failed: Operation canceled
When debugging the bluetooth daemon, (using bluetoothd -n -d) I notice the following things when executing the method call:
bluetoothd[340]: src/adapter.c:create_device() BC:6A:29:26:C2:1C
bluetoothd[340]: src/adapter.c:adapter_create_device() BC:6A:29:26:C2:1C
bluetoothd[340]: src/device.c:device_create() Creating device /org/bluez/340/hci0/dev_BC_6A_29_26_C2_1C
bluetoothd[340]: src/device.c:btd_device_ref() 0xb7ad8: ref=1
bluetoothd[340]: src/device.c:device_set_temporary() temporary 1
bluetoothd[340]: src/device.c:btd_device_ref() 0xb7ad8: ref=2
bluetoothd[340]: plugins/mgmtops.c:mgmt_event() cond 1
bluetoothd[340]: plugins/mgmtops.c:mgmt_event() Received 14 bytes from management socket
bluetoothd[340]: plugins/mgmtops.c:mgmt_connect_failed() hci0 BC:6A:29:26:C2:1C status 4
bluetoothd[340]: src/event.c:btd_event_conn_failed() status 0x04
bluetoothd[340]: src/device.c:device_remove() Removing device /org/bluez/340/hci0/dev_BC_6A_29_26_C2_1C
bluetoothd[340]: src/device.c:device_set_temporary() temporary 1
bluetoothd[340]: src/device.c:btd_device_unref() 0xb7ad8: ref=1
bluetoothd[340]: src/device.c:btd_device_unref() 0xb7ad8: ref=0
bluetoothd[340]: src/device.c:device_free() 0xb7ad8
As far as I can see, my Bluetooth dongle sends me an error event (status 4) when I try to connect to the device.
However, when I use hcitool ot gatttool to connect to the device, everything works perfectly.
I found that this happens mostly after I try to connect to the device using a different program (i.e cinnamon-settings), and cancel the connection prematurely. I also noticed this with other programs like bluetooth-properties on Angstrom.
My guess is that Bluez sends the wrong HCI commands to my bluetooth dongle in certain conditions. I think this is because the gui programs try to pair with the device instead of just connecting to it, which may cause BlueZ to think my device is a Bluetooth 2.0 device.
Thus far I seemed to be able to resolve this problem by connecting to my BT device using a gui application, waiting till it fails, and restarting my computer. However, the problem seems to reoccur occasionally, making this very painful.
I have seen this problem on systems running both BlueZ version 4.99 and 4.101.
Does anyone know how I can solve this correctly?
It seems like my predictions where more or less correct. After many hours of debugging the Bluetooth daemon I discovered that connecting to BT LE devices without a preliminary scan causes the daemon to try to connect to the device as a BR/EDR device. This is because the daemon's "internal cache" is filled with the EIR information at the time the device is discovered. If this information is not available when connecting to a LE device the CreateDevice method will fail.
A simple solution is to always make sure to discover devices before connecting to them.
The BlueZ 5 API introduction and porting guide also describes this problem, and how it is solved in BlueZ 5:
Bluetooth Low Energy essentially extended Bluetooth addresses with one extra bit, requiring one to always know whether an address is “random” or “public”. This caused issues with the BlueZ 4 API where the address was given to BlueZ in the CreateDevice and CreatePairedDevice calls. Since the parameter didn’t contain any of this extra random/public information bluetoothd had to maintain an internal cache to look up the necessary info. Another complication to the matter is that the BlueZ D-Bus API doesn’t differentiate between traditional BR/EDR devices and LE devices so there are essentially three possible address types: BR/EDR, LE public and LE random.

L2CAP connection over an HCI socket?

The usual way to access L2CAP is to create an L2CAP socket and simply call connect() on it to connect to the bluetooth device you want to access. This usually works completely fine. However, I'm trying to do this on an ARM device with Linux kernel 3.0 and there appears to be a nasty bug where you can't have multiple L2CAP connections without all of the data coming down which ever channel was created last. (ie if I connect to 2 bluetooth sensors with 2 l2cap sockets, all the notifications for both devices come through the socket open last and nothing comes on the socket open first.) However, if I set the filters right on the HCI socket I can see that the ACL data is coming through with the proper connection handles so I could get the data properly over there.
So... I'd like to change my code to utilize just the HCI socket.
My problem is, I'm not sure how (or even if it's possible). There's a "create logical link command" in HCI that seems like it would create an L2CAP connection, but the arguments make no sense to me. After I make an HCI connection over LE I get back a "connection complete event" that gives me a 2 octet "Connection_Handle". The "create logical link command" takes a 1 octet "Physical_Link_Handle" though.
The "create logic link command" is for AMP controllers and has nothing to do with L2CAP. With LE you automatically have a "connection" through the fixed channels and can simply send ATT commands as ACL packets on CID 4. The ACL packets make use of the connection handle returned fro the HCI LE connection event.
(answer courtesy someone on the #bluez IRC channel; I don't recall who)
In BLE, whenever you establish a connection, the L2CAP is ready to be used.
You don't need to connect or anything else. Once you receive the LE Connection Complete Event, you are ready to go and you may start communicating through L2CAP.
The other commands and data you mention are not LE, they are only for BR/EDR.

HID Connection to a remote device without SDP record

To connect a HID profile to a mouse/keyboard, HID_CONTROL and HID_INTERUPT channel with psm 17 and 19 needs to be connected. We find information using SDP record for the HID and then we establish a L2CAP connection to connect on the channels.
Is there any utility in bluez which can help me in connecting a input device. My keybaord/mouse does not support SDP record so when i use dbus signals(connect to a input device), it fails.
Are there any libraries provided within bluez with which i can connect to a device using BD_ADDR and PSM numbers without quering for device via SDP
Its possible using HIDD utility available, though hidd utility also does SDP and then connects, i tweeked the code with removing of code for SDP search, after that it did connect on control and interrupt channels. As my peer device was capable of PSM 17 and 19, it did accepted HID connection

No audio through the bluetooth headset

When i am connecting my phone to any handsfree device , the Voice is
not coming to the hands free device, when call is accepted using
handset/hands free.
The headset was paired and connected to the handset. Then accepted a
call. The voise was not coming in headset.
When i extracted the airlog i could find that the downlink( headset to
handset) is working fine.
But the uplink (phone to headset) is not sending the data over the sco
link.
Please anyone tell me the reason of this. When i checked the logs i
could see that the sco connection establishment was all proper.

Resources