Hints on implementing iOS-compatible L2CAP peripheral

Hi all,

We've developed BLE controllers for our new smartphone-based VR product. nRF52810 with S113 softdevice.

Right now the data (inputs + multiple IMU data samples) are sent via GATT characteristic updates, and on iOS we negotiate down to a 15ms connection interval.

I noticed something weird on some iOS devices (iPhone 12 Pro is my main test device atm). On a regular cadence (every 10 seconds) the characteristic update callbacks to the app are delayed by 100ms or more. I've confirmed with the BLE Sniffer that all the over-the-air traffic is as expected, so it's just something within the iOS CoreBluetooth stack on some devices.

More details in the Apple Developer Forums here: https://developer.apple.com/forums/thread/713800 - I've also reported it as a bug to Apple.

Out of interest I thought I'd try using two iOS devices and the CoreBluetooth support for making apps behave like peripherals. The delays in GATT characteristic updates were still reproducible. I then tried using an L2CAP channel instead (very simple on iOS) and was surprised that these messages didn't suffer the regular-cadence delays.

So my goal now is to try to make my nRF peripheral behave like the L2CAP channel iOS one to avoid the CoreBluetooth flakiness.

The iOS peripheral API to do this is simple:

[peripheralManager_ publishL2CAPChannelWithEncryption:NO];

That triggers a didPublishL2CAPChannel callback with the PSM id. Then when a central connects to that PSM you get a didOpenL2CAPChannel callback with input and output streams that you can just read and write bytes with.
I've seen various posts referencing the Object Transfer Service example but that's a pretty complex sample.
I'd be keen to just have a few pointers to where to start in the docs on this.
Thanks!
Parents Reply Children
No Data
Related