I am facing an issue in nRF Connect SDK v2.9.0 related to pairing and bonding callbacks.

My device supports both Central and Peripheral roles. By default, it works in Peripheral mode.
When the device connects in Peripheral mode, I want the following behavior:

  1. A passkey popup window should appear on the mobile app.

  2. The mobile should enter the correct passkey.

  3. Only after successful pairing and bonding, the mobile should send the passkey to my device through a BLE characteristic.

  4. My device stores this passkey and later automatically enters it when connecting to another device in Central mode.


Current Authentication Callback

static struct bt_conn_auth_cb auth_cb = {
.passkey_display = auth_passkey_display,
.passkey_entry = auth_passkey_entry,
.passkey_confirm = auth_passkey_confirm,
.cancel = auth_cancel,
.pairing_confirm = pairing_confirm,
};

Issue with This Callback

  • When auth_passkey_entry is enabled, no popup window is generated on the mobile, and the stack sends a random passkey.

  • This happens because passkey_entry has higher priority than passkey_display.

  • If I comment out passkey_entry and passkey_confirm, the popup window appears correctly on the mobile.

  • However, in that case, the device cannot enter the passkey when it connects to another device in Central mode.


Attempted Solution: Separate Callbacks for Each Role

Because of this, I created separate authentication callbacks and tried switching them based on the role.

Peripheral Mode (Mobile → HH)

DisplayOnly — mobile enters passkey

static struct bt_conn_auth_cb auth_cb_peripheral = {
.passkey_display = auth_passkey_display,
.passkey_entry = NULL,
.passkey_confirm = NULL,
.cancel = auth_cancel,
.pairing_confirm = pairing_confirm,
};

Central Mode (HH → Underdash 2)

KeyboardOnly — HH enters stored passkey

static struct bt_conn_auth_cb auth_cb_central = {
.passkey_entry = auth_passkey_entry,
.passkey_confirm = auth_passkey_confirm,
.cancel = auth_cancel,
.pairing_confirm = pairing_confirm,
};

Current Problem

  • The first registered callback works, but after switching the callback at runtime, the new one does not take effect.

  • I believe this happens because the BLE stack already registered the previous callback, and it cannot be switched dynamically at runtime.

If needed, I can share my full authentication callback implementation so you can analyze it and identify the exact issue.

Related