This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Errors after unpairing devices and further attempts to bond them

I built and run Bluetooth: Peripheral HIDS keyboard example on nRF52840 DK using nRF Connect SDK 1.3.0. I connected and bonded with it from an Android phone. Then I deleted bond information from the Android phone. After it, I wanted to connect and bond again. And it worked properly. Great! It was BT_SECURITY_L4. You can see UART logs below.

*** Booting Zephyr OS build v2.3.0-rc1-ncs1  ***
Starting Bluetooth Peripheral HIDS keyboard example
I: 8 Sectors of 4096 bytes
I: alloc wra: 0, fa0
I: data wra: 0, f4
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF52x (0x0002)
I: Firmware: Standard Bluetooth controller (0x00) Version 2.3 Build 0
I: No ID address. App must call settings_load()
Bluetooth initialized
E: set-value failure. key: bt/name error(-2)
I: Identity: d6:c4:f9:a2:02:ad (random)
I: HCI: version 5.2 (0x0b) revision 0x0000, manufacturer 0x05f1
I: LMP: version 5.2 (0x0b) subver 0xffff
NFC configuration start
NFC configuration done
Advertising successfully started
Advertising continued
Connected 20:47:da:12:f4:e8 (public)
Passkey for 20:47:da:12:f4:e8 (public): 800540
Press Button 1 to confirm, Button 2 to reject.
Numeric Match, conn 0x2000177c
Key report send error: -13
Security changed: 20:47:da:12:f4:e8 (public) level 4
Pairing completed: 20:47:da:12:f4:e8 (public), bonded: 1
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)
Advertising successfully started
Advertising continued
Connected 20:47:da:12:f4:e8 (public)
Passkey for 20:47:da:12:f4:e8 (public): 379671
Press Button 1 to confirm, Button 2 to reject.
Numeric Match, conn 0x2000177c
Security changed: 20:47:da:12:f4:e8 (public) level 4
Pairing completed: 20:47:da:12:f4:e8 (public), bonded: 1
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)


Now I want to do the same with BT_SECURITY_L2 without any numeric comparison. What should I do? I set passkey_display and passkey_confirm callbacks to NULL:

static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = NULL,
	.passkey_confirm = NULL,
	.cancel = auth_cancel,
	.pairing_confirm = pairing_confirm,
#if CONFIG_NFC_OOB_PAIRING
	.oob_data_request = auth_oob_data_request,
#endif
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};


Is it right?

And I built and run the program. And I did the same steps of connecting/disconnecting and bonding/deleting bond information twice. And you can see in below UART logs that I couldn't bond the second time:

Security failed: 20:47:da:12:f4:e8 (public) level 1 err 4
Pairing failed conn: 20:47:da:12:f4:e8 (public), reason 4

*** Booting Zephyr OS build v2.3.0-rc1-ncs1  ***
Starting Bluetooth Peripheral HIDS keyboard example
I: 8 Sectors of 4096 bytes
I: alloc wra: 0, ff0
I: data wra: 0, 0
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF52x (0x0002)
I: Firmware: Standard Bluetooth controller (0x00) Version 2.3 Build 0
I: No ID address. App must call settings_load()
Bluetooth initialized
I: Identity: d6:c4:f9:a2:02:ad (random)
I: HCI: version 5.2 (0x0b) revision 0x0000, manufacturer 0x05f1
I: LMP: version 5.2 (0x0b) subver 0xffff
NFC configuration start
NFC configuration done
Advertising successfully started
Advertising continued
Connected 48:ef:30:6f:b3:db (random)
Pairing confirmed: 48:ef:30:6f:b3:db (random)
Security changed: 48:ef:30:6f:b3:db (random) level 2
Pairing completed: 20:47:da:12:f4:e8 (public), bonded: 1
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)
Advertising successfully started
Advertising continued
Connected 20:47:da:12:f4:e8 (public)
Security failed: 20:47:da:12:f4:e8 (public) level 1 err 4
Pairing failed conn: 20:47:da:12:f4:e8 (public), reason 4
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)

Logs from nRF Connect SDK:

nRF Connect, 2020-08-07
Nordic_HIDS_keyboard (D6:C4:F9:A2:02:AD)
V	02:32:15.042	Connecting to D6:C4:F9:A2:02:AD...
D	02:32:15.042	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
D	02:32:15.922	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	02:32:15.922	Connected to D6:C4:F9:A2:02:AD
D	02:32:15.922	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
V	02:32:15.946	Discovering services...
D	02:32:15.946	gatt.discoverServices()
D	02:32:15.954	[Callback] Services discovered with status: 0
I	02:32:15.954	Services discovered
V	02:32:15.991	Generic Attribute (0x1801)
- Service Changed [I] (0x2A05)
   Client Characteristic Configuration (0x2902)
- Client Supported Features [R W] (0x2B29)
- Database Hash [R] (0x2B2A)
Generic Access (0x1800)
- Device Name [R] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Battery Service (0x180F)
- Battery Level [N R] (0x2A19)
   Client Characteristic Configuration (0x2902)
Device Information (0x180A)
- Model Number String [R] (0x2A24)
- Manufacturer Name String [R] (0x2A29)
- PnP ID [R] (0x2A50)
Human Interface Device (0x1812)
- Protocol Mode [R WNR] (0x2A4E)
- Report [N R] (0x2A4D)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
- Report [R W WNR] (0x2A4D)
   Report Reference (0x2908)
- Report Map [R] (0x2A4B)
- Boot Keyboard Input Report [N R] (0x2A22)
   Client Characteristic Configuration (0x2902)
- Boot Keyboard Output Report [R W WNR] (0x2A32)
- HID Information [R] (0x2A4A)
- HID Control Point [WNR] (0x2A4C)
D	02:32:15.991	gatt.setCharacteristicNotification(00002a05-0000-1000-8000-00805f9b34fb, true)
D	02:32:15.993	gatt.setCharacteristicNotification(00002a19-0000-1000-8000-00805f9b34fb, true)
D	02:32:15.994	gatt.setCharacteristicNotification(00002a4d-0000-1000-8000-00805f9b34fb, true)
D	02:32:15.995	gatt.setCharacteristicNotification(00002a22-0000-1000-8000-00805f9b34fb, true)
V	02:32:17.786	Starting pairing...
D	02:32:17.786	device.createBond()
D	02:32:17.809	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
I	02:32:18.619	Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D	02:32:19.158	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
I	02:32:19.158	Device bonded
I	02:32:19.696	Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
I	02:32:21.226	Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 420ms)
V	02:32:28.559	Removing bond information...
D	02:32:28.559	device.removeBond() (hidden)
D	02:32:28.608	[Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0)
E	02:32:28.609	Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST
I	02:32:28.609	Disconnected
D	02:32:28.628	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	02:32:29.218	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
I	02:32:29.218	Bond information deleted
D	02:32:36.404	gatt.close()
D	02:32:36.406	wait(200)
V	02:32:36.608	Connecting to D6:C4:F9:A2:02:AD...
D	02:32:36.608	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
D	02:32:37.564	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	02:32:37.569	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	02:32:37.569	Connected to D6:C4:F9:A2:02:AD
V	02:32:37.594	Discovering services...
D	02:32:37.594	gatt.discoverServices()
D	02:32:37.601	[Callback] Services discovered with status: 0
I	02:32:37.601	Services discovered
V	02:32:37.617	Generic Attribute (0x1801)
- Service Changed [I] (0x2A05)
   Client Characteristic Configuration (0x2902)
- Client Supported Features [R W] (0x2B29)
- Database Hash [R] (0x2B2A)
Generic Access (0x1800)
- Device Name [R] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Battery Service (0x180F)
- Battery Level [N R] (0x2A19)
   Client Characteristic Configuration (0x2902)
Device Information (0x180A)
- Model Number String [R] (0x2A24)
- Manufacturer Name String [R] (0x2A29)
- PnP ID [R] (0x2A50)
Human Interface Device (0x1812)
- Protocol Mode [R WNR] (0x2A4E)
- Report [N R] (0x2A4D)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
- Report [R W WNR] (0x2A4D)
   Report Reference (0x2908)
- Report Map [R] (0x2A4B)
- Boot Keyboard Input Report [N R] (0x2A22)
   Client Characteristic Configuration (0x2902)
- Boot Keyboard Output Report [R W WNR] (0x2A32)
- HID Information [R] (0x2A4A)
- HID Control Point [WNR] (0x2A4C)
D	02:32:37.617	gatt.setCharacteristicNotification(00002a05-0000-1000-8000-00805f9b34fb, true)
D	02:32:37.619	gatt.setCharacteristicNotification(00002a19-0000-1000-8000-00805f9b34fb, true)
D	02:32:37.621	gatt.setCharacteristicNotification(00002a4d-0000-1000-8000-00805f9b34fb, true)
D	02:32:37.624	gatt.setCharacteristicNotification(00002a22-0000-1000-8000-00805f9b34fb, true)
V	02:32:40.512	Starting pairing...
D	02:32:40.512	device.createBond()
D	02:32:40.541	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D	02:32:40.589	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
I	02:32:40.589	Bonding failed
I	02:32:41.072	Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D	02:32:43.644	[Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0)
E	02:32:43.644	Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST
I	02:32:43.644	Disconnected
D	02:32:43.708	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED

As I understood, I had to add unpairing on the side of peripherals. And I added bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY) call in a disconnected callback. Then I built and run the program again and I tried the same steps of connecting/disconnecting and bonding/deleting bond information twice. And everything worked fine!

So, I want to ask you about the unpairing stage. In which callback should I call bt_unpair function?

Is there a way to distinguish ordinary disconnection from deleting bond information on a remote device? I think that no. So, I want to ask how to properly avoid the error with the second attempt to bond, when there's not a numeric comparison. It's an ordinary case when the bond information was deleted on the remote device and it tries to connect the second time. So I have to handle such bonding properly. Please, explain to me, how to cope with it.

Why don't provided examples have such unpairing functions?

And why did a security level changed to 1 during the second bonding without calling bt_unpair function, although it was 2 after the first attempt?

Thank you in advance for any assistance!

Parents
  • As I understood, I had to add unpairing on the side of peripherals.

     That's correct! The device won't be able to connect and pair again to a device it thinks it is already paired with. If you'd like to delete bonding information upon a disconnect, it would be correct to add the bt_unpair function in the disconnected callback.

    Is there a way to distinguish ordinary disconnection from deleting bond information on a remote device?

     No, the peripheral won't be able to distinguish this as far as I know.

    The reason our examples don't do this by default is that you'd generally like to keep bonding information even though the devices disconnect from one another so that reconnections are easier. You can call the bt_unpair() by I.E. pressing a button if you'd like to delete the bonding information manually instead. This is just a suggestion, and I'm sure there are multiple clever solutions on how you could do this.

    Best regards,

    Simon

  • Thank you very much for your response!

    I would like to clarify, is it possible to correctly handle the second attempt to bond, when a central device has deleted bond information, whereas a peripheral device still stores it? In a security_changed callback we can see an error, when the central device tries to bond again after deleting the bond information. Can the peripheral device delete outdated bond information, when during the second attempt it raises the error and bond again successfully within the second bonding?

    So, I will try to rephrase. Central and peripheral devices are bonded. After it, the central device deletes bond information, and the peripheral device still stores it. Then the central device tries to bond again to the peripheral device. Now it raises an error, because the peripheral device thinks it is already paired. If I don't want to delete to bond information after each disconnection, and I want to delete it only it becomes not corresponding to the central device bond information. So, how should the central device handle the second attempt of bonding? Can you specify callbacks, when the central device recognises that bond information is wrong, so it should delete it and bond again and not just break the connection?

Reply
  • Thank you very much for your response!

    I would like to clarify, is it possible to correctly handle the second attempt to bond, when a central device has deleted bond information, whereas a peripheral device still stores it? In a security_changed callback we can see an error, when the central device tries to bond again after deleting the bond information. Can the peripheral device delete outdated bond information, when during the second attempt it raises the error and bond again successfully within the second bonding?

    So, I will try to rephrase. Central and peripheral devices are bonded. After it, the central device deletes bond information, and the peripheral device still stores it. Then the central device tries to bond again to the peripheral device. Now it raises an error, because the peripheral device thinks it is already paired. If I don't want to delete to bond information after each disconnection, and I want to delete it only it becomes not corresponding to the central device bond information. So, how should the central device handle the second attempt of bonding? Can you specify callbacks, when the central device recognises that bond information is wrong, so it should delete it and bond again and not just break the connection?

Children
Related