What is the path of handling an incoming SCAN_REQ request in an the ESP32 Bluedroid stack? - bluetooth

I am trying to debug this bug https://github.com/espressif/esp-idf/issues/10660 where on some ESP32 versions, the device doesn't respond with a SCAN_RSP for incoming scan requests.
The BLE stack in use is ESP32 Bluedroid with BLE 5.0 disabled (only 4.x, I believe that 5.x is not supported on ESP32) but I am having hard time to figure out where in the source code incoming SCAN_REQ are handled https://github.com/espressif/esp-idf/tree/master/components/bt/host/bluedroid
My question is, what is the path of incoming SCAN_REQ requests in the ESP32 Bluedroid stack and where the requests are handled by sending back a SCAN_RSP. My plan is to set breakpoints and add log messages to compare a working chip version with a non working one.

You won't find it in the host part of a Bluetooth stack (for example Bluedroid). It's handled by the controller (one layer below hci).
The controller code can be found in ROM code, with some patches here https://github.com/espressif/esp-idf/tree/master/components/bt/controller (everything is closed source). The rest of the implementation is done fully in hardware, likely including the part that responds to scan requests, since there is such a strict time requirement (150 microseconds) when the response must be sent.

Related

Azure TCP segmentation and HTTP chunks

I have an Azure application that connects to a large installed base of devices. Everything has been working fine for years until today when everything has stopped working. What I think has happened is Azure is now segmenting the small (87 byte payload) message and this has exposed a bug in my TCP handler.
Does anyone know if there is a way of forcing Azure not to segment small TCP messages?
Follow up - I think this is because the HTTP message is 'chunked' and send as 2 TCP segments. There is a bug in my code that does not handle chunks which as only now surfaced.
Can I turn off chunking in Azure?
If your question is whether there is a way to prevent a HTTP response from using HTTP Chunked Transfer Encoding, then perhaps, depending on the server-side APIs you are using. Setting a Content-Length header usually suffices.
But I think your question is whether you can force Azure to buffer IP packets in a way that avoids the bug in your client, which is assuming that a single socket Read() will return a complete message. In which case, no. It may not even be within Azure's control, as any intermediate router could cause a delay in the delivery of packets, which, in turn, will cause the client's Read() to return a partial message.
I found a solution here Disable chunking in Asp.Net Core
In summary:
response.Headers["Content-Encoding"] = "identity";
response.Headers["Transfer-Encoding"] = "identity";
This seems to disable unnecessary chunking. I have no idea how

Changing the connection interval in a Bluez-based GATT-oriented application

We are currently working on an application on linux (a.o. RasPi running latest Debian Jessie) that connects to a BLE device (developed by us). This tool has evolved from cherry-picking files from the bluez (5.46) stack and adding an application layer on top. This all works quite nicely, except for the fact that connecting is incredibly slow. From the output of our tool, I understand that a truckload of messages need to be exchanged to communicate GATT services and characteristics, and each of those costs one connection interval of time. Since it is a low power device, we want the connection interval to be relatively high, and thus the high delay.
When connecting with Android BLE Scanner, I see (on the device side) that BLE Scanner manipulates the connection interval to a low value, gets all the requested data, and then sets the connection interval back to its original value. Note, btw, that neither BLE Scanner nor our Bluez-derived application take the preferred connection parameters into account.
Now I want to have our application do the same: set the connection interval to 8ms, get all info about characteristics and services, and set the connection interval back. In the Bluez stack I even find a nice function in the HCI layer for this: hci_le_conn_update.
But now the challenge: the rest of the application is built on top of the GATT functionality and even though the BLE specification defines a hierarchy between those two (with some layers in between), in code they seem absolutely independent of each other.
There are two parameters to the hci_le_conn_update function that are HCI specific: 'dd' (file descriptor to device) and 'handle' (some value that identifies the connection). The hcitool tells me that when I create a connection, the first handle is 64, so I tried with that value. For 'dd' I used hci_dev_open to get a file descriptor for the device. This worked. Sort of.
As I said before, the min/max values are not entirely taking into account. So when I set it to 6/10, I get 11 and when I set it to 6/50, I get 60. This is a bit too undeterministic for my taste, and I would prefer a function that directly changes the connection interval instead of giving a range that is mostly ignored anyway. Also the fact that I have to use a hardcoded magic number 64 gives me a bad itch. I can actually control the connection interval on the embedded device's side, but I want the control at the side of the client application.
The goal is to update the connection interval in a Bluez-GATT-based application. Within certain limits, I do not mind that much how I get there. Any suggestions?
In the official dbus API, there is no method to change connection parameters. (See https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt and https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt). The key is therefore to send the Connection Parameter Update Request from the peripheral side. You can of course experiment with sending a raw hci command but that is a bit "hacky" and has no guarantees to not mess up the BlueZ daemon.
If you would like to discuss the features of BlueZ such as an connection parameter update request api, you should do that on the BlueZ mailing list (http://www.bluez.org/contact/) rather than here.

How to handle DISABLE_NOTIFICATION_VALUE?

If a Bluetooth server has a notifying characteristic and the remote client writes to the descriptor of this characteristic the value DISABLE_NOTIFICATION_VALUE , then how must the server cope with this descriptor write request?
Must the server software refrain from calling any GattServer.notifyCharacteristicChanged() , or will the Bluetooth stack prevent sending notifications to the client after GattServer.notifyCharacteristicChanged() has been called by the server software?
The server should only send a notification over the air if the corresponding notification bit in the descriptor is 1. Whether the application software is the one that should do this check or the bluetooth stack does this for you is implementation-specific. I guess most bluetooth stacks do not do this for you.
If you wonder about Android, I can't see clear documentation whether this is done or not, so you'd better do it yourself.

BLE Pairing from microcontroller

As part of my requirement, we need to have paring connection between microcontroller (Cortox M3) and Mobile or Pc. We are using Alpwise stack for our purpose. My problem is with the controller configurations, not with the mobile, because without paring i am able to work with it.
Where should i the API "BLESMP_InitiatePairing" api. Presently i am calling the api inside GAP_callback function, inside BLEGAP_EVENT_CONNECTED.
Is this a correct location to call at this API, because if i call over here, control goes to BLEEVENT_PAIRING_COMPLETE (returning SMERROR_UNKNOWREASON) then it goes into BLEEVENT_PAIRING_REQUEST then once again it goes into
BLEEVENT_PAIRING_COMPLETE (returning SMERROR_UNKNOWREASON). Whereas when i call "BLESMP_InitiatePairing" api, it returns me with success message
(You listed the core-bluetooth tag, so I'm assuming you want to use iOS.)
I don't know the specific stack you are using. However, if you are developing an LE peripheral and want to connect with an iOS device as central, it is sufficient to reply to a read / write request with an InsufficientAuthentication error code. iOS will then initiate pairing from its side.
More details on this process can be found in the Bluetooth Accessory Design Guidelines for Apple Products Section 3.9.

Multiple BLE Connections using Linux and Bluez 5.0

I am currently attempting to connect to multiple BLE devices using BlueZ 5.0 and Linux. I have one host BLE adapter and I have modified the gatttool to connect and perform this function. If I run an instance of the modified gatttool, I successfully connect and receive notification data from the BLE device. If I run another instance of the modified gatttool and connect to another BLE device, this application starts receiving notification data from both BLE devices and the initial application no longer receives any data. I believe this is due to the socket setup, where both applications are configuring their sockets to the same address and PSM (the newest instance receives the data whereas the other is starved). Is there a way to prevent this condition? Ideally, I want one application to connect to multiple devices. I assume that the application can only have one socket for the reason that multiple sockets will have the same issue as the multiple instances above. My BLE device is a TI CC2540 keyfob acting as a heartrate monitor.
I started an answer so I could have more space...
I'm using a combination of Python and C to get my code to work, so my "code" may look funny because it could be from either. Also, I used Bluez 4 as the 5 didn't support the kernel I was using. Let me know if there's an issue and I can clarify.
It seems like there's several ways of doing things, but I ended up opening separate sockets for different tasks. You can open a single socket and then set the socket options to take filtering off and you should get all the packets in one place. However, that was my initial way of doing it and I found that my connections would die within seconds.
To scan for connections I opened a socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI) then did a bind on device 0. (there's a function called hci_get_route to get an available device number) You can then call hci_le_set_scan_parameters to set options, setsockopt(SOL_HCI, HCI_FILTER, filter) to just get LE scan events, and then called hci_le_set_scan_enable to turn on scanning.
Each device connection was made with a socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) which you then tell to connect to a particular device by calling connect on the socket with a struct sockaddr_l2 that has the particular device address in it. On that socket you should only get packets from that device. (one caveat... I found that my dongle wouldn't allow a connection while active scanning was taking place.. I had to temporarily shut it off just before connecting and then turn it back on. Otherwise I got a BUSY error from errno)
After saying all that, though... I think the way you're supposed to do everything in Bluez 5 is to use DBUS. Unfortunately that wasn't really an option for what I was doing. The functions I mentioned are in the shared lib that apparently isn't installed by default in 5 (you have to explicitly ask for it to be installed with configure). They stopped installing the shared lib by default because they wanted to encourage people to use DBUS instead.
WE have combined the code from hcitool and gatttool. The code works well for 2 device (scan, hci_le_create_conn and gatt_connect). I believe there is no limitation on the number of devices used.
1 Start cmd_lescan (from hcitool.c)
2.For each device scanned -
cmd_lecc (from hcitool.c)
gatt_connect (from gatttool.c)
This way one process can manage multiple BLE device. We do not have to turn OFF the scanning, just have ignore non advertisement messages:
if (meta->subevent != 0x02)
continue;
Thanks and looking forward to comments.

Resources