mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-15 05:30:03 +00:00
nimble/gap: Add support for handling extended advertising event
X-Original-Commit: 0429b5e67e1a9cdfd832463eac2ebab85870f26a
This commit is contained in:
@@ -112,6 +112,7 @@ struct hci_conn_update;
|
||||
#define BLE_GAP_EVENT_MTU 15
|
||||
#define BLE_GAP_EVENT_IDENTITY_RESOLVED 16
|
||||
#define BLE_GAP_EVENT_PHY_UPDATE_COMPLETE 17
|
||||
#define BLE_GAP_EVENT_EXT_DISC 18
|
||||
|
||||
/*** Reason codes for the subscribe GAP event. */
|
||||
|
||||
@@ -217,6 +218,28 @@ struct ble_gap_passkey_params {
|
||||
uint32_t numcmp;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
struct ble_gap_ext_disc_desc {
|
||||
/*** Common fields. */
|
||||
uint8_t props;
|
||||
uint8_t data_status;
|
||||
uint8_t legacy_event_type;
|
||||
ble_addr_t addr;
|
||||
int8_t rssi;
|
||||
uint8_t tx_power;
|
||||
uint8_t sid;
|
||||
uint8_t prim_phy;
|
||||
uint8_t sec_phy;
|
||||
uint8_t length_data;
|
||||
uint8_t *data;
|
||||
/***
|
||||
* LE direct advertising report fields; direct_addr is BLE_ADDR_ANY if
|
||||
* direct address fields are not present.
|
||||
*/
|
||||
ble_addr_t direct_addr;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ble_gap_disc_desc {
|
||||
/*** Common fields. */
|
||||
uint8_t event_type;
|
||||
@@ -230,9 +253,6 @@ struct ble_gap_disc_desc {
|
||||
* direct address fields are not present.
|
||||
*/
|
||||
ble_addr_t direct_addr;
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
uint8_t tx_power;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -293,6 +313,14 @@ struct ble_gap_event {
|
||||
*/
|
||||
struct ble_gap_disc_desc disc;
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/**
|
||||
* Represents an extended advertising report received during a discovery
|
||||
* procedure. Valid for the following event types:
|
||||
* o BLE_GAP_EVENT_EXT_DISC
|
||||
*/
|
||||
struct ble_gap_ext_disc_desc ext_disc;
|
||||
#endif
|
||||
/**
|
||||
* Represents an attempt to update a connection's parameters. If the
|
||||
* attempt was successful, the connection's descriptor reflects the
|
||||
|
||||
+60
-28
@@ -665,8 +665,15 @@ ble_gap_master_connect_cancelled(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ble_gap_is_extended_disc(void)
|
||||
{
|
||||
return ble_gap_master.disc.extended;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_gap_disc_report(struct ble_gap_disc_desc *desc)
|
||||
ble_gap_disc_report(void *desc)
|
||||
{
|
||||
struct ble_gap_master_state state;
|
||||
struct ble_gap_event event;
|
||||
@@ -675,8 +682,17 @@ ble_gap_disc_report(struct ble_gap_disc_desc *desc)
|
||||
|
||||
if (state.cb != NULL) {
|
||||
memset(&event, 0, sizeof event);
|
||||
event.type = BLE_GAP_EVENT_DISC;
|
||||
event.disc = *desc;
|
||||
if (ble_gap_is_extended_disc()) {
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
event.type = BLE_GAP_EVENT_EXT_DISC;
|
||||
event.ext_disc = *((struct ble_gap_ext_disc_desc *)desc);
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
} else {
|
||||
event.type = BLE_GAP_EVENT_DISC;
|
||||
event.disc = *((struct ble_gap_disc_desc *)desc);
|
||||
}
|
||||
|
||||
state.cb(&event, state.cb_arg);
|
||||
}
|
||||
@@ -1114,6 +1130,33 @@ ble_gap_accept_slave_conn(uint8_t addr_type, uint8_t *addr)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_gap_rx_adv_report_sanity_check(uint8_t *adv_data, uint8_t adv_data_len)
|
||||
{
|
||||
const struct ble_hs_adv_field *flags;
|
||||
int rc;
|
||||
|
||||
STATS_INC(ble_gap_stats, rx_adv_report);
|
||||
|
||||
if (ble_gap_master.op != BLE_GAP_OP_M_DISC) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If a limited discovery procedure is active, discard non-limited
|
||||
* advertisements.
|
||||
*/
|
||||
if (ble_gap_master.disc.limited) {
|
||||
rc = ble_hs_adv_find_field(BLE_HS_ADV_TYPE_FLAGS, adv_data,
|
||||
adv_data_len, &flags);
|
||||
if ((rc == 0) && (flags->length == 2) &&
|
||||
!(flags->value[0] & BLE_HS_ADV_F_DISC_LTD)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
|
||||
{
|
||||
@@ -1121,30 +1164,24 @@ ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
|
||||
return;
|
||||
#endif
|
||||
|
||||
const struct ble_hs_adv_field *flags;
|
||||
int rc;
|
||||
|
||||
STATS_INC(ble_gap_stats, rx_adv_report);
|
||||
|
||||
if (ble_gap_master.op != BLE_GAP_OP_M_DISC) {
|
||||
if (ble_gap_rx_adv_report_sanity_check(desc->data, desc->length_data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If a limited discovery procedure is active, discard non-limited
|
||||
* advertisements.
|
||||
*/
|
||||
if (ble_gap_master.disc.limited) {
|
||||
rc = ble_hs_adv_find_field(BLE_HS_ADV_TYPE_FLAGS, desc->data,
|
||||
desc->length_data, &flags);
|
||||
if ((rc == 0) && (flags->length == 2) &&
|
||||
!(flags->value[0] & BLE_HS_ADV_F_DISC_LTD)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ble_gap_disc_report(desc);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
void
|
||||
ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc)
|
||||
{
|
||||
if (ble_gap_rx_adv_report_sanity_check(desc->data, desc->length_data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ble_gap_disc_report(desc);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Processes an incoming connection-complete HCI event.
|
||||
*/
|
||||
@@ -2207,12 +2244,6 @@ ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ble_gap_is_extended_disc(void)
|
||||
{
|
||||
return ble_gap_master.disc.extended;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the discovery procedure currently in progress. A success return
|
||||
* code indicates that scanning has been fully aborted; a new discovery or
|
||||
@@ -2516,6 +2547,7 @@ ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
|
||||
|
||||
ble_gap_master.disc.limited = params.limited;
|
||||
ble_gap_master.cb = cb;
|
||||
ble_gap_master.disc.extended = 0;
|
||||
ble_gap_master.cb_arg = cb_arg;
|
||||
|
||||
BLE_HS_LOG(INFO, "GAP procedure initiated: discovery; ");
|
||||
@@ -2636,7 +2668,7 @@ ble_gap_ext_conn_create_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr,
|
||||
const struct ble_gap_conn_params *phy_coded_conn_params)
|
||||
{
|
||||
uint8_t buf[BLE_HCI_CMD_HDR_LEN + sizeof(struct hci_ext_create_conn)];
|
||||
struct hci_ext_create_conn hcc = {};
|
||||
struct hci_ext_create_conn hcc = {0};
|
||||
int rc;
|
||||
|
||||
if (peer_addr == NULL) {
|
||||
|
||||
@@ -74,6 +74,9 @@ extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
|
||||
#define BLE_GAP_CONN_MODE_MAX 3
|
||||
#define BLE_GAP_DISC_MODE_MAX 3
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc);
|
||||
#endif
|
||||
void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
|
||||
int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt);
|
||||
void ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt);
|
||||
|
||||
@@ -47,6 +47,7 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_lt_key_req;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_parm_req;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_phy_update_complete;
|
||||
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_ext_adv_rpt;
|
||||
|
||||
/* Statistics */
|
||||
struct host_hci_stats
|
||||
@@ -95,6 +96,7 @@ static const struct ble_hs_hci_evt_le_dispatch_entry
|
||||
{ BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT, ble_hs_hci_evt_le_dir_adv_rpt },
|
||||
{ BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE,
|
||||
ble_hs_hci_evt_le_phy_update_complete },
|
||||
{ BLE_HCI_LE_SUBEV_EXT_ADV_RPT, ble_hs_hci_evt_le_ext_adv_rpt },
|
||||
};
|
||||
|
||||
#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
|
||||
@@ -357,7 +359,7 @@ ble_hs_hci_evt_le_adv_rpt_first_pass(uint8_t *data, int len)
|
||||
static int
|
||||
ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||
{
|
||||
struct ble_gap_disc_desc desc;
|
||||
struct ble_gap_disc_desc desc = {0};
|
||||
uint8_t num_reports;
|
||||
int off;
|
||||
int rc;
|
||||
@@ -401,7 +403,7 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||
static int
|
||||
ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||
{
|
||||
struct ble_gap_disc_desc desc;
|
||||
struct ble_gap_disc_desc desc = {0};
|
||||
uint8_t num_reports;
|
||||
int suboff;
|
||||
int off;
|
||||
@@ -453,6 +455,85 @@ ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
static int
|
||||
ble_hs_hci_decode_legacy_type(uint16_t evt_type)
|
||||
{
|
||||
switch (evt_type) {
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
|
||||
return BLE_HCI_ADV_TYPE_ADV_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
|
||||
return BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
|
||||
return BLE_HCI_ADV_TYPE_ADV_SCAN_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND:
|
||||
return BLE_HCI_ADV_TYPE_ADV_NONCONN_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND:
|
||||
return BLE_HCI_ADV_TYPE_ADV_SCAN_IND;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
struct ble_gap_ext_disc_desc desc = {0};
|
||||
struct hci_ext_adv_report *ext_adv;
|
||||
struct hci_ext_adv_report_param *params;
|
||||
int num_reports;
|
||||
int i;
|
||||
int legacy_event_type;
|
||||
|
||||
if (len < sizeof(*ext_adv)) {
|
||||
return BLE_HS_EBADDATA;
|
||||
}
|
||||
|
||||
ext_adv = (struct hci_ext_adv_report *) data;
|
||||
num_reports = ext_adv->num_reports;
|
||||
if (num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
|
||||
num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
|
||||
|
||||
return BLE_HS_EBADDATA;
|
||||
}
|
||||
|
||||
if (len < (sizeof(*ext_adv) + ext_adv->num_reports * sizeof(*params))) {
|
||||
return BLE_HS_ECONTROLLER;
|
||||
}
|
||||
|
||||
params = &ext_adv->params[0];
|
||||
for (i = 0; i < num_reports; i++) {
|
||||
desc.props = (params->evt_type) & 0xFF;
|
||||
if (desc.props & BLE_HCI_ADV_LEGACY_MASK) {
|
||||
legacy_event_type = ble_hs_hci_decode_legacy_type(params->evt_type);
|
||||
if (legacy_event_type < 0) {
|
||||
params += 1;
|
||||
continue;
|
||||
}
|
||||
desc.legacy_event_type = legacy_event_type;
|
||||
} else {
|
||||
desc.data_status = params->evt_type >> 8;
|
||||
}
|
||||
desc.addr.type = params->addr_type;
|
||||
memcpy(desc.addr.val, params->addr, 6);
|
||||
desc.length_data = params->adv_data_len;
|
||||
desc.data = params->adv_data;
|
||||
desc.rssi = params->rssi;
|
||||
desc.tx_power = params->tx_power;
|
||||
memcpy(desc.direct_addr.val, params->dir_addr, 6);
|
||||
desc.direct_addr.type = params->dir_addr_type;
|
||||
desc.sid = params->sid;
|
||||
desc.prim_phy = params->prim_phy;
|
||||
desc.sec_phy = params->sec_phy;
|
||||
ble_gap_rx_ext_adv_report(&desc);
|
||||
params += 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, uint8_t *data, int len)
|
||||
{
|
||||
|
||||
@@ -215,6 +215,10 @@ extern "C" {
|
||||
#define BLE_HCI_ADV_SCAN_RSP_MASK (0x0008)
|
||||
#define BLE_HCI_ADV_LEGACY_MASK (0x0010)
|
||||
|
||||
#define BLE_HCI_ADV_COMPLETED (0x00)
|
||||
#define BLE_HCI_ADV_INCOMPLETE (0x01)
|
||||
#define BLE_HCI_ADV_CORRUPTED (0x10)
|
||||
|
||||
/* Own address types */
|
||||
#define BLE_HCI_ADV_OWN_ADDR_PUBLIC (0)
|
||||
#define BLE_HCI_ADV_OWN_ADDR_RANDOM (1)
|
||||
@@ -802,6 +806,29 @@ struct hci_ext_create_conn
|
||||
uint8_t init_phy_mask;
|
||||
struct hci_ext_conn_params params[3];
|
||||
};
|
||||
|
||||
struct hci_ext_adv_report_param {
|
||||
uint16_t evt_type;
|
||||
uint8_t addr_type;
|
||||
uint8_t addr[6];
|
||||
uint8_t prim_phy;
|
||||
uint8_t sec_phy;
|
||||
uint8_t sid;
|
||||
uint8_t tx_power;
|
||||
int8_t rssi;
|
||||
uint16_t per_adv_itvl;
|
||||
uint8_t dir_addr_type;
|
||||
uint8_t dir_addr[6];
|
||||
uint8_t adv_data_len;
|
||||
uint8_t adv_data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hci_ext_adv_report {
|
||||
/* We support one report per event for now */
|
||||
uint8_t subevt;
|
||||
uint8_t num_reports;
|
||||
struct hci_ext_adv_report_param params[0];
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
/* LE connection update command (ocf=0x0013). */
|
||||
|
||||
Reference in New Issue
Block a user