mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-07-28 13:47:55 +00:00
feat(nimble): Added PAwR support for nimble
This commit is contained in:
committed by
Sumeet Singh
parent
97287467de
commit
c4b3bec003
@@ -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
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user