From f82022c94134ced09cda84b36d13fb1c751731fd Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 23 Aug 2026 18:04:20 -0400 Subject: [PATCH] Accept re-pairing from a bonded peer (espressif) NimBLE reports BLE_GAP_EVENT_REPEAT_PAIRING when a peer we still hold a bond for asks to pair again. Unless the application deletes the old bond and returns BLE_GAP_REPEAT_PAIRING_RETRY, the stack silently ignores the pairing request. The event was unhandled, so a central that had forgotten its side of the bond could not pair again: the board's bonds had to be erased first. Delete the stale bond with ble_store_util_delete_peer() and retry, matching the nordic port, which clears the stored keys when a peer re-pairs. --- ports/espressif/common-hal/_bleio/Connection.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ports/espressif/common-hal/_bleio/Connection.c b/ports/espressif/common-hal/_bleio/Connection.c index 91d2336ee68..a063f3ee1a8 100644 --- a/ports/espressif/common-hal/_bleio/Connection.c +++ b/ports/espressif/common-hal/_bleio/Connection.c @@ -34,6 +34,7 @@ #include "freertos/queue.h" #include "host/ble_att.h" +#include "host/ble_store.h" // Uncomment to turn on debug logging just in this file. // #undef CIRCUITPY_VERBOSE_BLE @@ -81,6 +82,22 @@ int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in) } break; } + case BLE_GAP_EVENT_REPEAT_PAIRING: { + // The peer is asking to pair even though we still have a bond with it. + // This means it no longer has its own copy of that bond. Discard our bond + // and tell the BLE stack to carry on pairing. Otherwise NimBLE silently + // ignores the request, and a central that has forgotten this device can + // never pair again without erasing the bonds on the board. The + // nordic port likewise replaces the stored keys when a peer re-pairs. + struct ble_gap_conn_desc desc; + if (ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc) != 0) { + return BLE_GAP_REPEAT_PAIRING_IGNORE; + } + ble_store_util_delete_peer(&desc.peer_id_addr); + // The BLE stack checks that the bond is really gone before retrying, and + // reports this event again if it is not. + return BLE_GAP_REPEAT_PAIRING_RETRY; + } case BLE_GAP_EVENT_MTU: { if (event->mtu.conn_handle != connection->conn_handle) { return 0;