Hi Alfonso, On Fri, Jan 5, 2018 at 5:41 PM, Alfonso Acosta <alfonso.acosta@xxxxxxxxx> wrote: > Hi there, > > TL;DR: I have observed that BlueZ does some operations which incur in > extra latency when connecting to a bonded peripheral. I would like to > know if it's possible to remove those operations through configuration > or, if maintainers are open for it, provide some patches to remove > them. > > I have a BLE peripheral with a button. The button state (key pressed / > key released) is associated to a custom characteristic (i.e. it's not > HID). The state is conveyed through ATT notifications to a central > running BlueZ (5.47, using dbus gatt api) with which it’s bonded. > > In order to save battery, the peripheral is normally disconnected and > only starts advertising when the key is pressed. The central is always > attempting to connect. Once the connection is established, the > key-press in conveyed to the central as a notification (the central > calls StartNotify() as soon as a connection is established). > > For the application’s purpose, it’s critical that the notification is > recieved with the minimum latency. > > However, between the connection establishment and the notification, I > see that BlueZ does some operations which incur in extra latency. > > To guide the conversation, here is a btmon dump showing what happens > in the central right after a connection is established with the > peripheral: https://pastebin.com/tQMgwK7v > > My goal is to minimize the time between #6 and #18 > > At #7 there is an MTU exchange request, which, for this particular > peripheral is not really necessary since I know it only supports 23 > bytes. Is there a way to disable that? After reading the gatt client > initialization code, it seems that no exchange is attempted if the MTU > of the central is also 23 bytes, but I don’t know if the default MTU > is configurable. Is it? In theory the stacks does not have to hold on to the same MTU on every connection, this is important especially for devices where services can be registered dynamically, so what you are asking probably require a blacklist of devices that don't require MTU negotiation which is something hard to maintain. > At #9 and #12 there are reads for the device name and device > appearance. I have managed to disable those by lanching bluetoothd > with --noplugin=deviceinfo,gap . So, it's not an issue anymore. Again the stacks can change the name and appearance depending on the services, therefore we read this on every connection. > At #14 there is an ATT write to the CCC descriptor of the > button-status attribute, in order to enable notifications (maybe as a > consequence of invoking StartNotify() in the central). But, why is > this needed for a bonded peripheral? If I interpret the standard > properly, CCC descriptor values should be cached and restored across > connections among bonded devices (section "3.3.3.3 Client > Characteristic Configuration" "The Client Characteristic Configuration > descriptor value shall be persistent across connections for bonded > devices."). I, however, can't find a ccc file in the peripheral cache, > as described here > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt?h=5.47#n46 > . The reasons for reprograming the CCC are normally related to faulty devices which did not maintain state of CCC, and in some case when they had been flashed. > At #17 the central starts discovering the primary services. Why is > this necessary? Shouldn’t they be simply recovered from the cache? > (According to the standard "For clients that have a trusted > relationship (i.e. bond) with the server, the attribute cache is valid > across connections."). I have verified that the cache already > contained all the primary services. However, after looking at the code > (shared/gatt-client.c ) it seems primary service discovery > (bt_gatt_discover_all_primary_services()) is always invoked :S BlueZ does cache validation of the services, again this is due to faulty devices which does not indicate changes on service changed as they may have been flashed or something like that. > Finally, at #18, I get the notification from the peripheral. And here is the real explanation why we do all this, GATT/ATT notification do no share the same queue as request/response, so all of this shall not stop your peripheral to send the notification upfront regardless if there are any requests outstanding, so perhaps the problem is really the peripheral which expects the central to be quiet while it notifies? > I am happy to try to provide some patches if we agree that at least > some of these operations are not necessary and there is no way to > disable them through configuration. Except if you want to maintain database of devices with various invalid behaviors I don't think we can do much better, especially because GATT/ATT on the OSes like iOS and Android do come with drivers in a form of applications which does things in their own way we have to deal with these nuances smartly or end up reproducing the same procedures each and every app does which imo is not maintainable. > Thanks in advance, > > Alfonso Acosta > -- > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Luiz Augusto von Dentz -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html