feat(nimble): Add support for HCI commands / events

1. Read all local supported feature
  2. Read remote supported feature
  3. Advertising monitor.
This commit is contained in:
Rahul Tank
2025-09-25 18:08:50 +05:30
parent 9464ecd6e3
commit 4538733010
8 changed files with 352 additions and 1 deletions
+50
View File
@@ -183,6 +183,9 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_BIGINFO_ADV_RPT 49
#define BLE_GAP_EVENT_CIS_ESTAB_V2 50
#define BLE_GAP_EVENT_RD_ALL_REM_FEAT 51
#define BLE_GAP_EVENT_MONITOR_ADV_REPORT 52
/* DTM events */
#define BLE_GAP_DTM_TX_START_EVT 0
#define BLE_GAP_DTM_RX_START_EVT 1
@@ -1986,6 +1989,53 @@ struct ble_gap_event {
} cis_estab_v2;
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
/**
* Represents a read all remote features complet event
* Valid for the following event types:
* o BLE_GAP_EVENT_RD_ALL_REM_FEAT
*/
struct {
/** Status indicating the reason for failure.
* Refer to HCI error codes for detailed status values.
*/
uint8_t status;
/** Connection handle identifying the connection. */
uint16_t conn_handle;
/** Highest numbered page of remote device's supported LE features
* that contains atleast one bit set to 1
*/
uint8_t max_remote_page;
/** Number of highest numbered page of LE features that contains
* valid data
*/
uint8_t max_valid_page;
/** Bit Mask List of LE features */
uint8_t le_features[248];
} rd_all_rem_feat;
#if MYNEWT_VAL(BLE_MONITOR_ADV)
/**
* Represents a read all remote features complet event
* Valid for the following event types:
* o BLE_GAP_EVENT_MONITOR_ADV_REPORT
*/
struct {
/** Address Type [Public/Random...] */
uint8_t addr_type;
/** Device Address */
uint16_t address[6];
/** Represents weather RSSI threshold condition is met */
uint8_t condition;
} monitor_adv_report;
#endif
};
};
+50
View File
@@ -2203,6 +2203,44 @@ ble_gap_rx_cis_estab_v2(const struct ble_hci_ev_le_subev_cis_established_v2 *ev)
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
void
ble_gap_rx_rd_all_remote_feat(const struct ble_hci_ev_le_subev_rd_all_rem_feat *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_RD_ALL_REM_FEAT;
event.rd_all_rem_feat.status = ev->status;
event.rd_all_rem_feat.max_remote_page = ev->max_remote_page;
event.rd_all_rem_feat.max_valid_page = ev->max_valid_page;
memcpy(event.rd_all_rem_feat.le_features, ev->le_features, 248);
ble_gap_event_listener_call(&event);
#if NIMBLE_BLE_CONNECT
ble_gap_call_conn_event_cb(&event, ev->conn_handle);
#endif
}
#if MYNEWT_VAL(BLE_MONITOR_ADV)
void
ble_gap_rx_rd_monitor_adv_report(const struct ble_hci_ev_le_subev_monitor_adv_report *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_MONITOR_ADV_REPORT;
event.monitor_adv_report.addr_type = ev->addr_type;
event.monitor_adv_report.condition = ev->condition;
memcpy(event.monitor_adv_report.address, ev->address, 6);
ble_gap_event_listener_call(&event);
}
#endif
void
ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
{
@@ -9936,6 +9974,18 @@ ble_gap_dtm_enh_rx_start(uint8_t rx_chan, uint8_t index, uint8_t phy)
return ble_hs_hci_dtm_enh_rx_start(rx_chan, index, phy);
}
int
ble_gap_rd_all_local_supp_features(uint8_t *status, uint8_t *max_page, uint8_t *le_features)
{
return ble_hs_hci_rd_all_local_supp_features(status, max_page, le_features);
}
int
ble_gap_rd_all_remote_features(uint16_t conn_handle, uint8_t page_requested)
{
return ble_hs_hci_rd_all_remote_features(conn_handle, page_requested);
}
void
ble_gap_deinit(void)
{
+4
View File
@@ -199,6 +199,10 @@ void ble_gap_reattempt_count(uint16_t conn_handle, uint8_t count);
#endif
void ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev);
void ble_gap_rx_rd_all_remote_feat(const struct ble_hci_ev_le_subev_rd_all_rem_feat *ev);
#if MYNEWT_VAL(BLE_MONITOR_ADV)
void ble_gap_rx_rd_monitor_adv_report(const struct ble_hci_ev_le_subev_monitor_adv_report *ev);
#endif
#ifdef __cplusplus
}
+45 -1
View File
@@ -127,6 +127,12 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_biginfo_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cis_estab_v2;
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
#if NIMBLE_BLE_CONNECT
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_all_rem_feat;
#endif
#if MYNEWT_VAL(BLE_MONITOR_ADV)
static ble_hs_hci_evt_le_fn ble_hci_ev_le_subev_monitor_adv_report;
#endif
/* Statistics */
struct host_hci_stats {
@@ -227,7 +233,6 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
[BLE_HCI_LE_SUBEV_CIS_ESTABLISHED_V2] = ble_hs_hci_evt_le_cis_estab_v2,
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING)
[BLE_HCI_LE_SUBEV_CS_RD_REM_SUPP_CAP_COMPLETE] = ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete,
[BLE_HCI_LE_SUBEV_CS_RD_REM_FAE_COMPLETE] = ble_hs_hci_evt_le_cs_rd_rem_fae_complete,
@@ -238,6 +243,12 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
[BLE_HCI_LE_SUBEV_CS_SUBEVENT_RESULT_CONTINUE] = ble_hs_hci_evt_le_cs_subevent_result_continue,
[BLE_HCI_LE_SUBEV_CS_TEST_END_COMPLETE] = ble_hs_hci_evt_le_cs_test_end_complete,
#endif
#if NIMBLE_BLE_CONNECT
[BLE_HCI_LE_SUBEV_RD_ALL_REM_FEAT] = ble_hs_hci_evt_le_rd_all_rem_feat,
#endif
#if MYNEWT_VAL(BLE_MONITOR_ADV)
[BLE_HCI_LE_SUBEV_MONITOR_ADV_REPORT] = ble_hci_ev_le_subev_monitor_adv_report,
#endif
};
#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
@@ -1546,6 +1557,39 @@ ble_hs_hci_evt_le_data_len_change(uint8_t subevent, const void *data,
return 0;
}
static int
ble_hs_hci_evt_le_rd_all_rem_feat(uint8_t subevent, const void *data,
unsigned int len)
{
const struct ble_hci_ev_le_subev_rd_all_rem_feat *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
ble_gap_rx_rd_all_remote_feat(ev);
return 0;
}
#endif
#if MYNEWT_VAL(BLE_MONITOR_ADV)
static int
ble_hci_ev_le_subev_monitor_adv_report(uint8_t subevent, const void *data,
unsigned int len)
{
const struct ble_hci_ev_le_subev_monitor_adv_report *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
ble_gap_rx_rd_monitor_adv_report(ev);
return 0;
}
#endif
int
+13
View File
@@ -140,6 +140,19 @@ int ble_hs_hci_dtm_enh_tx_start(uint8_t tx_chan, uint8_t test_data_len,
uint8_t payload, uint8_t phy);
int ble_hs_hci_dtm_stop(void);
int ble_hs_hci_rd_all_local_supp_features(uint8_t *status, uint8_t *max_page,
uint8_t *le_features);
int ble_hs_hci_rd_all_remote_features(uint16_t conn_handle, uint8_t page_requested);
#if MYNEWT_VAL(BLE_MONITOR_ADV)
int ble_hs_hci_add_monitor_adv_list(uint8_t addr_type, uint8_t *addr, uint8_t rssi_low,
uint8_t rssi_high, uint8_t timeout);
int ble_hs_hci_rmv_monitor_adv_list(uint8_t addr_type, uint8_t *addr);
int ble_hs_hci_clear_monitor_adv_list(void);
int ble_hs_hci_read_monitor_adv_list_size(uint8_t *out_number);
int ble_hs_hci_enable_monitor_adv(uint8_t enable);
#endif
#ifdef __cplusplus
}
#endif
+111
View File
@@ -377,3 +377,114 @@ ble_hs_hci_set_host_feature(uint8_t bit_num, uint8_t bit_val)
BLE_HCI_OCF_LE_SET_HOST_FEATURE),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_rd_all_local_supp_features(uint8_t* status, uint8_t* max_page,
uint8_t *le_features)
{
struct ble_hci_le_rd_all_local_feat_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_ALL_LOCAL_SUP_FEAT), NULL, 0,
&rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
*status = rsp.status;
*max_page = rsp.max_page;
memcpy(le_features, rsp.le_features, 248);
return 0;
}
int
ble_hs_hci_rd_all_remote_features(uint16_t conn_handle, uint8_t page_requested)
{
struct ble_hci_le_rd_all_remote_feat_cp cmd;
if (page_requested > 0x0A) {
return BLE_HS_EINVAL;
}
cmd.conn_handle = htole16(conn_handle);
cmd.page_requested = page_requested;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_ALL_REMOTE_FEAT), &cmd, sizeof(cmd),
NULL, 0);
}
#if MYNEWT_VAL(BLE_MONITOR_ADV)
int
ble_hs_hci_add_monitor_adv_list(uint8_t addr_type, uint8_t *addr, uint8_t rssi_low,
uint8_t rssi_high, uint8_t timeout)
{
struct ble_hci_le_add_monitor_adv_list_cp cmd;
cmd.addr_type = addr_type;
memcpy(cmd.address, addr, 6);
cmd.rssi_low_threshold = rssi_low;
cmd.rssi_high_threshold = rssi_high;
cmd.timeout = timeout;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ADD_MONITOR_ADV_LIST), &cmd, sizeof(cmd),
NULL, 0);
}
int
ble_hs_hci_rmv_monitor_adv_list(uint8_t addr_type, uint8_t *addr)
{
struct ble_hci_le_rmv_monitor_adv_list_cp cmd;
cmd.addr_type = addr_type;
memcpy(cmd.address, addr, 6);
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RMV_MONITOR_ADV_LIST), &cmd, sizeof(cmd),
NULL, 0);
}
int
ble_hs_hci_clear_monitor_adv_list(void)
{
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_CLEAR_MONITOR_ADV_LIST), NULL, 0,
NULL, 0);
}
int
ble_hs_hci_read_monitor_adv_list_size(uint8_t *out_number)
{
int rc;
struct ble_hci_le_rd_monitor_adv_list_size_rp rsp;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_READ_MONITOR_ADV_LIST_SIZE), NULL, 0,
&rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
*out_number = rsp.number;
return 0;
}
int
ble_hs_hci_enable_monitor_adv(uint8_t enable)
{
struct ble_hci_le_enable_monitor_adv_cp cmd;
cmd.enable = enable;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ENABLE_MONITOR_ADV), &cmd, sizeof(cmd),
NULL, 0);
}
#endif
+13
View File
@@ -421,6 +421,19 @@ ble_hs_startup_le_set_evmask_tx(void)
}
#endif
if (version >= BLE_HCI_VER_BCS_6_0) {
/**
* Enable following LE events:
* 0x0000040000000000 LE Read All Remote Features Complete event
* 0x0008000000000000 LE Monitored Advertisers Report event
*/
#if MYNEWT_VAL(BLE_MONITOR_ADV)
mask |= 0x0008000000000000;
#endif
mask |= 0x0000040000000000;
}
cmd.event_mask = htole64(mask);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+66
View File
@@ -1368,6 +1368,19 @@ struct ble_hci_le_set_periodic_adv_params_v2 {
uint8_t num_response_slots;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_RD_ALL_LOCAL_SUP_FEAT (0x0087)
struct ble_hci_le_rd_all_local_feat_rp {
uint8_t status;
uint8_t max_page;
uint8_t le_features[248];
} __attribute__((packed));
#define BLE_HCI_OCF_LE_RD_ALL_REMOTE_FEAT (0x0088)
struct ble_hci_le_rd_all_remote_feat_cp {
uint16_t conn_handle;
uint8_t page_requested;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_CS_RD_LOC_SUPP_CAP (0x0089)
struct ble_hci_le_cs_rd_loc_supp_cap_rp {
uint8_t num_config_supported;
@@ -1542,6 +1555,34 @@ struct ble_hci_le_cs_test_cp {
#define BLE_HCI_OCF_LE_CS_TEST_END (0x0096)
#define BLE_HCI_OCF_LE_ADD_MONITOR_ADV_LIST (0x0098)
struct ble_hci_le_add_monitor_adv_list_cp {
uint8_t addr_type;
uint8_t address[6];
uint8_t rssi_low_threshold;
uint8_t rssi_high_threshold;
uint8_t timeout;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_RMV_MONITOR_ADV_LIST (0x0099)
struct ble_hci_le_rmv_monitor_adv_list_cp {
uint8_t addr_type;
uint8_t address[6];
} __attribute__((packed));
#define BLE_HCI_OCF_LE_CLEAR_MONITOR_ADV_LIST (0x009A)
#define BLE_HCI_OCF_LE_READ_MONITOR_ADV_LIST_SIZE (0x009B)
struct ble_hci_le_rd_monitor_adv_list_size_rp {
uint8_t number;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_ENABLE_MONITOR_ADV (0x009C)
struct ble_hci_le_enable_monitor_adv_cp {
uint8_t enable;
} __attribute__((packed));
/* --- Vendor specific commands (OGF 0x003F) */
/* Read Random Static Address */
#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0001))
@@ -2547,6 +2588,24 @@ struct ble_hci_ev_le_subev_cis_established_v2 {
uint8_t framing;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_RD_ALL_REM_FEAT (0x2B)
struct ble_hci_ev_le_subev_rd_all_rem_feat {
uint8_t subev_code;
uint8_t status;
uint16_t conn_handle;
uint8_t max_remote_page;
uint8_t max_valid_page;
uint8_t le_features[248];
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_MONITOR_ADV_REPORT (0x34)
struct ble_hci_ev_le_subev_monitor_adv_report {
uint8_t subev_code;
uint8_t addr_type;
uint8_t address[6];
uint8_t condition;
} __attribute__((packed));
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
// LE vendor hci event
#define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0
@@ -2726,6 +2785,7 @@ struct ble_hci_ev_le_subev_cs_test_end_complete {
#define BLE_HCI_VER_BCS_5_2 (11)
#define BLE_HCI_VER_BCS_5_3 (12)
#define BLE_HCI_VER_BCS_5_4 (13)
#define BLE_HCI_VER_BCS_6_0 (14)
#define BLE_LMP_VER_BCS_1_0b (0)
#define BLE_LMP_VER_BCS_1_1 (1)
@@ -2741,6 +2801,7 @@ struct ble_hci_ev_le_subev_cs_test_end_complete {
#define BLE_LMP_VER_BCS_5_2 (11)
#define BLE_LMP_VER_BCS_5_3 (12)
#define BLE_LMP_VER_BCS_5_4 (13)
#define BLE_LMP_VER_BCS_6_0 (14)
/* selected HCI and LMP version */
#if MYNEWT_VAL(BLE_VERSION) == 50
@@ -2758,6 +2819,11 @@ struct ble_hci_ev_le_subev_cs_test_end_complete {
#elif MYNEWT_VAL(BLE_VERSION) == 54
#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_4
#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_4
#elif MYNEWT_VAL(BLE_VERSION) == 60
#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_6_0
#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_6_0
#else
#error Unsupported BLE_VERSION selected
#endif
#define BLE_HCI_DATA_HDR_SZ 4