 I guess we can start, so my name is Shimon Yand and I will present you how to do Bluetooth on Linux, Bluetooth low-energy specifically. So what we will talk, I will introduce myself, then I will do a short recap of what Bluetooth low energy actually is, then I will move to a stag architecture, how it's split between Kernar and Unespace, then we will, I will present you the way to do basic things with Bluetooth low-energy using D-Bus APIs like scanning, advertising, pairing, so on. Then I will present you the GAT API that was recently promoted to a stable APIs, so this, you know, that was a big thing, and a bit about connection to channels and six low-pounds. And then a few tips and tricks how you can customize Bluetooth stag on Linux a bit more, and some thoughts about future work. Okay, so about me, I'm a software engineer. I work with Linux and Android platforms for nine years now, and I'm primarily focused on local connectivity things like Bluetooth NFC. I do contribute to open source in my both work time and in free time, mostly to Bluezy, some Linux kernel work and recently I'm working on Zephyr. Last year I co-founded a company named Codeco and we provide consulting for other companies with Bluetooth, Linux, Android, embedded software and so on. Okay, so Bluetooth low energy. The technology was introduced in 2010 with the presentation of Core Specification 4.0. It is a short-range technology, about 100 meters top. It operates on IMS, a 2.4 GHz band. It's designed for low power use cases, and applications are typically implemented as profiles that use GAT, Generic Attribute Protocol. In Core Specification 4.1 and 4.2 there were further improvements to low energy. This includes at least secure connections. So the key generation is now done with the elliptic curve crypto and connection into channels. Okay, so what is supported by Linux? Basically Core Specification 4.2. This includes all the roles like central privacy observer broadcaster and privacy feature, which means that you are using randomized addresses so that nobody can track your device. Security manager is supported, both legacy pairing, secure connections for LE and BRDR, and cross transfer pairing. Generic Attribute Profile, L2CAP connection into channels are provided by Kernel as an L2CAP socket. Six low plan, hit over GAT is supported. You can have multiple adapters. So how the stack architecture looks like? It's basically split between Kernel and user space component. Kernel is implementing most of the GAP profiles. So it handles scanning, connecting, pairing, and so on. It abstracts the hardware for you. So whatever chip you have, if you have a running driver, upper liars don't need to care about it. If it's USB, UART base, or all that type of connection. Security manager is implemented inside Kernel, and that's quite important. And it provides an L2CAP socket that user space can use. On the user space side, we have a Bluetooth D. This is a central daemon that provides high-level APIs over D-Bus that the application can use. It implements GAP, basically it uses what Kernel provides and provides it to D-Bus. ATT and GAT are implemented in user space. So this is done in daemon. It provides storage, so it will save keys, cache the GAT databases, and so on for you. And it is extendable with plugins if needed. On top of this daemon, it provides a D-Bus interface. So agents or user interface or other kind of applications should be using this D-Bus interface. Okay, so what is exactly done in Kernel? As mentioned, GAP L2CAP security manager, so pairing is done by the kernel for user space. And for control, we have a management interface that basically allows user space to control what kernel is doing with your adapter without very low-level details of HCI interfaces. And Bluetooth D, central daemon, as mentioned, D-Bus interface, it really, really reduces the exposure to low-level details of the technology for applications. And it handles persistent storage. Extendable with plugins, okay, so NERD plugin, that one is, well, that one implements a handover interface that is required by NERD so you can get out of band pairing using NFC. And this is a bit star here because it only supports basic right now, so it's still not implemented for LE, but eventually it will be. And there are legacy GAT plugins that predates the D-Bus generic GAT API. Those are currently deprecated by default, so you actually need to explicitly enable them when you build Bluetooth D if you would like to use those legacy interfaces that were provided. But you really shouldn't. From the tools perspective, we have a Bluetooth control command line. This is a pretty nifty command line client that allows you to register agent, do the pairing, scanning, query GAT because it implements GAT D-Bus API. For monitoring, we have a bitmon that provides you tracing for HCI so you can actually see what's going on between host and controller. And there are some other command line tools which are not installed but are useful for development of Bluetooth technology like to some tests, some tools for testing lower protocols, and so on. Those are usually placed in tools or test folder in Blu-Z code. Okay, so the management interface I mentioned, that was introduced in kernel 3.4 and it basically replace a raw HCI access that user space used to have to the controller with a new interface that provides a generic access profile functionality. So you can configure your control with this, you can do scanning, pairing and so on, but you don't need to use a raw HCI command so it abstracts this into more use cases. And this interface is required by Blu-Z5 user space. So if you really think about doing low energy on Linux, you should be using Blu-Z5. Blu-Z4 is deprecated for a few years now and you really shouldn't be using that. The interface is documented in Blu-Z source codes and there is a testing tool, BT management, that can actually issue commands directly to kernel and see the events that comes back. Okay, so Blu-Z as a Bluetooth demon provides a D-Bus API and this is the API that most of the applications should actually use. So it uses a standard object manager and properties interfaces that are standardized one by free desktop org. So if you have bindings for your language, which you use for your application that actually implement this, like Python for example, using D-Bus APIs from Blu-Z is really, really simple. So local adapters and remote devices are presented on D-Bus as an object with standardized paths. So you get org, Blu-Z, ACI, zero, one, whatever number of adapters you have and devices are, when they are discovered, they are hierarchically placed under the adapter that actually sold them. Then on those objects you get interfaces that you can call methods and set properties. Those with Blu-Z5, those are those are versioned. So what it means is that if we ever need to really change interface in an incompatible way, there will be a new number, a new version of that interface and the old one will be supported at least for one version bug so that there is a great period of time for applications to actually adjust. Let's hope that it won't be needed, but this is lesson learned from Blu-Z4. And if the device provides functionality like connectable gap or something like this, then more interfaces will be showing up on those objects. Another type of D-Bus interaction that Blu-Z requires is kind of manager and agent style APIs. This basically means that Blu-Z provides a manager interface that external application can register its own agent that will be called when Blu2D, for example, needs to interact with user. Since Blu2D doesn't have any input output capabilities, it just calls the agent. And with the release of Blu-Z5.42, which happens a couple of weeks ago, the gap D-Bus interface is finally declared stable. So it's no longer needed to provide an extra switch when you run Blu2D to be able to use this interface. Okay, so what you can do with D-Bus APIs? You can control adapter like powering on, setting connectable, discoverable, configuring name and so on. You can start a discovery session so that you can discover remote devices. It allows for connection management, so connecting, disconnecting. It provides a high-level API for pairing. So all you need to care when you pair is to only interact with user, nothing else. You don't need to care about low-level details. So basic interfaces, adapter one is for controlling adapter. That's on the adapter object. Device one is for device control. This is on objects that represent remote devices. And agent one interface, it's the interface that is implemented by external agent that is used by Blu-Z to actually interact with user for, let's say, confirming a pass key when you pair two devices. So I will now go through the basic functionality that you can do with Blu2D. So let's start with scanning. So to discover remote devices, of course, you need to first power on your adapter. And after that on interface adapter one, you get start and stop discovery methods, very simple, no parameters. You start discovery, you wait for devices to show up, you stop discovery. By default, this is doing interleave type of discovery. So if your device is dual mode, it will do both basic rate and early discovery. If you are having only control, it will do only early discovery. But sometime ago, we added a method called setDiscoveryFilter. And this method can be used by applications to actually do some tuning on what kind of discovery application are interested in. So you can do filtering based on UID supported by devices or RSSI or PUT loss type of transport. So you can choose, even if your contrary supports two type of technologies, so classic Blu2D and early Blu2D, you can only do early discovery when you configure this. Multiple applications can actually set their own filters. So internally, this is matched to one that fits the needs of all the applications. So this is important because if you are expecting to run more than one application that have different requirements, you need to filter the devices that shows up during the discovery by your own. For example, we have one application that do early scan and another one that will do internally scan. The early application will also get signals about new devices from a classic Blu2D discovery. So you want to make sure that you take care of that in your applications. And when devices are discovered, new objects with device one interface start to show up on the debas and using object manager interface, you can catch them and start interacting with them. Okay, so that was scanning, so central. Now advertising, so if you want to be a peripheral, Blu2D provides interface so you can actually register your own advertising instance. Multiple advertising instance will be supported. I think it's not supported yet. There are some limitations. But the interface is ready and it will be supported. So what you need to do to start advertising is that you create the object with early advertisement one interface in your application that implements the implements the required properties. And with those properties you specify what type of advertising you want. For example, if you want to connect table advertising or you want to be a beacon, what kind of data should be included in advertising and so on. Then Blu2D will prepare advertising data based on this flux and start advertising. So when you have this object ready in your application, you just register it with early advertising manager and it will start advertising. If your application crashes or exits without cleaning, Blu2D actually tracks this so it will stop advertising for you even if you don't call unregistered advertising. Currently there is no support for configuring responses with this interface, so you can only use advertising data. But it will come eventually. This API is documented in doc advertising API file in Blu2D sources. So if you need to check what options are available, you can check there. Okay, so pairing. Once you discover the devices, we want to connect to it and issue security. So for user interaction, Blu2D relies on agents as mentioned before. So this can be user interface, but it can also be if your device doesn't have a screen or something, but you have some sort of internal policy you want to enforce. This can be also used for this, like allowing specific devices to connect or something like this. So using agent manager one API using register agent method, you register your local agent that will provide the information about local capability. This is something I want to emphasize because there is some confusion if you look for forums on Google. So you provide your own local capabilities. What IO capabilities are your devices capable of? So if you have screen, you use display. If you have keyboard, you use keyboard only and so on. And when the pairing starts, Blu2D and Kernel will figure out what's the best pairing method for you. Each application, if you have multiple applications, can register on agent. And this agent will be used for pairing that was initiated by this application only. If application didn't register any agent, the default agent can be used for pairing. And the default agent is also used for incoming pairing requests. So if you are peripheral and you get central connected and it will start pairing, the default agent will be used. The figure on the right shows basically the call chain of what is needed to pair with remote device. So you register your agent. You set your discovery filter with UIDs, for example. You start discovery. When devices show up, you stop discovery. This is rather important since you will have better antenna time for pairing and connecting. And on device object, on device one interface, you call pair. And that's it. Blu2D will start pairing. If there is a need for a user interaction because you, for example, need to confirm a pass key if it matches, it will issue a call to registered agent. And when pairing is complete, the pair command will return. Okay, so we managed to pair with device. And now we want to do some application on top of this. So we need to use GAT. As mentioned before, internal plugins that was available before are now deprecated. So you should not use, I know there was a heart rate plug-in, a second speed and a few others that provide a custom API. So now you should be using GAT. The interface is stable. If there will be changes, those will be in a backward compatible manner. Local and remote services are represented with the same D-Bus APIs. So we have three types of objects that represent service, characteristics, and descriptors. And on the right, you can see a screenshot from Defeat that actually shows a remote device hierarchy of objects. So those basically represent a remote device database, GAT database. So when Bluetooth connects to device, it will start doing GAT discovery. So those objects will start showing up on D-Bus. And if your application needs to wait for a full discovery to complete, it should wait for a service resolve property change to true. That means discovery is done, service discovery on that device. Okay, so that was for remote. If you want to expose your own GAT database to remote devices, you have to use GAT manager API and register your own application. Basically what you do, you create a hierarchy of D-Bus objects in your application with D-Bus object manager in the route that will allow Bluetooth V to examine what kind of GAT database should be created, what properties you want, and so on. And then you register your application using register application on GAT manager. And that's it. For a local profile, that means that creates a GAT server. And if you want Bluetooth D to automatically connect to devices that actually support specific UIDs, for example, you also need to create an object that implements GAT profile in this hierarchy, GAT profile interface. And then if Bluetooth D sees that this interface is present, it will add matching devices to auto connect list. This is quite nice because it uses passive scanning, so it's conserved battery. It's not doing active scan like when you do with discovery session. So typically this is for devices that you already know. So you pair it with your heart rate monitor and whenever it starts advertising, you want to connect to it. This should be used for this. And objects should not be removed. Well, I'm not sure it will happen if they are removed, but if you remove the object, the database will not change. So this is, if you want to change database, you should unregister and register again your application. Okay, so one exception from what I mentioned is heat over GAT. This is actually implemented internally for inside Bluetooth D with Hock plug-in. This is for mice and keyboards over using Bluetooth low energy. So this plug-in claims the heat device and those characteristics won't be visible on the bus. So if you pair it to your mouse, you will not see a heat over GAT interface over D-bus. Instead, Bluetooth D will claim this service and if the U-heat interface is enabled in kernel, it will connect your mouse, create a virtual device. You should see something like that in kernel and you can start using your mouse or keyboard. So that's one exception. So this is basically done to make it very easy and similar to classic heat devices. So you pair your devices connected, you can start using your mouse and it works pretty well. Privacy support. Since in Bluetooth low energy, whenever device wants to connect, it needs to start advertising. So other devices can scan it so that you can be tracked. So Bluetooth D can be configured to, sorry, kernel can be configured to use something called resolvable private address, which means that after pairing your device will be using random addresses that match your identity key that was exchanged during pairing. So only devices that you are paired with can track you. So they knew that, okay, this random address is really that device. If the address changes and it matched the identity key, it will be known that it's the same device, although it's using a different address. This prevents tracking. So if you move around with your heart rate monitor that doesn't use this, everybody can track you where you go around. If device is using this privacy, then only bonded devices can actually track you, identify you. Okay, so this is supported in kernel. It's not yet supported in Bluetooth D and by it I mean local privacy so that Linux box is using random addresses. Because if remote device is using random addresses, this is handled internally by Bluetooth D and your application doesn't need to care about this. There are patches pending on mailing list, waiting for review. Marcel, that will provide a Bluetooth D way to actually generate and store identity key and enable requested privacy mode for your device. I hope it will be integrated before next release. So then all you need to do to enable privacy is to set a configuration option in my.com file and restart Bluetooth D and that's it. Okay, early connection in the channel is that was added in kernel 3.14. Very easy to use. You can use standard socket interface. You create L2CAP socket with type of address set to LE and provide PSM number. There's one neat peek here is that currently you cannot obtain address type from D bus interface. So you need to guess whenever your remote device is using public address or random address. But this will be sorted out eventually. I'm not sure yet if it will be profile one interface that provides abstracted connection for connection in the channel or we just provide address type on D bus as a property on some interface. Okay, six loop on. It's available since 3.16. There is no stable interface yet. So you need to use debug.fs to play with it. But it's pretty easy to use. You just mod probe Bluetooth six loop on module. You enable six loop on and debug.fs and to connect you, you have to connect to a six loop on control file and network BT0 interface is created and you can start bringing your device. There were some patches for proposing management interface API that would allow to promote this interface to stable but they were never finished. So it's still pending. Okay, so that was all if you want to use Bluetooth D. So this should cover most of the typical use cases like you want to connect to heart rate, you want to be a heart rate monitor, you want to implement some standard profiles. But sometimes Bluetooth D is either too big or too generic for your application. One reason might be that for some reason you don't want or cannot have a D bus on your system. So then you are not able to use Bluetooth D. But Bluesy source code is nicely split into internal libraries and shared code that is used and then D bus interfaces are separated from that. So you can actually use those libraries for your own applications. Libraries placed in SRC shared folder are LGPL based licensed. So as long as you comply to this license, you can use them. It's not GPL, it's LGPL. Those are C. Libraries provide C APIs that is really, really nice to use. Easy to integrate and you get the all the functionality you need to actually implement your custom C, let's say demon or something like that. So you get the library for accessing management that will queue the events and comments for you and so on. ATT is implemented as a shared library that you just provide connected file descriptor and you get ATT working. Got crypto for if you need to do some cryptographic stuff on your application. There are libraries that are used advertising gap for scanning and so on. Well, of course, those are internal libraries. They are isolated, but those are still internal. So there's no guarantees that the IPs will change, but based on my experience, they don't change that often. And even if they change, those are like very easy things to integrate in application. There are some examples of how to use this besides Bluetooth decode. So in Peripheral folder, there is a sample also a GPA license that created a simple peripheral application using those shared libraries, not the GAT API. And for applications, when you need really, really low level direct access to HCI interface, I would recommend using a user channel API instead of raw HCI socket interface. This basically gives your application exclusive access to controller. So the controller appears to disappear from a management interface, for example, for a Bluetooth D. So when you open this kind of user channel, you have two controllers, and when you open it for one, it will disappear from Bluetooth D. So your application has exclusive access, which means that Bluetooth D will not screw you with your application and Vesa Vesa. Your application will not do anything that could confuse kernel or Bluetooth D. So some tips for the end. Use D-Bus API whenever possible. So don't try to use some HCI hooks. There is a lot of legacy documentations in some forums or blogs that have examples that use HCI interface to access controller, for example, to enable advertising or something like this. Don't do it because it will first confuse kernel states, and eventually kernel will start to confuse your application as well. So use D-Bus API. In test folder, there are Python-based examples. Super easy to check, works nicely, easy to understand because Python bindings supports object manager interface. Don't use HCI to really use Bluetooth control that use D-Bus or BT management tool if you really need to access management interface directly. For traces, use BTmon instead of HCI dump, basically because it provides more decoding and it also can support multiple adapters, including power-up sequence of adapter, which is not possible with HCI. And HCI dump is basically deprecated and probably will be removed at some point. If you are stuck with ancient kernel because you should be using the newest kernel, the newer is the better. But if you are stuck with old kernel, which can happen, if you have some custom embedded board or things like that, you can try Linux Backport projects that allows you to backport Bluetooth subsystem from newer kernel to older kernel. We actually use this in BlueZ for Android project and it works really well. I mean, better than we expected. We basically have almost no issues related to backporting itself. If you need to do some extra configuration like change default connection parameters and so on, you can do it by assist interface. And in debug interface, you can get some extra information about your currently running controller. Okay, so Bluetooth D has a configuration file. It is not needed. If it's not present, it used, let's say, reasonable defaults. But you can place it in ETC Bluetooth main conf and customize it. If you want to contribute, join BlueZ on FreeNote. You can send mailings, patches or questions to mailing list as well. Read a hacking file before you do that. This will allow you to skip some obvious steps. If you don't follow what's hacking, the first response will be, please read hacking and follow rules that are described there. If you report a bug, use BlueZ users IRC channel or report them to Linux Bluetooth mailing list. Provide HCI traces. This is usually the first question you will get when you try to report the bug. Please show HCI traces from this session. And if logs from Bluetooth DR are required, enable debug logs. This can be done by starting Bluetooth D with minus D option. Or if you are already running, you can send a SIG user to a signal and Bluetooth D will start printing debug logs as well. What's missing? Management API for BT6. As mentioned, there was some effort a few months ago to actually propose this API. It never went in, got stale, so if someone needs this, you can pick up this work and try to propose something that actually will be accepted. Got D bus API has a limitation that it doesn't currently provide included services, so this is something for sure that will be implemented at some point. The API is specified for included services, but it's not implemented. Of course, upcoming Bluetooth 5 features when they show up and out of band pairing for early devices, but this requires interaction with nerd, NFC demon, and it's a bit bigger task to actually achieve. For some internal stuff, currently we have inside BlueZ say two types of gut. I mean, we have two libraries that implements gut and one is legacy, and it eventually going to be removed, but it didn't happen yet because some parts of some tools and some part of the demon are still using that old code. So this is something that for sure will be work on. And a few months ago, I also proposed an extension to device APIs that should improve the way Bluetooth de-handles dual mode devices. Dual mode means devices that can operate both on Ali and classic Bluetooth because there are some limitations related to choosing transport and so on. I think it was in 542 that there were some improvements in the internal code that actually tried to figure out which transport should use that should fix some problems with headphones that do advertising on Ali in the same time. So if you have problems with your boss super headsets, then try with latest Bluetooth de-handle. And the extending adapter one interfaces something. Actually, I don't remember what I wanted to say here. So yeah, that's future work. Due to limited time, not everything will happen soon. So it's a nice moment to actually try to get involved into the community if you need some of the features. We are willing to guide new commerce if needed. Okay, so that's all I had for today. If you have any questions, I think we have a few more minutes. So if there are any questions. Okay, so no questions. So thank you for attending. And you can, I will be hanging around on the corridor. So if you want to ask questions offline, then I'm all for you. Thank you.