feat(nimble): Added PAwR support for nimble

This commit is contained in:
Abhinav Kudnar
2024-12-10 15:44:26 +05:30
committed by Sumeet Singh
parent 97287467de
commit c4b3bec003
6 changed files with 1036 additions and 16 deletions
+262
View File
@@ -161,6 +161,8 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_LINK_ESTAB 32
#define BLE_GAP_EVENT_AUTHORIZE 33
#define BLE_GAP_EVENT_EATT 34
#define BLE_GAP_EVENT_PER_SUBEV_DATA_REQ 35
#define BLE_GAP_EVENT_PER_SUBEV_RESP 36
/* DTM events */
#define BLE_GAP_DTM_TX_START_EVT 0
@@ -505,6 +507,66 @@ struct ble_gap_repeat_pairing {
uint8_t new_bonding:1;
};
#define BLE_GAP_PER_ADV_DATA_STATUS_COMPLETE 0x00
#define BLE_GAP_PER_ADV_DATA_STATUS_INCOMPLETE 0x01
#define BLE_GAP_PER_ADV_DATA_STATUS_TRUNCATED 0x02
#define BLE_GAP_PER_ADV_DATA_STATUS_RX_FAILED 0xFF
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
struct ble_gap_periodic_adv_response {
/** The subevent in which the response is received */
uint8_t subevent;
/** Status of the subevent indication.
*
* 0 if subevent indication was transmitted.
* 1 if subevent indication was not transmitted.
* All other values RFU.
*/
/** The adv handle of the adv */
uint8_t adv_handle;
uint8_t tx_status;
/** The TX power of the response in dBm */
int8_t tx_power;
/** The RSSI of the response in dBm */
int8_t rssi;
/** The Constant Tone Extension (CTE) of the advertisement */
uint8_t cte_type;
/** The response slot */
uint8_t response_slot;
/** Data status */
uint8_t data_status;
/** Data length */
uint8_t data_length;
/** response data */
const uint8_t *data;
};
struct ble_gap_periodic_adv_response_params {
/** The periodic advertsing event for which response shall be sent in */
uint16_t request_event;
/** The request subevent for which response shall be sent in */
uint8_t request_subevent;
/** The subevent the response shall be sent in */
uint8_t response_subevent;
/** The response slot the response shall be sent in */
uint8_t response_slot;
};
#endif
/**
* Represents a GAP-related event. When such an event occurs, the host
* notifies the application by passing an instance of this structure to an
@@ -538,6 +600,23 @@ struct ble_gap_event {
/** The handle of the relevant connection. */
uint16_t conn_handle;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
/*
* Adv_Handle is used to identify an advertising set.
* If the connection is established from periodic advertising with responses
* and Role is 0x00 then the Advertising_Handle parameter shall be set
* according to the periodic advertising train the connection was established from
*/
uint8_t adv_handle;
/*
* Sync_Handle identifying the periodic advertising train
* If the connection is established from periodic advertising with responses
* and Role is 0x01, then the Sync_Handle parameter shall be set according
* to the periodic advertising train the connection was established from
*/
uint16_t sync_handle;
#endif
} connect;
/**
@@ -939,6 +1018,18 @@ struct ble_gap_event {
/** Advertiser clock accuracy */
uint8_t adv_clk_accuracy;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
/** Number of subevents. If zero, the periodic advertiser will be a broadcaster,
* without responses.
*/
uint8_t num_subevents;
/** Interval between subevents (N * 1.25 ms) */
uint8_t subevent_interval;
/** Time between the advertising packet and the first response slot (N * 1.25 ms). */
uint8_t response_slot_delay;
/** Time between response slots (N * 0.125 ms) */
uint8_t response_slot_spacing;
#endif
} periodic_sync;
/**
@@ -956,10 +1047,24 @@ struct ble_gap_event {
/** Received signal strength indication in dBm (127 if unavailable) */
int8_t rssi;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
/**
* It indicates the periodic advertising event counter (paEventCounter) of
* the event that the periodic advertising packet was received in.
*/
uint16_t event_counter;
/**
* It indicates Periodic Advertising with Responses subevent in which
* the periodic advertising packet was received in.
*/
uint8_t subevent;
#endif
/** Advertising data status, can be one of following constants:
* - BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE
* - BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE
* - BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED
* - BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED
*/
uint8_t data_status;
@@ -1041,6 +1146,18 @@ struct ble_gap_event {
/** Advertiser clock accuracy */
uint8_t adv_clk_accuracy;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
/** Number of subevents. If zero, the periodic advertiser will be a broadcaster,-
* without responses.
*/
uint8_t num_subevents;
/** Interval between subevents (N * 1.25 ms) */
uint8_t subevent_interval;
/** Time between the advertising packet and the first response slot (N * 1.25 ms). */
uint8_t response_slot_delay;
/** Time between response slots (N * 0.125 ms) */
uint8_t response_slot_spacing;
#endif
} periodic_transfer;
#endif
@@ -1119,6 +1236,30 @@ struct ble_gap_event {
uint16_t supervision_tmo;
} subrate_change;
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
/**
* Represents a periodic advertising subevent data request
* with parameters valid for the following event types:
* o BLE_GAP_EVENT_PER_SUBEV_DATA_REQ
*/
struct {
/** Advertising handle */
uint8_t adv_handle;
/** Subevent start */
uint8_t subevent_start;
/** Number of subevents */
uint8_t subevent_data_count;
} periodic_adv_subev_data_req;
/**
* Represents a periodic advertising response
* with parameters valid for the following event types:
* o BLE_GAP_EVENT_PER_SUBEV_RESP
*/
struct ble_gap_periodic_adv_response periodic_adv_response;
#endif
/**
* GATT Authorization Event. Ask the user to authorize a GATT
@@ -1705,6 +1846,34 @@ struct ble_gap_periodic_adv_params {
* defaults
*/
uint16_t itvl_max;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
/** Number of subevents
* If zero, the periodic advertiser will be a broadcaster, without responses.
*/
uint8_t num_subevents;
/** Interval between subevents (N * 1.25 ms)
* Shall be between 7.5ms and 318.75 ms.
*/
uint8_t subevent_interval;
/** Time between the advertising packet in a subevent and the
* first response slot (N * 1.25 ms)
*
*/
uint8_t response_slot_delay;
/** Time between response slots (N * 0.125 ms)
* Shall be between 0.25 and 31.875 ms.
*/
uint8_t response_slot_spacing;
/** Number of subevent response slots
* If zero, response_slot_delay and response_slot_spacing are ignored.
*/
uint8_t num_response_slots;
#endif /* PERIODIC_ADV_WITH_RESPONSES */
};
#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH)
@@ -1748,6 +1917,22 @@ struct ble_gap_periodic_sync_params {
#endif
};
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
struct ble_gap_set_periodic_adv_subev_data_params {
/** The subevent to set data for */
uint8_t subevent;
/** The first response slot to listen to */
uint8_t response_slot_start;
/** The number of response slots to listen to */
uint8_t response_slot_count;
/** The data to send */
struct os_mbuf *data;
};
#endif
/**
* Configure periodic advertising for specified advertising instance
*
@@ -1990,6 +2175,18 @@ int ble_gap_clear_periodic_adv_list(void);
* @return 0 on success; nonzero on failure.
*/
int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size);
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
int
ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents,
const struct ble_gap_set_periodic_adv_subev_data_params *params);
int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle,
struct ble_gap_periodic_adv_response_params *param,
struct os_mbuf *data);
int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power,
uint8_t num_subevents, uint8_t *subevents);
#endif
#endif
@@ -2135,6 +2332,71 @@ int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
const struct ble_gap_conn_params *params,
ble_gap_event_fn *cb, void *cb_arg);
/**
* Initiates an Sync connect procedure for PAwR.
*
* @param own_addr_type The type of address the stack should use for
* itself during connection establishment.
* - BLE_OWN_ADDR_PUBLIC
* - BLE_OWN_ADDR_RANDOM
* - BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
* - BLE_OWN_ADDR_RPA_RANDOM_DEFAULT
* @param advertising_handle The advertising_Handle identifying the periodic advertising train
* Range: 0x00 to 0xEF or 0xFF
* @param subevent The Subevent parameter is used to identify the subevent where a connection
request shall be initiated from a periodic advertising train.
The Advertising_Handle and Subevent parameters
shall be set to 0xFF if these
parameters are not used.
* @param peer_addr The address of the peer to connect to.
* If this parameter is NULL, the white list
* is used.
* @param duration_ms The duration of the discovery procedure.
* On expiration, the procedure ends and a
* BLE_GAP_EVENT_DISC_COMPLETE event is
* reported. Units are milliseconds.
* @param phy_mask Define on which PHYs connection attempt should
* be done
* @param phy_1m_conn_params Additional arguments specifying the
* particulars of the connect procedure. When
* BLE_GAP_LE_PHY_1M_MASK is set in phy_mask
* this parameter can be specify to null for
* default values.
* @param phy_2m_conn_params Additional arguments specifying the
* particulars of the connect procedure. When
* BLE_GAP_LE_PHY_2M_MASK is set in phy_mask
* this parameter can be specify to null for
* default values.
* @param phy_coded_conn_params Additional arguments specifying the
* particulars of the connect procedure. When
* BLE_GAP_LE_PHY_CODED_MASK is set in
* phy_mask this parameter can be specify to
* null for default values.
* @param cb The callback to associate with this connect
* procedure. When the connect procedure
* completes, the result is reported through
* this callback. If the connect procedure
* succeeds, the connection inherits this
* callback as its event-reporting mechanism.
* @param cb_arg The optional argument to pass to the callback
* function.
*
* @return 0 on success;
* BLE_HS_EALREADY if a connection attempt is
* already in progress;
* BLE_HS_EBUSY if initiating a connection is not
* possible because scanning is in progress;
* BLE_HS_EDONE if the specified peer is already
* connected;
* Other nonzero on error.
*/
int ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle,
uint8_t subevent, const ble_addr_t *peer_addr,
int32_t duration_ms, uint8_t phy_mask,
const struct ble_gap_conn_params *phy_1m_conn_params,
const struct ble_gap_conn_params *phy_2m_conn_params,
const struct ble_gap_conn_params *phy_coded_conn_params,
ble_gap_event_fn *cb, void *cb_arg);
/**
* Initiates an extended connect procedure.
*
+548 -12
View File
@@ -106,7 +106,7 @@
#define BLE_GAP_UPDATE_TIMEOUT_MS 40000 /* ms */
#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
static const struct ble_gap_conn_params ble_gap_conn_params_dflt = {
.scan_itvl = 0x0010,
.scan_window = 0x0010,
@@ -1314,7 +1314,8 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
}
#if NIMBLE_BLE_SCAN
#if (NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)) || \
(MYNEWT_VAL(BLE_ROLE_CENTRAL) && MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT))
static void
ble_gap_master_set_timer(uint32_t ticks_from_now)
{
@@ -1658,11 +1659,16 @@ ble_gap_accept_master_conn(void)
static int
ble_gap_accept_slave_conn(uint8_t instance)
{
int rc;
int rc = 0;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
if (instance >= BLE_ADV_INSTANCES) {
rc = BLE_HS_ENOENT;
rc = BLE_HS_ENOENT;
}
#else
if (instance >= BLE_ADV_INSTANCES) {
rc = BLE_HS_ENOENT;
} else if (!ble_gap_adv_active_instance(instance)) {
rc = BLE_HS_ENOENT;
} else {
if (ble_gap_slave[instance].connectable) {
@@ -1676,6 +1682,7 @@ ble_gap_accept_slave_conn(uint8_t instance)
STATS_INC(ble_gap_stats, connect_slv);
}
#endif
return rc;
}
#endif
@@ -1810,7 +1817,6 @@ ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev)
/* Periodic adv events */
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
void
ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev)
{
@@ -1845,6 +1851,12 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv
event.periodic_sync.adv_phy = ev->phy;
event.periodic_sync.per_adv_ival = ev->interval;
event.periodic_sync.adv_clk_accuracy = ev->aca;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
event.periodic_sync.num_subevents = ev->num_subevents;
event.periodic_sync.subevent_interval = ev->subevent_interval;
event.periodic_sync.response_slot_delay = ev->response_slot_delay;
event.periodic_sync.response_slot_spacing = ev->response_slot_spacing;
#endif
ble_hs_periodic_sync_insert(ble_gap_sync.psync);
} else {
@@ -1896,6 +1908,10 @@ ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *e
event.periodic_report.data_status = ev->data_status;
event.periodic_report.data_length = ev->data_len;
event.periodic_report.data = ev->data;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
event.periodic_report.event_counter = ev->event_counter;
event.periodic_report.subevent = ev->subevent;
#endif
/* TODO should we allow for listener too? this can be spammy and is more
* like ACL data, not general event
@@ -2076,7 +2092,12 @@ ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_
event.periodic_transfer.adv_phy = ev->phy;
event.periodic_transfer.per_adv_itvl = le16toh(ev->interval);
event.periodic_transfer.adv_clk_accuracy = ev->aca;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
event.periodic_transfer.num_subevents = ev->num_subevents;
event.periodic_transfer.subevent_interval = ev->subevent_interval;
event.periodic_transfer.response_slot_delay = ev->response_slot_delay;
event.periodic_transfer.response_slot_spacing = ev->response_slot_spacing;
#endif
ble_hs_unlock();
ble_gap_event_listener_call(&event);
@@ -2110,6 +2131,51 @@ ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev)
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
void
ble_gap_rx_periodic_adv_subev_data_req(const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev)
{
struct ble_gap_event event;
ble_gap_event_fn *cb;
void *cb_arg;
memset(&event, 0x0, sizeof event);
event.type = BLE_GAP_EVENT_PER_SUBEV_DATA_REQ;
event.periodic_adv_subev_data_req.adv_handle = ev->adv_handle;
event.periodic_adv_subev_data_req.subevent_start = ev->subevent_start;
event.periodic_adv_subev_data_req.subevent_data_count = ev->subevent_data_count;
ble_gap_slave_extract_cb(ev->adv_handle, &cb, &cb_arg);
if (cb != NULL) {
cb(&event, cb_arg);
}
ble_gap_event_listener_call(&event);
}
void
ble_gap_rx_periodic_adv_response(const struct ble_gap_periodic_adv_response resp)
{
struct ble_gap_event event;
ble_gap_event_fn *cb;
void *cb_arg;
memset(&event, 0x0, sizeof event);
event.type = BLE_GAP_EVENT_PER_SUBEV_RESP;
memcpy(&event.periodic_adv_response, &resp,
sizeof(struct ble_gap_periodic_adv_response));
ble_gap_slave_extract_cb(resp.adv_handle, &cb, &cb_arg);
if (cb != NULL) {
cb(&event, cb_arg);
}
ble_gap_event_listener_call(&event);
}
#endif
#if NIMBLE_BLE_CONNECT
static int
ble_gap_rd_rem_sup_feat_tx(uint16_t handle)
@@ -2214,6 +2280,21 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance)
conn->bhc_latency = evt->conn_latency;
conn->bhc_supervision_timeout = evt->supervision_timeout;
conn->bhc_master_clock_accuracy = evt->master_clk_acc;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
if (ble_gap_master.cb) {
conn->bhc_cb = ble_gap_master.cb;
conn->bhc_cb_arg = ble_gap_master.cb_arg;
conn->bhc_flags |= BLE_HS_CONN_F_MASTER;
conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type;
ble_gap_master_reset_state();
}
else {
conn->bhc_cb = ble_gap_slave[instance].cb;
conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg;
conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type;
ble_gap_slave_reset_state(instance);
}
#else
if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER) {
conn->bhc_cb = ble_gap_master.cb;
conn->bhc_cb_arg = ble_gap_master.cb_arg;
@@ -2229,6 +2310,7 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance)
#endif
ble_gap_slave_reset_state(instance);
}
#endif
conn->bhc_peer_addr.type = evt->peer_addr_type;
memcpy(conn->bhc_peer_addr.val, evt->peer_addr, 6);
@@ -2278,6 +2360,10 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance)
}
}
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
event.connect.sync_handle = evt->sync_handle;
event.connect.adv_handle = evt->adv_handle;
#endif
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, evt->connection_handle);
@@ -3966,7 +4052,11 @@ ble_gap_periodic_adv_params_tx(uint8_t instance,
const struct ble_gap_periodic_adv_params *params)
{
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
struct ble_hci_le_set_periodic_adv_params_v2 cmd;
#else
struct ble_hci_le_set_periodic_adv_params_cp cmd;
#endif
uint16_t opcode;
cmd.adv_handle = instance;
@@ -3987,8 +4077,19 @@ ble_gap_periodic_adv_params_tx(uint8_t instance,
cmd.props = 0;
}
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS);
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
cmd.num_subevents = params->num_subevents;
cmd.subevent_interval = params->subevent_interval;
cmd.response_slot_delay = params->response_slot_delay;
cmd.response_slot_spacing = params->response_slot_spacing;
cmd.num_response_slots = params->num_response_slots;
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS_V2);
#else
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS);
#endif
return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
}
@@ -4025,7 +4126,7 @@ ble_gap_periodic_adv_configure(uint8_t instance,
rc = ble_gap_periodic_adv_params_validate(params);
if (rc) {
return rc;
return rc;
}
ble_hs_lock();
@@ -4888,6 +4989,152 @@ ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size)
return 0;
}
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
static int
ble_gap_calc_periodic_adv_data_size(uint8_t num_subevents,
const struct ble_gap_set_periodic_adv_subev_data_params *params) {
int len = 0;
const struct ble_gap_set_periodic_adv_subev_data_params *param;
int raw_subev_size = sizeof(*param) - sizeof(struct os_mbuf*);
for(int i = 0; i < num_subevents; i++) {
param = params + i;
len += raw_subev_size;
len += OS_MBUF_PKTLEN(param->data);
}
return len;
}
int
ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents,
const struct ble_gap_set_periodic_adv_subev_data_params *params)
{
struct ble_hci_le_set_periodic_adv_subev_data_cp *cmd;
struct periodic_adv_subevents *subevents;
uint8_t len = ble_gap_calc_periodic_adv_data_size(num_subevents, params);
uint8_t buf[len + 2];
uint16_t opcode;
uint16_t subev_data_len;
int rc;
if (instance >= BLE_ADV_INSTANCES) {
rc = BLE_HS_EINVAL;
goto done;
}
if (!ble_hs_is_enabled()) {
rc = BLE_HS_EDISABLED;
goto done;
}
/* Check if we can set all of data in one hci command. */
if ((len + 2) >= 0xff) {
rc = BLE_HS_EINVAL;
goto done;
}
ble_hs_lock();
/* Periodic advertising cannot start unless it is configured before */
if (!ble_gap_slave[instance].periodic_configured) {
ble_hs_unlock();
rc = BLE_HS_EINVAL;
goto done;
}
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SUBEV_DATA);
cmd = (void *) buf;
subevents = cmd->subevents;
cmd->adv_handle = instance;
cmd->num_subevents = num_subevents;
for (int i = 0; i < num_subevents; i++) {
subevents->subevent = params[i].subevent;
subevents->response_slot_start = params[i].response_slot_start;
subevents->response_slot_count = params[i].response_slot_count;
ble_hs_mbuf_to_flat(params[i].data, subevents->subevent_data, OS_MBUF_PKTLEN(params[i].data),
(void*)&subev_data_len);
subevents->subevent_data_length = OS_MBUF_PKTLEN(params[i].data);
subevents = (struct periodic_adv_subevents *)(
(uint32_t)subevents + sizeof(struct periodic_adv_subevents) + subev_data_len);
}
rc = ble_hs_hci_cmd_tx(opcode, cmd, len + 2, NULL, 0);
if (rc != 0) {
ble_hs_unlock();
goto done;
}
ble_gap_slave[instance].periodic_op = BLE_GAP_OP_S_PERIODIC_ADV;
ble_hs_unlock();
done:
for (int i = 0; i < num_subevents; i++) {
os_mbuf_free_chain(params[i].data);
}
return rc;
}
int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle,
struct ble_gap_periodic_adv_response_params *param,
struct os_mbuf *data)
{
struct ble_hci_le_set_periodic_adv_response_data *cmd;
uint16_t opcode;
int len = sizeof(*cmd);
int data_len = OS_MBUF_PKTLEN(data);
uint8_t buf[len + data_len];
//!TODO: Check if we can set all of data in one hci command.
cmd = (void *) buf;
(void)memset(cmd, 0, sizeof(*cmd));
put_le16(&cmd->sync_handle, sync_handle);
put_le16(&cmd->request_event, param->request_event);
cmd->request_subevent = param->request_subevent;
cmd->response_subevent = param->response_subevent;
cmd->response_slot = param->response_slot;
cmd->response_data_length = data_len;
ble_hs_mbuf_to_flat(data, cmd->response_data, data_len, NULL);
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_RESPONSE_DATA);
return ble_hs_hci_cmd_tx(opcode, cmd, len + data_len, NULL, 0);
}
int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power,
uint8_t num_subevents, uint8_t *subevents)
{
struct ble_hci_le_set_periodic_adv_sync_subevent *cmd;
struct ble_hci_le_set_periodic_adv_sync_subevent_rp rsp;
struct ble_hs_periodic_sync *psync;
uint8_t cmd_buf[sizeof(*cmd) + num_subevents];
uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SYNC_SUBEVENT);
int rc;
psync = ble_hs_periodic_sync_find_by_handle(sync_handle);
if (!psync) {
ble_hs_unlock();
return BLE_HS_ENOTCONN;
}
cmd = (void *)cmd_buf;
put_le16(&cmd->sync_handle, sync_handle);
put_le16(&cmd->periodic_adv_properties, (uint16_t)(include_tx_power << 6));
cmd->num_subevents = num_subevents;
memcpy(cmd->subevents, subevents, num_subevents);
rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + num_subevents, &rsp, sizeof(rsp));
if (!rc) {
BLE_HS_DBG_ASSERT(le16toh(rsp.sync_handle) == sync_handle);
}
return rc;
}
#endif
#endif
/*****************************************************************************
@@ -5487,8 +5734,7 @@ ble_gap_subrate_req(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate
}
#endif
#if MYNEWT_VAL(BLE_EXT_ADV)
#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) || MYNEWT_VAL(BLE_EXT_ADV)
static int
ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params)
{
@@ -5532,6 +5778,243 @@ ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params)
return 0;
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
static int
ble_gap_ext_conn_create_conn_synced_tx(uint8_t own_addr_type,
uint8_t advertising_handle, uint8_t subevent,
const ble_addr_t *peer_addr, uint8_t phy_mask,
const struct ble_gap_conn_params *phy_1m_conn_params,
const struct ble_gap_conn_params *phy_2m_conn_params,
const struct ble_gap_conn_params *phy_coded_conn_params)
{
struct ble_hci_le_ext_create_conn_v2_cp *cmd;
struct conn_params *params;
uint8_t buf[sizeof(*cmd) + 3 * sizeof(*params)];
uint8_t len = sizeof(*cmd);
int rc;
/* Check own addr type */
if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
BLE_HCI_LE_PHY_2M_PREF_MASK |
BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd = (void *) buf;
params = cmd->conn_params;
if (peer_addr == NULL) {
/* Application wants to connect to any device in the white list. The
* peer address type and peer address fields are ignored by the
* controller; fill them with dummy values.
*/
cmd->filter_policy = BLE_HCI_CONN_FILT_USE_WL;
cmd->peer_addr_type = 0;
memset(cmd->peer_addr, 0, sizeof(cmd->peer_addr));
} else {
/* Check peer addr type */
if (peer_addr->type > BLE_HCI_CONN_PEER_ADDR_MAX) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd->filter_policy = BLE_HCI_CONN_FILT_NO_WL;
cmd->peer_addr_type = peer_addr->type;
memcpy(cmd->peer_addr, peer_addr->val, sizeof(cmd->peer_addr));
}
cmd->own_addr_type = own_addr_type;
cmd->init_phy_mask = phy_mask;
cmd->adv_handle = advertising_handle;
cmd->subevent = subevent;
if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) {
rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_1M, phy_1m_conn_params);
if (rc) {
return rc;
}
params->scan_itvl = htole16(phy_1m_conn_params->scan_itvl);
params->scan_window = htole16(phy_1m_conn_params->scan_window);
params->conn_min_itvl = htole16(phy_1m_conn_params->itvl_min);
params->conn_max_itvl = htole16(phy_1m_conn_params->itvl_max);
params->conn_latency = htole16(phy_1m_conn_params->latency);
params->supervision_timeout = htole16(phy_1m_conn_params->supervision_timeout);
params->min_ce = htole16(phy_1m_conn_params->min_ce_len);
params->max_ce = htole16(phy_1m_conn_params->max_ce_len);
params++;
len += sizeof(*params);
}
if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) {
rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_2M, phy_2m_conn_params);
if (rc) {
return rc;
}
params->scan_itvl = htole16(phy_2m_conn_params->scan_itvl);
params->scan_window = htole16(phy_2m_conn_params->scan_window);
params->conn_min_itvl = htole16(phy_2m_conn_params->itvl_min);
params->conn_max_itvl = htole16(phy_2m_conn_params->itvl_max);
params->conn_latency = htole16(phy_2m_conn_params->latency);
params->supervision_timeout = htole16(phy_2m_conn_params->supervision_timeout);
params->min_ce = htole16(phy_2m_conn_params->min_ce_len);
params->max_ce = htole16(phy_2m_conn_params->max_ce_len);
params++;
len += sizeof(*params);
}
if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) {
rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_CODED, phy_coded_conn_params);
if (rc) {
return rc;
}
params->scan_itvl = htole16(phy_coded_conn_params->scan_itvl);
params->scan_window = htole16(phy_coded_conn_params->scan_window);
params->conn_min_itvl = htole16(phy_coded_conn_params->itvl_min);
params->conn_max_itvl = htole16(phy_coded_conn_params->itvl_max);
params->conn_latency = htole16(phy_coded_conn_params->latency);
params->supervision_timeout = htole16(phy_coded_conn_params->supervision_timeout);
params->min_ce = htole16(phy_coded_conn_params->min_ce_len);
params->max_ce = htole16(phy_coded_conn_params->max_ce_len);
params++;
len += sizeof(*params);
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_LE_EXT_CREATE_CONN_V2),
cmd, len, NULL, 0);
}
int
ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle,
uint8_t subevent, const ble_addr_t *peer_addr,
int32_t duration_ms, uint8_t phy_mask,
const struct ble_gap_conn_params *phy_1m_conn_params,
const struct ble_gap_conn_params *phy_2m_conn_params,
const struct ble_gap_conn_params *phy_coded_conn_params,
ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
STATS_INC(ble_gap_stats, initiate);
ble_hs_lock();
if (ble_gap_conn_active()) {
rc = BLE_HS_EALREADY;
goto done;
}
if (ble_gap_disc_active()) {
rc = BLE_HS_EBUSY;
goto done;
}
if (!ble_hs_is_enabled()) {
rc = BLE_HS_EDISABLED;
goto done;
}
if (ble_gap_is_preempted()) {
rc = BLE_HS_EPREEMPTED;
goto done;
}
if (!ble_hs_conn_can_alloc()) {
rc = BLE_HS_ENOMEM;
goto done;
}
if (peer_addr &&
peer_addr->type != BLE_ADDR_PUBLIC &&
peer_addr->type != BLE_ADDR_RANDOM &&
peer_addr->type != BLE_ADDR_PUBLIC_ID &&
peer_addr->type != BLE_ADDR_RANDOM_ID) {
rc = BLE_HS_EINVAL;
goto done;
}
if ((phy_mask & BLE_GAP_LE_PHY_1M_MASK) && phy_1m_conn_params == NULL) {
phy_1m_conn_params = &ble_gap_conn_params_dflt;
}
if ((phy_mask & BLE_GAP_LE_PHY_2M_MASK) && phy_2m_conn_params == NULL) {
phy_2m_conn_params = &ble_gap_conn_params_dflt;
}
if ((phy_mask & BLE_GAP_LE_PHY_CODED_MASK) &&
phy_coded_conn_params == NULL) {
phy_coded_conn_params = &ble_gap_conn_params_dflt;
}
if (duration_ms == 0) {
duration_ms = BLE_GAP_CONN_DUR_DFLT;
}
/* The connection creation timeout is not really useful for PAwR.
* The controller will give a result for the connection attempt
* within a periodic interval. We do not know the periodic interval
* used, so disable the timeout.
*/
/* Verify peer not already connected. */
if (ble_hs_conn_find_by_addr(peer_addr) != NULL) {
rc = BLE_HS_EDONE;
goto done;
}
/* XXX: Verify conn_params. */
rc = ble_hs_id_use_addr(own_addr_type);
if (rc != 0) {
goto done;
}
BLE_HS_LOG(INFO, "GAP procedure initiated: extended connect; \n");
ble_gap_master.cb = cb;
ble_gap_master.cb_arg = cb_arg;
ble_gap_master.conn.using_wl = peer_addr == NULL;
ble_gap_master.conn.our_addr_type = own_addr_type;
ble_gap_master.op = BLE_GAP_OP_M_CONN;
rc = ble_gap_ext_conn_create_conn_synced_tx(own_addr_type,advertising_handle,subevent, peer_addr, phy_mask,
phy_1m_conn_params, phy_2m_conn_params,
phy_coded_conn_params);
if (rc != 0) {
ble_gap_master_reset_state();
goto done;
}
rc = 0;
done:
ble_hs_unlock();
if (rc != 0) {
STATS_INC(ble_gap_stats, initiate_fail);
}
return rc;
}
#endif
#if MYNEWT_VAL(BLE_EXT_ADV)
#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
static int
ble_gap_ext_conn_create_tx(
@@ -5643,7 +6126,60 @@ ble_gap_ext_conn_create_tx(
BLE_HCI_OCF_LE_EXT_CREATE_CONN),
cmd, len, NULL, 0);
}
#endif
/**
* Initiates a connect procedure.
*
* @param own_addr_type The type of address the stack should use for
* itself during connection establishment.
* o BLE_OWN_ADDR_PUBLIC
* o BLE_OWN_ADDR_RANDOM
* o BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
* o BLE_OWN_ADDR_RPA_RANDOM_DEFAULT
* @param peer_addr The address of the peer to connect to.
* If this parameter is NULL, the white list
* is used.
* @param duration_ms The duration of the discovery procedure.
* On expiration, the procedure ends and a
* BLE_GAP_EVENT_DISC_COMPLETE event is
* reported. Units are milliseconds.
* @param phy_mask Define on which PHYs connection attempt should
* be done
* @param phy_1m_conn_params Additional arguments specifying the
* particulars of the connect procedure. When
* BLE_GAP_LE_PHY_1M_MASK is set in phy_mask
* this parameter can be specify to null for
* default values.
* @param phy_2m_conn_params Additional arguments specifying the
* particulars of the connect procedure. When
* BLE_GAP_LE_PHY_2M_MASK is set in phy_mask
* this parameter can be specify to null for
* default values.
* @param phy_coded_conn_params Additional arguments specifying the
* particulars of the connect procedure. When
* BLE_GAP_LE_PHY_CODED_MASK is set in
* phy_mask this parameter can be specify to
* null for default values.
* @param cb The callback to associate with this connect
* procedure. When the connect procedure
* completes, the result is reported through
* this callback. If the connect procedure
* succeeds, the connection inherits this
* callback as its event-reporting mechanism.
* @param cb_arg The optional argument to pass to the callback
* function.
*
* @return 0 on success;
* BLE_HS_EALREADY if a connection attempt is
* already in progress;
* BLE_HS_EBUSY if initiating a connection is not
* possible because scanning is in progress;
* BLE_HS_EDONE if the specified peer is already
* connected;
* Other nonzero on error.
*/
#endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
/**
* Initiates a connect procedure.
+8
View File
@@ -95,6 +95,10 @@ void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem
#if MYNEWT_VAL(BLE_CONN_SUBRATING)
void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev);
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
void ble_gap_rx_periodic_adv_subev_data_req(const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev);
void ble_gap_rx_periodic_adv_response(const struct ble_gap_periodic_adv_response resp);
#endif
#if MYNEWT_VAL(BLE_POWER_CONTROL)
void ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power_report *ev);
void ble_gap_rx_le_pathloss_threshold(const struct ble_hci_ev_le_subev_path_loss_threshold *ev);
@@ -113,6 +117,10 @@ struct ble_gap_conn_complete
uint8_t master_clk_acc;
uint8_t local_rpa[BLE_DEV_ADDR_LEN];
uint8_t peer_rpa[BLE_DEV_ADDR_LEN];
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
uint8_t adv_handle;
uint16_t sync_handle;
#endif
};
int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance);
+76 -2
View File
@@ -102,6 +102,10 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_transmit_power_report;
#if MYNEWT_VAL(BLE_CONN_SUBRATING)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_subrate_change;
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_data_req;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_resp_rep;
#endif
/* Statistics */
struct host_hci_stats {
@@ -173,6 +177,14 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
#if MYNEWT_VAL(BLE_CONN_SUBRATING)
[BLE_HCI_LE_SUBEV_SUBRATE_CHANGE] = ble_hs_hci_evt_le_subrate_change,
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB_V2] = ble_hs_hci_evt_le_periodic_adv_sync_estab,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT_V2] = ble_hs_hci_evt_le_periodic_adv_rpt,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER_V2] = ble_hs_hci_evt_le_periodic_adv_sync_transfer,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_SUBEV_DATA_REQ] = ble_hs_hci_evt_le_periodic_adv_subev_data_req,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT] = ble_hs_hci_evt_le_periodic_adv_subev_resp_rep,
[BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2] = ble_hs_hci_evt_le_enh_conn_complete,
#endif
};
#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
@@ -202,7 +214,6 @@ ble_hs_hci_evt_le_dispatch_find(uint8_t event_code)
if (event_code >= BLE_HS_HCI_EVT_LE_DISPATCH_SZ) {
return NULL;
}
return ble_hs_hci_evt_le_dispatch[event_code];
}
@@ -484,7 +495,7 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data,
evt.connection_handle = BLE_HS_CONN_HANDLE_NONE;
#endif
}
#if MYNEWT_VAL(BLE_EXT_ADV)
#if MYNEWT_VAL(BLE_EXT_ADV) && !MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
if (evt.status == BLE_ERR_DIR_ADV_TMO ||
evt.role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) {
/* store this until we get set terminated event with adv handle */
@@ -492,6 +503,11 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data,
return 0;
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
evt.adv_handle = ev->adv_handle;
evt.sync_handle = ev->sync_handle;
#endif
return ble_gap_rx_conn_complete(&evt, 0);
}
@@ -968,6 +984,64 @@ ble_hs_hci_evt_le_subrate_change(uint8_t subevent, const void *data,
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
static int
ble_hs_hci_evt_le_periodic_adv_subev_data_req(uint8_t subevent, const void *data,
unsigned int len)
{
const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
ble_gap_rx_periodic_adv_subev_data_req(ev);
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_subev_resp_rep(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_periodic_adv_resp_rep *ev = data;
const struct periodic_adv_response *response;
struct ble_gap_periodic_adv_response resp;
if (len < (sizeof(*ev) + ev->num_responses * sizeof(struct periodic_adv_response))) {
return BLE_HS_ECONTROLLER;
}
len -= sizeof(*ev);
data += sizeof(*ev);
resp.adv_handle = ev->adv_handle;
resp.subevent = ev->subevent;
resp.tx_status = ev->tx_status;
for (uint8_t i = 0; i < ev->num_responses; i++) {
response = data;
if (len < sizeof(*response) + response->data_length) {
return BLE_HS_ECONTROLLER;
}
len -= sizeof(*response) + response->data_length;
data += sizeof(*response) + response->data_length;
resp.tx_power = response->tx_power;
resp.rssi = response->rssi;
resp.cte_type = response->cte_type;
resp.response_slot = response->response_slot;
resp.data_length = response->data_length;
resp.data = response->data;
resp.data_status = response->data_status;
ble_gap_rx_periodic_adv_response(resp);
}
return 0;
}
#endif
#if NIMBLE_BLE_CONNECT
static int
ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, const void *data,
+24
View File
@@ -259,6 +259,30 @@ ble_hs_startup_le_set_evmask_tx(void)
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
if (version >= BLE_HCI_VER_BCS_5_4) {
/**
* Enable the following LE events:
* 0x0000000800000000 LE Periodic Advertising Sync Established event V2
* 0x0000001000000000 LE Periodic Advertising Report Event V2
* 0x0000004000000000 LE Periodic Advertising Subevent Data Request event
* 0x0000008000000000 LE Periodic Advertising Response Report event
* 0x0000010000000000 LE Enhanced Connection Complete event V2
*/
mask |= 0x000001d800000000;
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
if (version >= BLE_HCI_VER_BCS_5_4) {
/**
* Enable the following LE events:
* 0x0000002000000000 LE Periodic Advertising Sync Transfer Received event V2
*/
mask |= 0x0000002000000000;
}
#endif
cmd.event_mask = htole64(mask);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+118 -2
View File
@@ -706,6 +706,18 @@ struct ble_hci_le_ext_create_conn_cp {
struct conn_params conn_params[0];
} __attribute__((packed));
#define BLE_HCI_LE_EXT_CREATE_CONN_V2 (0x0085)
struct ble_hci_le_ext_create_conn_v2_cp {
uint8_t adv_handle;
uint8_t subevent;
uint8_t filter_policy;
uint8_t own_addr_type;
uint8_t peer_addr_type;
uint8_t peer_addr[6];
uint8_t init_phy_mask;
struct conn_params conn_params[0];
} __attribute__((packed));
#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER 0x01
#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED 0x02
@@ -1123,6 +1135,57 @@ struct ble_hci_le_subrate_req_cp {
/* --- Vendor specific commands (OGF 0x00FF) */
#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001)
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SUBEV_DATA (0x0082)
struct periodic_adv_subevents {
uint8_t subevent;
uint8_t response_slot_start;
uint8_t response_slot_count;
uint8_t subevent_data_length;
uint8_t subevent_data[0];
} __attribute__((packed));
struct ble_hci_le_set_periodic_adv_subev_data_cp {
uint8_t adv_handle;
uint8_t num_subevents;
struct periodic_adv_subevents subevents[0];
} __attribute__((packed));
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_RESPONSE_DATA (0x0083)
struct ble_hci_le_set_periodic_adv_response_data {
uint16_t sync_handle;
uint16_t request_event;
uint8_t request_subevent;
uint8_t response_subevent;
uint8_t response_slot;
uint8_t response_data_length;
uint8_t response_data[0];
} __attribute__((packed));
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SYNC_SUBEVENT (0x0084)
struct ble_hci_le_set_periodic_adv_sync_subevent {
uint16_t sync_handle;
uint16_t periodic_adv_properties;
uint8_t num_subevents;
uint8_t subevents[0];
} __attribute__((packed));
struct ble_hci_le_set_periodic_adv_sync_subevent_rp {
uint16_t sync_handle;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS_V2 (0x0086)
struct ble_hci_le_set_periodic_adv_params_v2 {
uint8_t adv_handle;
uint16_t min_itvl;
uint16_t max_itvl;
uint16_t props;
uint8_t num_subevents;
uint8_t subevent_interval;
uint8_t response_slot_delay;
uint8_t response_slot_spacing;
uint8_t num_response_slots;
} __attribute__((packed));
struct ble_hci_vs_rd_static_addr_rp {
uint8_t addr[6];
} __attribute__((packed));
@@ -1374,6 +1437,7 @@ struct ble_hci_vs_duplicate_exception_list_cp {
#define BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE 0x00
#define BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE 0x01
#define BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED 0x02
#define BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED 0xFF
/* --- LE set privacy mode (OCF 0x004E) */
#define BLE_HCI_PRIVACY_NETWORK (0)
@@ -1630,6 +1694,7 @@ struct ble_hci_ev_le_subev_gen_dhkey_complete {
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE (0x0A)
#define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2 (0x29)
struct ble_hci_ev_le_subev_enh_conn_complete {
uint8_t subev_code;
uint8_t status;
@@ -1643,6 +1708,10 @@ struct ble_hci_ev_le_subev_enh_conn_complete {
uint16_t conn_latency;
uint16_t supervision_timeout;
uint8_t mca;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
uint8_t adv_handle;
uint16_t sync_handle;
#endif
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT (0x0B)
@@ -1691,7 +1760,8 @@ struct ble_hci_ev_le_subev_ext_adv_rpt {
struct ext_adv_report reports[0];
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB_V2 (0x24)
struct ble_hci_ev_le_subev_periodic_adv_sync_estab {
uint8_t subev_code;
uint8_t status;
@@ -1702,15 +1772,26 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_estab {
uint8_t phy;
uint16_t interval;
uint8_t aca;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
uint8_t num_subevents;
uint8_t subevent_interval;
uint8_t response_slot_delay;
uint8_t response_slot_spacing;
#endif
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT (0x0F)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT_V2 (0x25)
struct ble_hci_ev_le_subev_periodic_adv_rpt {
uint8_t subev_code;
uint16_t sync_handle;
int8_t tx_power;
int8_t rssi;
uint8_t cte_type;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
uint16_t event_counter;
uint8_t subevent;
#endif
uint8_t data_status;
uint8_t data_len;
uint8_t data[0];
@@ -1755,7 +1836,8 @@ struct ble_hci_ev_le_subev_chan_sel_alg {
#define BLE_HCI_LE_SUBEV_CONN_IQ_RPT (0x16)
#define BLE_HCI_LE_SUBEV_CTE_REQ_FAILED (0x17)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER (0x18)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER (0x18)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER_V2 (0x26)
struct ble_hci_ev_le_subev_periodic_adv_sync_transfer {
uint8_t subev_code;
uint8_t status;
@@ -1768,6 +1850,12 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_transfer {
uint8_t phy;
uint16_t interval;
uint8_t aca;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES)
uint8_t num_subevents;
uint8_t subevent_interval;
uint8_t response_slot_delay;
uint8_t response_slot_spacing;
#endif
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_CIS_ESTAB (0x19)
@@ -1905,6 +1993,34 @@ struct ble_hci_ev_le_subev_subrate_change {
uint16_t supervision_tmo;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SUBEV_DATA_REQ (0x27)
struct ble_hci_ev_le_subev_periodic_adv_subev_data_req {
uint8_t subev_code;
uint8_t adv_handle;
uint8_t subevent_start;
uint8_t subevent_data_count;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT (0x28)
struct periodic_adv_response {
int8_t tx_power;
int8_t rssi;
uint8_t cte_type;
uint8_t response_slot;
uint8_t data_status;
uint8_t data_length;
uint8_t data[0];
} __attribute__((packed));
struct ble_hci_ev_le_subev_periodic_adv_resp_rep {
uint8_t subev_code;
uint8_t adv_handle;
uint8_t subevent;
uint8_t tx_status;
uint8_t num_responses;
struct periodic_adv_response responses[0];
} __attribute__((packed));
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
// LE vendor hci event
#define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0