Continuous issues with Bluetooth Pairing with Apple Devices, while Android works flawlessly

Hello, 

Since our Product Launch we have gotten feedback that pairing with some (but not all) Apple devices is a significant problem. Even through several attempted fixes we haven't gotten this to work. 

We use the BT FTMS Profile, implemented on top of the S313 ANT+ and BLE Softdevice. There, our pairing setup looks like this: 

1. Device connects, might read preferred connection parameters or not, which are: 

ble_gap_conn_params_t {
    min_conn_interval: 12, // 12 * 1.25ms = 15ms  (ios-compatible min)
    max_conn_interval: 24, // 24 * 1.25ms = 30ms  (common "safe" max for iOS)
    slave_latency: 0,      // no slave latency
    conn_sup_timeout: 500, // 500 * 10ms = 5s
};

2. (generally) discovers GATT services and such

3. One second after connection, our firmware sets the connection params itself (which are the same as above, and generally succeeds according to nrf-connect)

4. 800ms after that, our firmware triggers pairing. This generally shows a notification or confirmation window on devices, and tends to work as expected. 

For all devices I have available from multiple manufacturers and with multiple OSses (Linux, Windows, Android, iOS including an iPhone 14 and an iPad Air), this works just fine. However, we've heard from several people that there's behavior like this: 

1. Device gets selected in the fitness app or whereever, connects, pairing window pops up, connection works

2. Data gets received (no security on all the rx parts, so that makes sense), no control commands to e.g. set power get sent (which makes sense assuming the pairing didn't work, as writing to it requires just works security)

3. After 30-45ish seconds a new pairing prompt gets displayed. Same behavior loops after pressing pair again. 

We've tried quite a few different ways to fix that, but nothing we found until now works so far, so we're kind of at a loss as to what we're doing wrong. 

Some more info: 

- io_caps are set to BLE_GAP_IO_CAPS_NONE, and the MITM flag is 0. Also, min_key_size = 7 and max_key_size = 16. 

- Advertising interval is the Apple-recommended 20ms (32). Discoverability never was a problem, but can't hurt. 

- Bonding is only triggered after 1.8s if and only if the device is not yet bonded, it's not just slammed down indiscriminately. 

- LESC is not supported by our firmware (and it indicates this properly)

- Devices that don't work seem to be some macbooks, quite a few iPads, the iPhone 17 Pro, and the Apple TV. Pretty often people report that it works on some of their devices, but not on e.g. an iPad. 

- The only other problematic device we saw is a Lenovo tablet that (according to what I think) doesn't accept pairing without LESC due to some bluetooth stack regression, but nothing we have in our hands allows us to replicate the issue until now.

- Some devices failed silently in the past, never showing a pairing prompt while just refusing to write to the Control Point behind the JustWorks security

- The device has the DIS service implemented, which is explicitly required by Apple. I have no idea if its presence has any relation on this problem, but it can't hurt I think.

I'd really appreciate any ideas or tips as to how to proceed here. This seems to be a consistent problem across some versions of Apple Bluetooth stacks, but it's hard to see a pattern for now. Any help would really be much appreciated!

  • Just one correction to the chip used, this is on an nRF52832, not a nRF52840, apologies for the wrong selection there

  • Hello,

    I don't think I have seen other reports similar to this. Have you been able to consistently reproduce this issue locally using these Apple devices? If you are able to do this you can also capture a sniffer trace which may help troubleshoot this further: https://www.nordicsemi.com/Products/Development-tools/nRF-Sniffer-for-Bluetooth-LE

    Data gets received (no security on all the rx parts, so that makes sense), no control commands to e.g. set power get sent (which makes sense assuming the pairing didn't work, as writing to it requires just works security

    The pairing prompt should appear as soon as the iOS app tries to access a characteristic that requires security. 

    One second after connection, our firmware sets the connection params itself (which are the same as above, and generally succeeds according to nrf-connect)

    What happens if the phone were to reject the connection parameters update request, will it terminate the connection?

    Best regards,

    Vidar

  • No worries, but thanks for the update. The chip variant is likely not relevant to the issue.

  • Hello Vidar, thanks for the quick answer!

    Firstly, I am completely unable to repro this locally. That's the major roadblock I've hit aswell, so there's no real way for me to figure out what exactly is going wrong. I think I'll just have to commit to buying Apple devices until I hit one that doesn't work or something like that :/

    The pairing prompt should appear as soon as the iOS app tries to access a characteristic that requires security. 

    It does. It appears, gets confirmed, and still the pairing is unsuccessful. I don't know why. Then, the pairing prompt reappears a few seconds later, generally 30-40 (but always the exact same time interval per device)

    What happens if the phone were to reject the connection parameters update request, will it terminate the connection?

    Nothing. If the phone rejects, the device accepts that fact, and proceeds with the active pairing request 800ms later, while keeping the GATT server available at all times since the start of the connection of course. 

  • Hi,

    Vidar is away, so I am taking a look instead. I can't think of anything in specific, but maybe you can share some of the kconfig options you have from the .config file in the build folder?

    I am in specific interested for instance in:

    CONFIG_BT_GATT_AUTO_SEC_REQ
    CONFIG_BT_AUTO_DATA_LEN_UPDATE
    CONFIG_BT_AUTO_PHY_UPDATE
    CONFIG_BT_GATT_AUTO_UPDATE_MTU
    CONFIG_BT_KEYS_OVERWRITE_OLDEST
    CONFIG_BT_ID_UNPAIR_MATCHING_BONDS
    CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE
    CONFIG_BT_ID_ALLOW_UNAUTH_OVERWRITE
    CONFIG_ASSERT

    If I were to wild guess anything I can see that the connection interval is rather short (20ms), while the slave latency is 0. I would prefer that you use some slave latency with this short interval, the reasoning behind that is a bit technical, but the problem is that if the application needs to perform any flash erase operations to store bonding data to flash, then it will need to reserve about 100ms for this to complete. However at the same time the softdevice need to ensure that it can handle any LL procedures within a connection interval * (6 + slave latency), so I can see that it will have difficult to schedule this to occur with the connection parameters settings you have chosen unless you enable to some slave latency.

    Kenneth

Related