nrf-softdevice icon indicating copy to clipboard operation
nrf-softdevice copied to clipboard

Add support for peripheral BLE legacy peering and bonding

Open alexmoon opened this issue 2 years ago • 2 comments

This adds peering and bonding support for peripheral devices. Bonding is supported by a new advertise_bondable function which takes a &'static dyn BondHandler that provides the methods needed to create, store and retrieve the LTK for the bond.

alexmoon avatar Apr 24 '22 14:04 alexmoon

Very excited to see a bonding API. Shouldn't the new trait functions be async, though, to match the rest of the crate? Especially since the flash interface in this crate, which would probably be used to implement bonding, is already async.

quentinmit avatar Jul 16 '22 20:07 quentinmit

Very excited to see a bonding API. Shouldn't the new trait functions be async, though, to match the rest of the crate? Especially since the flash interface in this crate, which would probably be used to implement bonding, is already async.

That would be ideal, unfortunately there are a couple of problems:

  • We don't want to block the ble event loop from handling other events during async handling of bond requests. If the trait functions were async, that would mean they should be spawned as new tasks. That would require an allocator which we can't count on in no-std.
  • An async trait (without an allocator) relies on GAT and TAIT. Those features make the trait not object-safe. That means we couldn't store a &dyn reference but would have to make everything generic on the type of the BondHandler. That generic parameter would quickly pollute everything because of how deep in the crate the BondHandler functions need to be called.

In general, if the implementation of the BondHandler methods has async requirements, the application should forward the request (via a Channel or similar) to a task it creates for that purpose. The functions that are expected to provide a reply asynchronously (e.g. enter_passkey and recv_out_of_band) take a ...Reply struct that can be stored or sent over a channel to other tasks for this purpose. The get_key implementation currently does need to be synchronous; the expectation is that the bond database can be loaded into RAM or accessed via memory-mapped flash and does not need to be asynchronous. Let me know if that's a problem for your application.

alexmoon avatar Jul 18 '22 15:07 alexmoon

In general, if the implementation of the BondHandler methods has async requirements, the application should forward the request (via a Channel or similar) to a task it creates for that purpose. The functions that are expected to provide a reply asynchronously (e.g. enter_passkey and recv_out_of_band) take a ...Reply struct that can be stored or sent over a channel to other tasks for this purpose. The get_key implementation currently does need to be synchronous; the expectation is that the bond database can be loaded into RAM or accessed via memory-mapped flash and does not need to be asynchronous. Let me know if that's a problem for your application.

That makes sense. I don't have any particular requirements, though compatibility with the Bluefruit library that's commonly used on Arduino would be nice. I started working on that rabbit hole (they store bonds in a littlefs on internal flash at 0xED000-0xF4000) and I've got working code to read the files now, but I haven't tried connecting it to your interface yet.

quentinmit avatar Aug 26 '22 19:08 quentinmit