diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index 2a311db2a8..236a39736a 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -252,11 +252,14 @@ struct hci_conn_update; /** GAP event: Subrate change */ #define BLE_GAP_EVENT_SUBRATE_CHANGE 28 +/** GAP event: Unhandled HCI event */ +#define BLE_GAP_EVENT_UNHANDLED_HCI 29 + /** GAP event: Vendor specific HCI event */ -#define BLE_GAP_EVENT_VS_HCI 29 +#define BLE_GAP_EVENT_VS_HCI 30 /** GAP event: BIG (Broadcast Isochronous Group) information report */ -#define BLE_GAP_EVENT_BIGINFO_REPORT 30 +#define BLE_GAP_EVENT_BIGINFO_REPORT 31 /** @} */ @@ -1288,6 +1291,18 @@ struct ble_gap_event { } subrate_change; #endif + /** + * Represents a received HCI event that host did not handle + * + * Valid for the following event types: + * o BLE_GAP_EVENT_UNHANDLED_HCI + */ + struct { + bool le_meta; + const void *ev; + uint8_t length; + } unhandled_hci; + #if MYNEWT_VAL(BLE_HCI_VS) /** * Represents a received vendor-specific HCI event diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 3a63050b40..7fc63a492a 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -6357,6 +6357,22 @@ ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu) #endif } +#if MYNEWT_VAL(BLE_HS_GAP_UNHANDLED_HCI_EVENT) +void +ble_gap_unhandled_hci_event(bool le_meta, uint8_t len, const void *buf) +{ + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_UNHANDLED_HCI; + event.unhandled_hci.le_meta = le_meta; + event.unhandled_hci.ev = buf; + event.unhandled_hci.length = len; + + ble_gap_event_listener_call(&event); +} +#endif + #if MYNEWT_VAL(BLE_HCI_VS) void ble_gap_vs_hci_event(const void *buf, uint8_t len) diff --git a/nimble/host/src/ble_gap_priv.h b/nimble/host/src/ble_gap_priv.h index 0be949da60..0ada2af6a8 100644 --- a/nimble/host/src/ble_gap_priv.h +++ b/nimble/host/src/ble_gap_priv.h @@ -141,6 +141,7 @@ void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu); void ble_gap_identity_event(uint16_t conn_handle, const ble_addr_t *peer_id_addr); int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp); void ble_gap_pairing_complete_event(uint16_t conn_handle, int status); +void ble_gap_unhandled_hci_event(bool le_meta, unsigned char len, const void *buf); void ble_gap_vs_hci_event(const void *buf, uint8_t len); int ble_gap_master_in_progress(void); diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index e7af2243b8..93d92efca9 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -315,6 +315,10 @@ ble_hs_hci_evt_le_meta(uint8_t event_code, const void *data, unsigned int len) fn = ble_hs_hci_evt_le_dispatch_find(ev->subevent); if (fn) { return fn(ev->subevent, data, len); + } else { +#if MYNEWT_VAL(BLE_HS_GAP_UNHANDLED_HCI_EVENT) + ble_gap_unhandled_hci_event(true, len, data); +#endif } return 0; @@ -910,6 +914,9 @@ ble_hs_hci_evt_process(struct ble_hci_ev *ev) entry = ble_hs_hci_evt_dispatch_find(ev->opcode); if (entry == NULL) { +#if MYNEWT_VAL(BLE_HS_GAP_UNHANDLED_HCI_EVENT) + ble_gap_unhandled_hci_event(false, ev->length, ev->data); +#endif STATS_INC(ble_hs_stats, hci_unknown_event); rc = BLE_HS_ENOTSUP; } else { diff --git a/nimble/host/syscfg.yml b/nimble/host/syscfg.yml index f94111c61d..8218b9e769 100644 --- a/nimble/host/syscfg.yml +++ b/nimble/host/syscfg.yml @@ -474,6 +474,13 @@ syscfg.defs: Sysinit stage for the NimBLE host. value: 200 + BLE_HS_GAP_UNHANDLED_HCI_EVENT: + description: > + Enables GAP event for received HCI events that are not handled by + host. This can be used to implement/test features that are not yet + supported by host. + value: 0 + ### Log settings. BLE_HS_LOG_MOD: