diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index f65020d2ae..d402c6a9eb 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -202,6 +202,9 @@ Event Handling elif event == _IRQ_CONNECTION_UPDATE: # The remote device has updated connection parameters. conn_handle, conn_interval, conn_latency, supervision_timeout, status = data + elif event == _IRQ_ENCRYPTION_UPDATE: + # The encryption state has changed (likely as a result of pairing or bonding). + conn_handle, encrypted, authenticated, bonded, key_size = data The event codes are:: @@ -233,6 +236,7 @@ The event codes are:: _IRQ_L2CAP_RECV = const(25) _IRQ_L2CAP_SEND_READY = const(26) _IRQ_CONNECTION_UPDATE = const(27) + _IRQ_ENCRYPTION_UPDATE = const(28) For the ``_IRQ_GATTS_READ_REQUEST`` event, the available return codes are:: diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index da9a6f732b..825a9ab7b1 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -359,6 +359,35 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t DEBUG_printf(" --> btstack # conns changed\n"); } else if (event_type == HCI_EVENT_VENDOR_SPECIFIC) { DEBUG_printf(" --> hci vendor specific\n"); + } else if (event_type == SM_EVENT_AUTHORIZATION_RESULT || + event_type == SM_EVENT_PAIRING_COMPLETE || + // event_type == GAP_EVENT_DEDICATED_BONDING_COMPLETED || // No conn_handle + event_type == HCI_EVENT_ENCRYPTION_CHANGE) { + DEBUG_printf(" --> enc/auth/pair/bond change\n", ); + #if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + uint16_t conn_handle; + switch (event_type) { + case SM_EVENT_AUTHORIZATION_RESULT: + conn_handle = sm_event_authorization_result_get_handle(packet); + break; + case SM_EVENT_PAIRING_COMPLETE: + conn_handle = sm_event_pairing_complete_get_handle(packet); + break; + case HCI_EVENT_ENCRYPTION_CHANGE: + conn_handle = hci_event_encryption_change_get_connection_handle(packet); + break; + default: + return; + } + + hci_connection_t *hci_con = hci_connection_for_handle(conn_handle); + sm_connection_t *desc = &hci_con->sm_connection; + mp_bluetooth_gatts_on_encryption_update(conn_handle, + desc->sm_connection_encrypted, + desc->sm_connection_authenticated, + desc->sm_le_db_index != -1, + desc->sm_actual_encryption_key_size); + #endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING } else if (event_type == HCI_EVENT_DISCONNECTION_COMPLETE) { DEBUG_printf(" --> hci disconnect complete\n"); uint16_t conn_handle = hci_event_disconnection_complete_get_connection_handle(packet); diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index b9b7c71248..5d7de7b97f 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1107,6 +1107,13 @@ void mp_bluetooth_gap_on_connection_update(uint16_t conn_handle, uint16_t conn_i invoke_irq_handler(MP_BLUETOOTH_IRQ_CONNECTION_UPDATE, args, 5, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); } +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypted, bool authenticated, bool bonded, uint8_t key_size) { + uint8_t args[] = {encrypted, authenticated, bonded, key_size}; + invoke_irq_handler(MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE, &conn_handle, 1, args, 4, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); +} +#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { uint16_t args[] = {conn_handle, value_handle}; invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_WRITE, args, 2, NULL_U8, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 2cb2c709c5..62ff6f2f9e 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -145,6 +145,7 @@ #define MP_BLUETOOTH_IRQ_L2CAP_RECV (25) #define MP_BLUETOOTH_IRQ_L2CAP_SEND_READY (26) #define MP_BLUETOOTH_IRQ_CONNECTION_UPDATE (27) +#define MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE (28) #define MP_BLUETOOTH_ADDRESS_MODE_PUBLIC (0) #define MP_BLUETOOTH_ADDRESS_MODE_RANDOM (1) @@ -182,7 +183,8 @@ _IRQ_L2CAP_CONNECT = const(23) _IRQ_L2CAP_DISCONNECT = const(24) _IRQ_L2CAP_RECV = const(25) _IRQ_L2CAP_SEND_READY = const(26) -_IRQ_GATTS_CONN_UPDATE = const(27) +_IRQ_CONNECTION_UPDATE = const(27) +_IRQ_ENCRYPTION_UPDATE = const(28) _FLAG_BROADCAST = const(0x0001) _FLAG_READ = const(0x0002) @@ -339,6 +341,11 @@ void mp_bluetooth_gap_on_connected_disconnected(uint8_t event, uint16_t conn_han // Call this when any connection parameters have been changed. void mp_bluetooth_gap_on_connection_update(uint16_t conn_handle, uint16_t conn_interval, uint16_t conn_latency, uint16_t supervision_timeout, uint16_t status); +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +// Call this when any connection encryption has been changed (e.g. during pairing). +void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypted, bool authenticated, bool bonded, uint8_t key_size); +#endif + // Call this when a characteristic is written to. void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index e79dc2d4cb..312a564263 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -316,6 +316,19 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) { } break; } + + case BLE_GAP_EVENT_ENC_CHANGE: { + DEBUG_printf("gap_event_cb: enc change: status=%d\n", event->enc_change.status); + #if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + struct ble_gap_conn_desc desc; + if (ble_gap_conn_find(event->enc_change.conn_handle, &desc) == 0) { + mp_bluetooth_gatts_on_encryption_update(event->conn_update.conn_handle, + desc.sec_state.encrypted, desc.sec_state.authenticated, + desc.sec_state.bonded, desc.sec_state.key_size); + } + #endif + break; + } } return 0; } @@ -971,6 +984,17 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { break; } + case BLE_GAP_EVENT_ENC_CHANGE: { + DEBUG_printf("peripheral_gap_event_cb: enc change: status=%d\n", event->enc_change.status); + #if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + if (ble_gap_conn_find(event->enc_change.conn_handle, &desc) == 0) { + mp_bluetooth_gatts_on_encryption_update(event->conn_update.conn_handle, + desc.sec_state.encrypted, desc.sec_state.authenticated, + desc.sec_state.bonded, desc.sec_state.key_size); + } + #endif + break; + } default: break; }