Re: defining a BLE GATT server
You're right, maybe I'm caught on the callback interface because that is how it is implemented now, but in the end there's always a packet you process. I still wonder if also having L2CAP in kernel would be better since it deals with multiple connection handling, packet fragmentation and so on (to me it is like TCP, but maybe I'm reading it wrong). Anyway, as I'm still finishing the link layer and I wouldn't want to get into this before completing that. But it would be cool if you or someone else would be willing to look into this further, I could then contribute to that effort. I guess I will hack something locally to make a GATT server until we devise a clean way to do it. Best, Matias On Mon, Aug 24, 2020, at 01:06, Brennan Ashton wrote: > On Sun, Aug 23, 2020, 8:45 PM Matias N. wrote: > > > Hi Brennan, > > > > Yes, as I understand the host layer is actually from (early?) Zephyr code. > > > > The way you suggest it should be done sounds very reasonable. However I > > wonder if this is > > always the right approach. Right now the HCI layer is using work queues to > > handle > > communication with different priorities. So I would guess that it would be > > best to expose at > > L2CAP level. From the looks of it, GATT is more like a library with > > convenience functions, but > > there are still many callbacks so the problem would be the same as now I > > think. Are callbacks > > abstracted via read/write on sockets in this case? Or what would be the > > simplest way to > > handle callbacks from OS to application? I can only think of POSIX > > signals, but that feels quite > > limited. > > > I'm not sure I follow. Normally the kennel would expose the HCI socket and > the you would issue a read on the socket to identify events to act on. That > would include an action like reading a GATT entry. With bluez there is a > user space daemon that does just that and then applications register via > dbus. Here it would probably be less important to have the daemon since > would likely only have a single application doing Bluetooth so you could > just make the GATT a library. > > The Bluez daemon also makes use of file descriptors for managing events if > you want to use that instead of the dbus API. So I suppose that could be > used here as well I just don't see why we have GATT in the kernel. That > seems like the wrong thing. > > > BlueZ is also doing some things to handle some HCI events in the kernel you > can fully unregister the device from connection management by requesting a > BTUSER_CHAN which Zypher once again also supports in POSIX mode. > > Reinventing this abstraction is probably not in our best interest. > > > --Brennan > > > >
Re: defining a BLE GATT server
You're right, maybe I'm caught on the callback interface because that is how it is implemented now, but in the end there's always a packet you process. I still wonder if also having L2CAP in kernel would be better since it deals with multiple connection handling, packet fragmentation and so on (to me it is like TCP, but maybe I'm reading it wrong). One of my longer term goals with BLE was to implement 6LoWPAN on top of L2CAP. There are several implementations like that out there (although it does seem redundant). In order to do that L2CAP would need to be inside the OS.
Re: defining a BLE GATT server
Also, I understand that Xiaomi intends to replace the entire Bluetooth stack with a newer BT 5.0 stack. I don't know if that is still a plan of record or not, but you probably should coordinate Bluetooth architectural changes with Xiao Xiang in any event.
Re: defining a BLE GATT server
Thanks for the heads up. Would be good to get Xiao Xiang's input on this then. Maybe he already encountered this issue. For now I'm working on the Link Layer, looking at 4.0 spec as a start. If the host layer is reimplemented for 5.0 I understand it shouldn't invalidate the LL in principle. But for any change on the host layer I would like to know if there are plans or work in progress. On Mon, Aug 24, 2020, at 11:47, Gregory Nutt wrote: > Also, I understand that Xiaomi intends to replace the entire Bluetooth > stack with a newer BT 5.0 stack. I don't know if that is still a plan > of record or not, but you probably should coordinate Bluetooth > architectural changes with Xiao Xiang in any event. >
Re: defining a BLE GATT server
Thanks for the heads up. Would be good to get Xiao Xiang's input on this then. Maybe he already encountered this issue. You should also be aware of the wireless architectural principles of https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629397 Some of the things you have speculated about would be contrary to these principles. The basic wireless rules are: 1. Network sockets are used to communicate with complex wireless networks (like bluetooth) 2. Character drivers should be avoided 3. Network interfaces must/should be compatible with corresponding Linux interfaces. I think if there are features that you want to implement, you might first want to look at how those features are implemented in Linux. That would be the correct way to proceed.
Re: defining a BLE GATT server
On Mon, Aug 24, 2020 at 12:34 PM Gregory Nutt wrote: > > Some of the things you have speculated about would be contrary to these > principles. The basic wireless rules are: > > 1. Network sockets are used to communicate with complex wireless > networks (like bluetooth) > > 2. Character drivers should be avoided > > 3. Network interfaces must/should be compatible with corresponding Linux > interfaces. > > I think if there are features that you want to implement, you might > first want to look at how those features are implemented in Linux. That > would be the correct way to proceed. I fully agree with this. AF_BLUETOOTH is already in place, but it only implements "BTPROTO_L2CAP" all of the GATT and advertising/scanning related functionality is implemented over "BTPROTO_HCI" fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI); addr.hci_family = AF_BLUETOOTH; addr.hci_dev = dev_id; addr.hci_channel = HCI_CHANNEL_RAW; HCI event filters are then controlled via socket options with SOL_HCI and HCI_FILTER Most of these are defined in the NuttX bluetooth stack, but they have not been implemented. If you bind using HCI_CHANNEL_RAW and not the HCI_CHANNEL_USER the Linux kernel will take care of some of the GAP related actions, there is also a management socket that is exposed as well. I see that there is an ioctl interface for the bluetooth network driver, but I don't think this is really a good idea. GATT is really something that should be handled in userspace. I finally have a few weeks off, so I can see about making some HCI socket progress, going to take a bit to get hardware setup for it though. --Brennan
Re: defining a BLE GATT server
On 8/24/2020 2:20 PM, Brennan Ashton wrote: On Mon, Aug 24, 2020 at 12:34 PM Gregory Nutt wrote: Some of the things you have speculated about would be contrary to these principles. The basic wireless rules are: 1. Network sockets are used to communicate with complex wireless networks (like bluetooth) 2. Character drivers should be avoided 3. Network interfaces must/should be compatible with corresponding Linux interfaces. I think if there are features that you want to implement, you might first want to look at how those features are implemented in Linux. That would be the correct way to proceed. I fully agree with this. AF_BLUETOOTH is already in place, but it only implements "BTPROTO_L2CAP" all of the GATT and advertising/scanning related functionality is implemented over "BTPROTO_HCI" fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI); addr.hci_family = AF_BLUETOOTH; addr.hci_dev = dev_id; addr.hci_channel = HCI_CHANNEL_RAW; HCI event filters are then controlled via socket options with SOL_HCI and HCI_FILTER Most of these are defined in the NuttX bluetooth stack, but they have not been implemented. If you bind using HCI_CHANNEL_RAW and not the HCI_CHANNEL_USER the Linux kernel will take care of some of the GAP related actions, there is also a management socket that is exposed as well. I see that there is an ioctl interface for the bluetooth network driver, but I don't think this is really a good idea. GATT is really something that should be handled in userspace. I finally have a few weeks off, so I can see about making some HCI socket progress, going to take a bit to get hardware setup for it though. --Brennan I have been puzzling through the Goobledegook GATT server (GGK, https://github.com/moovel/gatt-server fork). It uses the Bluez D-Bus interface. It is GPLv3 so not a candidate for porting. And also not much use for understanding APIs since the OS interface is hidden inside of the Bluez D-Bus interface (https://core.docs.ubuntu.com/en/stacks/bluetooth/bluez/docs/reference/dbus-api) I think there are several of us who would help with clean Linux-work-alike Bluetooth support.
Re: defining a BLE GATT server
> I see that there is an ioctl interface for the bluetooth network > driver, but I don't think this is really a good idea. GATT is really > something that should be handled in userspace. Yes, I've been using what exists at the host layer in NuttX, via the btsak application. While it opens a socket specifying "L2CAP", a lot of functionality is implemented via ioctl calls which use gatt for example. > I finally have a few weeks off, so I can see about making some HCI > socket progress, going to take a bit to get hardware setup for it > though. Cool! I can help test this. I have two nrf52832 boards I'm using: Sparkfun breakout, used as sniffer using raccoon firmware and MakerDiary MDK as main dev platform. The MDK is quite good, has embedded debugger + uart via USB (using DAPLINK). BTW, I would like to CC Xiang to have him in the loop but I can't find his email address (only GitHub handle). Can you copy him? Best, Matias
Re: defining a BLE GATT server
> I have been puzzling through the Goobledegook GATT server (GGK, > https://github.com/moovel/gatt-server fork). It uses the Bluez D-Bus > interface. It is GPLv3 so not a candidate for porting. And also not > much use for understanding APIs since the OS interface is hidden inside > of the Bluez D-Bus interface > (https://core.docs.ubuntu.com/en/stacks/bluetooth/bluez/docs/reference/dbus-api) I think all the GATT logic in NuttX is very complete so it would be better to use that as a base. Right now it kind of looks like a library already so I think it would mostly have to be reworked to interface to the kernel part of the host layer via L2CAP sockets. > I think there are several of us who would help with clean > Linux-work-alike Bluetooth support. Great! As I mentioned, I can help test. I'm actually a bit blocked right now to continue work on the Link Layer since I'm missing something generating useful traffic at GATT level. Best, Matias
Re: defining a BLE GATT server
On Mon, Aug 24, 2020 at 1:40 PM Matias N. wrote: > > > > I have been puzzling through the Goobledegook GATT server (GGK, > > https://github.com/moovel/gatt-server fork). It uses the Bluez D-Bus > > interface. It is GPLv3 so not a candidate for porting. And also not > > much use for understanding APIs since the OS interface is hidden inside > > of the Bluez D-Bus interface > > (https://core.docs.ubuntu.com/en/stacks/bluetooth/bluez/docs/reference/dbus-api) Yeah I am very familiar with this having shipped devices on top of the dbus API. The dbus API is provided by bluetoothd which intern is using the kernel socket interface. Goobledegook is not really providing us anything here since the underlying bindings between sockets and GATT are still in bluetoothd. > > I think all the GATT logic in NuttX is very complete so it would be better to > use that as a base. > Right now it kind of looks like a library already so I think it would mostly > have to be reworked > to interface to the kernel part of the host layer via L2CAP sockets I think you are missing something here, the interface that needs to be supported is not L2CAP, it is HCI. You would need to write a binding between the link layer and HCI. Long as your device implements the interfaces here wireless/bluetooth/bt_hcicore.c we should already be in a great place. --Brennan
Re: defining a BLE GATT server
I have been puzzling through the Goobledegook GATT server (GGK, https://github.com/moovel/gatt-server fork). It uses the Bluez D-Bus interface. It is GPLv3 so not a candidate for porting. And also not much use for understanding APIs since the OS interface is hidden inside of the Bluez D-Bus interface (https://core.docs.ubuntu.com/en/stacks/bluetooth/bluez/docs/reference/dbus-api) Yeah I am very familiar with this having shipped devices on top of the dbus API. The dbus API is provided by bluetoothd which intern is using the kernel socket interface. Goobledegook is not really providing us anything here since the underlying bindings between sockets and GATT are still in bluetoothd. So would adding the appropriate socket types and ioctls then re-implementing the d-bus API make a reasonable portability layer? That could be a pretty well defined job.
Re: defining a BLE GATT server
On Mon, Aug 24, 2020 at 2:25 PM Gregory Nutt wrote: > > >>> I have been puzzling through the Goobledegook GATT server (GGK, > >>> https://github.com/moovel/gatt-server fork). It uses the Bluez D-Bus > >>> interface. It is GPLv3 so not a candidate for porting. And also not > >>> much use for understanding APIs since the OS interface is hidden inside > >>> of the Bluez D-Bus interface > >>> (https://core.docs.ubuntu.com/en/stacks/bluetooth/bluez/docs/reference/dbus-api) > > Yeah I am very familiar with this having shipped devices on top of the > > dbus API. The dbus API is provided by bluetoothd which intern is > > using the kernel socket interface. Goobledegook is not really > > providing us anything here since the underlying bindings between > > sockets and GATT are still in bluetoothd. > So would adding the appropriate socket types and ioctls then > re-implementing the d-bus API make a reasonable portability layer? That > could be a pretty well defined job. You are going to hate dbus :) Honestly it is designed to be a system wide message bus for desktop/server software and defines even a wire message format that supports things like introspection. I think that is wrong for a small embedded system. That leaves the question of what should be used for IPC for the GATT server daemon. I suspect we could get far using event file descriptors, but also just having a library where a single application owns the GATT server is probably fine. The dbus service is nice because I can write a standalone application that provides the BAT service for showing battery life, and then have another application that broadcasts RPMs from a cadence sensor. --Brennan
Re: defining a BLE GATT server
> I think you are missing something here, the interface that needs to be > supported is not L2CAP, it is HCI. So you suggest to implement L2CAP in userspace? I'm confused when you mention that there's a L2CAP socket already and HCI socket needs to be added. Just to be clear, I have this stack in mind: So to me HCI is the protocol that L2CAP speaks to the LL and L2CAP sits on top. For that reason my understanding was that what was needed is to provide L2CAP to userspace via sockets. > > You would need to write a binding between the link layer and HCI. > Long as your device implements the interfaces here > wireless/bluetooth/bt_hcicore.c we should already be in a great place. I already have a Link Layer defined as an arch-independent upper-half that registers itself as a HCI capable net device (same as UART based devices do). Then I have an arch-dependant lower-half link-layer, which I'm currently working for NRF52. I can create a draft PR soon (after I finish upstreaming intermediate unrelated commits) if you want to take a look. > --Brennan >
Re: defining a BLE GATT server
I also think D-Bus does not seem to be appropriate for small systems. It is overkill. Also, having a library implementing all functionality and then a daemon using that library would be the best way. As Brennan mentions, in many use cases (such as mine) I would only have a single bluetooth application. On Mon, Aug 24, 2020, at 18:41, Brennan Ashton wrote: > You are going to hate dbus :) > Honestly it is designed to be a system wide message bus for > desktop/server software and defines even a wire message format that > supports things like introspection. I think that is wrong for a > small embedded system. That leaves the question of what should be > used for IPC for the GATT server daemon. I suspect we could get far > using event file descriptors, but also just having a library where a > single application owns the GATT server is probably fine. The dbus > service is nice because I can write a standalone application that > provides the BAT service for showing battery life, and then have > another application that broadcasts RPMs from a cadence sensor. > > --Brennan >
Re: defining a BLE GATT server
On Mon, Aug 24, 2020 at 3:56 PM Matias N. wrote: > That's quite a strange stack arrangement. If you go to the BLE spec, the > L2CAP sits above the HCI layer. > I would guess that the arrow between L2CAP and Bluez actually speaks the > HCI protocol and the "HCI sockets" allow you to directly call into the HCI > layer. I was under the impression that you wouldn't need to "skip layers" > to access all functionality of the LL, but I understand then why the > proposal of exposing the HCI layer via sockets. > The HCI socket interface does not directly map to the HCI interface of the controller. There are three different channels defined:#define HCI_CHANNEL_RAW 0 #define HCI_CHANNEL_RAW 0 #define HCI_CHANNEL_USER 1 #define HCI_CHANNEL_MONITOR 2 #define HCI_CHANNEL_CONTROL 3 HCI_CHANNEL_USER removes the rest of the bluetooth stack from the controller so that you dont have things like the L2CAP interface messing with the device. This can be super useful, it's actually what I am using to allow the NuttX sim to control my bluetooth hardware. This is in contrast to HCI_CHANNEL_RAW which does not unhook the rest of the stack so you can have multiple things now trying to control the hardware and you have to be careful. RAW is not recommended anymore. HCI_CHANNEL_MONITOR is somewhat self explanatory, but it lets you see all the transactions that are taking place over the HCI interface (including in bluez core). This is usually what something like wireshark will use. HCI_CHANNEL_CONTROL is the "new" control interface that speaks via the management API. This is what bluetoothd would be using to do things like advertise a new service. I wish this was better documented, but it is scattered around and bits of knowledge that I picked up writing a bluetooth mesh stack before it was included in Linux. Hopefully that is helpful, Brennan
Re: defining a BLE GATT server
Ah, ok, it was much more complex than what I thought. Thanks for the explanation! On Mon, Aug 24, 2020, at 20:10, Brennan Ashton wrote: > On Mon, Aug 24, 2020 at 3:56 PM Matias N. wrote: > > > That's quite a strange stack arrangement. If you go to the BLE spec, the > > L2CAP sits above the HCI layer. > > I would guess that the arrow between L2CAP and Bluez actually speaks the > > HCI protocol and the "HCI sockets" allow you to directly call into the HCI > > layer. I was under the impression that you wouldn't need to "skip layers" > > to access all functionality of the LL, but I understand then why the > > proposal of exposing the HCI layer via sockets. > > > > The HCI socket interface does not directly map to the HCI interface of the > controller. There are three different channels defined:#define > HCI_CHANNEL_RAW 0 > #define HCI_CHANNEL_RAW 0 > #define HCI_CHANNEL_USER 1 > #define HCI_CHANNEL_MONITOR 2 > #define HCI_CHANNEL_CONTROL 3 > > HCI_CHANNEL_USER removes the rest of the bluetooth stack from the > controller so that you dont have things like the L2CAP interface messing > with the device. This can be super useful, it's actually what I am using > to allow the NuttX sim to control my bluetooth hardware. > This is in contrast to HCI_CHANNEL_RAW which does not unhook the rest of > the stack so you can have multiple things now trying to control the > hardware and you have to be careful. RAW is not recommended anymore. > > HCI_CHANNEL_MONITOR is somewhat self explanatory, but it lets you see all > the transactions that are taking place over the HCI interface (including in > bluez core). This is usually what something like wireshark will use. > HCI_CHANNEL_CONTROL is the "new" control interface that speaks via the > management API. This is what bluetoothd would be using to do things like > advertise a new service. > > I wish this was better documented, but it is scattered around and bits of > knowledge that I picked up writing a bluetooth mesh stack before it was > included in Linux. > > Hopefully that is helpful, > Brennan >