nimble/host: Add initial periodic adverting host support

This patch adds the implementation for periodic advertising
nd discovery, which is available when BLE_PERIODIC_ADV is enabled
This commit is contained in:
Ahmed Shokry
2019-04-09 10:19:11 +02:00
committed by Łukasz Rymanowski
parent 95bb7fe646
commit 67844daa24
22 changed files with 1486 additions and 97 deletions
+13 -13
View File
@@ -2106,7 +2106,7 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
}
switch (operation) {
case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE:
case BLE_HCI_LE_SET_DATA_OPER_COMPLETE:
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
if (datalen > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -2115,10 +2115,10 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_LAST:
case BLE_HCI_LE_SET_DATA_OPER_LAST:
/* TODO mark scan rsp as complete? */
/* fall through */
case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT:
case BLE_HCI_LE_SET_DATA_OPER_INT:
if (!advsm->scan_rsp_data) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -2135,7 +2135,7 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
return BLE_ERR_INV_HCI_CMD_PARMS;
}
break;
case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST:
case BLE_HCI_LE_SET_DATA_OPER_FIRST:
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -2154,8 +2154,8 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
return BLE_ERR_INV_HCI_CMD_PARMS;
}
new_data = (operation == BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE) ||
(operation == BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST);
new_data = (operation == BLE_HCI_LE_SET_DATA_OPER_COMPLETE) ||
(operation == BLE_HCI_LE_SET_DATA_OPER_FIRST);
if (advsm->adv_enabled) {
if (advsm->new_scan_rsp_data) {
@@ -2234,7 +2234,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
}
switch (operation) {
case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE:
case BLE_HCI_LE_SET_DATA_OPER_COMPLETE:
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
if (datalen > BLE_ADV_LEGACY_DATA_MAX_LEN) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -2245,7 +2245,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED:
case BLE_HCI_LE_SET_DATA_OPER_UNCHANGED:
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -2257,10 +2257,10 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
/* update DID only */
ble_ll_adv_update_did(advsm);
return BLE_ERR_SUCCESS;
case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST:
case BLE_HCI_LE_SET_DATA_OPER_LAST:
ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE);
/* fall through */
case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT:
case BLE_HCI_LE_SET_DATA_OPER_INT:
if (!advsm->adv_data) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -2277,7 +2277,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
return BLE_ERR_CMD_DISALLOWED;
}
break;
case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST:
case BLE_HCI_LE_SET_DATA_OPER_FIRST:
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -2297,8 +2297,8 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
return BLE_ERR_INV_HCI_CMD_PARMS;
}
new_data = (operation == BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE) ||
(operation == BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST);
new_data = (operation == BLE_HCI_LE_SET_DATA_OPER_COMPLETE) ||
(operation == BLE_HCI_LE_SET_DATA_OPER_FIRST);
if (advsm->adv_enabled) {
if (advsm->new_adv_data) {
+12 -12
View File
@@ -696,16 +696,16 @@ ble_ll_is_valid_adv_mode(uint8_t ocf)
case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS:
case BLE_HCI_OCF_LE_REMOVE_ADV_SET:
case BLE_HCI_OCF_LE_CLEAR_ADV_SETS:
case BLE_HCI_OCF_LE_SET_PER_ADV_PARAMS:
case BLE_HCI_OCF_LE_SET_PER_ADV_DATA:
case BLE_HCI_OCF_LE_SET_PER_ADV_ENABLE:
case BLE_HCI_OCF_LE_PER_ADV_CREATE_SYNC:
case BLE_HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL:
case BLE_HCI_OCF_LE_PER_ADV_TERM_SYNC:
case BLE_HCI_OCF_LE_ADD_DEV_TO_PER_ADV_LIST:
case BLE_HCI_OCF_LE_REM_DEV_FROM_PER_ADV_LIST:
case BLE_HCI_OCF_LE_CLEAR_PER_ADV_LIST:
case BLE_HCI_OCF_LE_RD_PER_ADV_LIST_SIZE:
case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS:
case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA:
case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE:
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC:
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL:
case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC:
case BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST:
case BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST:
case BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST:
case BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE:
if (hci_adv_mode == ADV_MODE_LEGACY) {
return false;
}
@@ -859,13 +859,13 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen,
case BLE_HCI_OCF_LE_SET_ADV_DATA:
if (len == BLE_HCI_SET_ADV_DATA_LEN) {
rc = ble_ll_adv_set_adv_data(cmdbuf, len, 0,
BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE);
BLE_HCI_LE_SET_DATA_OPER_COMPLETE);
}
break;
case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA:
if (len == BLE_HCI_SET_SCAN_RSP_DATA_LEN) {
rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, len, 0,
BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE);
BLE_HCI_LE_SET_DATA_OPER_COMPLETE);
}
break;
case BLE_HCI_OCF_LE_SET_ADV_ENABLE:
+74
View File
@@ -124,6 +124,9 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_REPEAT_PAIRING 17
#define BLE_GAP_EVENT_PHY_UPDATE_COMPLETE 18
#define BLE_GAP_EVENT_EXT_DISC 19
#define BLE_GAP_EVENT_PERIODIC_ADV_SYNC_ESTAB 20
#define BLE_GAP_EVENT_PERIODIC_DISC 21
#define BLE_GAP_EVENT_PERIODIC_ADV_SYNC_LOST 22
/*** Reason codes for the subscribe GAP event. */
@@ -708,6 +711,46 @@ struct ble_gap_event {
uint8_t tx_phy;
uint8_t rx_phy;
} phy_updated;
#if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV)
/**
* Represents an periodic advertising sync established during discovery
* procedure. Valid for the following event types:
* o BLE_GAP_EVENT_PERIODIC_ADV_SYNC_ESTAB
*/
struct {
uint8_t status;
uint16_t sync_handle;
uint8_t sid;
uint8_t adv_addr_type;
uint8_t adv_addr[6];
uint8_t adv_phy;
uint16_t per_adv_ival;
uint8_t adv_clk_accuracy;
} periodic_adv_sync_estab;
/**
* Represents a Periodic advertising report received during discovery
* procedure. Valid for the following event types:
* o BLE_GAP_EVENT_PERIODIC_DISC
*/
struct {
uint16_t sync_handle;
uint8_t tx_power;
int8_t rssi;
uint8_t data_status;
uint8_t data_length;
uint8_t *data;
} periodic_disc;
/**
* Represents an periodic advertising sync Lost during discovery
* procedure. Valid for the following event types:
* o BLE_GAP_EVENT_PERIODIC_ADV_SYNC_LOST
*/
struct {
uint16_t sync_handle;
} periodic_adv_sync_lost;
#endif
};
};
@@ -903,6 +946,15 @@ struct ble_gap_ext_adv_params {
uint8_t sid;
};
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
struct ble_gap_periodic_adv_params {
unsigned int include_tx_power:1;
uint16_t itvl_min;
uint16_t itvl_max;
};
#endif
int ble_gap_ext_adv_configure(uint8_t instance,
const struct ble_gap_ext_adv_params *params,
int8_t *selected_tx_power,
@@ -913,6 +965,28 @@ int ble_gap_ext_adv_stop(uint8_t instance);
int ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data);
int ble_gap_ext_adv_rsp_set_data(uint8_t instance, struct os_mbuf *data);
int ble_gap_ext_adv_remove(uint8_t instance);
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
/* Periodic Advertising */
int ble_gap_periodic_adv_configure(uint8_t instance, const struct ble_gap_periodic_adv_params *params);
int ble_gap_periodic_adv_start(uint8_t instance);
int ble_gap_periodic_adv_stop(uint8_t instance);
int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data);
int ble_gap_periodic_adv_create_sync (uint8_t filter_policy,
uint8_t adv_sid, uint8_t adv_add_type,
const uint8_t *adv_addr, uint16_t skip,
uint16_t sync_timeout);
int ble_gap_periodic_adv_create_sync_cancel(void);
int ble_gap_periodic_adv_terminate_sync(uint16_t sync_handle);
int ble_gap_add_dev_to_periodic_adv_list(uint8_t adv_add_type, const uint8_t *adv_add,
uint8_t adv_sid);
int ble_gap_rem_dev_from_periodic_adv_list(uint8_t adv_addr_type,
const uint8_t *adv_addr,
uint8_t adv_sid);
int ble_gap_clear_periodic_adv_list(void);
int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size);
#endif
#endif
/**
+663 -24
View File
@@ -74,10 +74,11 @@
*/
/** GAP procedure op codes. */
#define BLE_GAP_OP_NULL 0
#define BLE_GAP_OP_M_DISC 1
#define BLE_GAP_OP_M_CONN 2
#define BLE_GAP_OP_S_ADV 1
#define BLE_GAP_OP_NULL 0
#define BLE_GAP_OP_M_DISC 1
#define BLE_GAP_OP_M_CONN 2
#define BLE_GAP_OP_S_ADV 1
#define BLE_GAP_OP_S_PERIODIC_ADV 2
/**
* If an attempt to cancel an active procedure fails, the attempt is retried
@@ -128,6 +129,13 @@ struct ble_gap_master_state {
uint8_t limited:1;
} disc;
};
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
/* Tells if create_sync was called without receiving sync
* established event
*/
uint8_t pending_create_sync;
#endif
};
static bssnz_t struct ble_gap_master_state ble_gap_master;
@@ -148,6 +156,10 @@ struct ble_gap_slave_state {
unsigned int directed:1;
unsigned int legacy_pdu:1;
unsigned int rnd_addr_set:1;
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
unsigned int periodic_configured:1;
uint8_t periodic_op;
#endif
uint8_t rnd_addr[6];
#else
/* timer is used only with legacy advertising */
@@ -176,7 +188,6 @@ struct ble_gap_snapshot {
};
static SLIST_HEAD(ble_gap_hook_list, ble_gap_event_listener) ble_gap_event_listener_list;
static os_membuf_t ble_gap_update_entry_mem[
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE),
sizeof (struct ble_gap_update_entry))];
@@ -433,22 +444,22 @@ int
ble_gap_conn_find_by_addr(const ble_addr_t *addr,
struct ble_gap_conn_desc *out_desc)
{
struct ble_hs_conn *conn;
struct ble_hs_conn *conn;
ble_hs_lock();
ble_hs_lock();
conn = ble_hs_conn_find_by_addr(addr);
if (conn != NULL && out_desc != NULL) {
ble_gap_fill_conn_desc(conn, out_desc);
}
conn = ble_hs_conn_find_by_addr(addr);
if (conn != NULL && out_desc != NULL) {
ble_gap_fill_conn_desc(conn, out_desc);
}
ble_hs_unlock();
ble_hs_unlock();
if (conn == NULL) {
return BLE_HS_ENOTCONN;
}
if (conn == NULL) {
return BLE_HS_ENOTCONN;
}
return 0;
return 0;
}
static int
@@ -1283,6 +1294,111 @@ ble_gap_rx_adv_set_terminated(struct hci_le_adv_set_terminated *evt)
}
#endif
/* Periodic adv events */
#if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV)
void
ble_gap_rx_peroidic_adv_sync_estab(
struct hci_le_subev_periodic_adv_sync_estab *evt)
{
struct ble_gap_event event;
struct ble_gap_master_state state;
struct ble_hs_periodic_sync * psync;
memset(&event, 0, sizeof event);
/* There must be memory for psync as the check was done when creating
* sync
*/
psync = ble_hs_periodic_sync_alloc();
BLE_HS_DBG_ASSERT(psync != NULL);
psync->sync_handle = evt->sync_handle;
psync->adv_sid = evt->sid;
psync->advertiser_addr_type = evt->adv_addr_type;
memcpy(psync->advertiser_addr.val, evt->adv_addr, 6);
psync->advertiser_phy = evt->adv_phy;
psync->periodic_adv_itvl = evt->per_adv_ival;
psync->advertiser_clock_accuracy = evt->adv_clk_accuracy;
ble_hs_lock();
ble_hs_periodic_sync_insert(psync);
ble_hs_unlock();
event.type = BLE_GAP_EVENT_PERIODIC_ADV_SYNC_ESTAB;
event.periodic_adv_sync_estab.status = evt->status;
event.periodic_adv_sync_estab.sync_handle = evt->sync_handle;
event.periodic_adv_sync_estab.sid = evt->sid;
event.periodic_adv_sync_estab.adv_addr_type = evt->adv_addr_type;
memcpy(event.periodic_adv_sync_estab.adv_addr, evt->adv_addr, 6);
event.periodic_adv_sync_estab.adv_phy = evt->adv_phy;
event.periodic_adv_sync_estab.per_adv_ival = evt->per_adv_ival;
event.periodic_adv_sync_estab.adv_clk_accuracy = evt->adv_clk_accuracy;
ble_gap_master.pending_create_sync = 0;
ble_gap_master_extract_state(&state, 0);
if (ble_gap_has_client(&state)) {
state.cb(&event, state.cb_arg);
}
}
void
ble_gap_rx_periodic_adv_rpt(struct hci_le_subev_periodic_adv_rpt *evt)
{
struct ble_gap_event event;
struct ble_gap_master_state state;
memset(&event, 0, sizeof event);
event.type = BLE_GAP_EVENT_PERIODIC_DISC;
event.periodic_disc.sync_handle = evt->sync_handle;
event.periodic_disc.tx_power = evt->tx_power;
event.periodic_disc.rssi = evt->rssi;
event.periodic_disc.data_status = evt->data_status;
event.periodic_disc.data_length = evt->data_length;
event.periodic_disc.data = evt->data;
ble_gap_master_extract_state(&state, 0);
if (ble_gap_has_client(&state)) {
state.cb(&event, state.cb_arg);
}
}
void
ble_gap_rx_periodic_adv_sync_lost(
struct hci_le_subev_periodic_adv_sync_lost *evt)
{
struct ble_gap_event event;
struct ble_gap_master_state state;
struct ble_hs_periodic_sync *psync;
memset(&event, 0, sizeof event);
event.type = BLE_GAP_EVENT_PERIODIC_ADV_SYNC_LOST;
event.periodic_adv_sync_lost.sync_handle = evt->sync_handle;
ble_hs_lock();
/* The handle must be in the list */
psync = ble_hs_periodic_sync_find_assert(evt->sync_handle);
/* Remove the handle from the list */
ble_hs_periodic_sync_remove(psync);
/* Free the memory occupied by psync as it is no longer needed */
ble_hs_periodic_sync_free(psync);
ble_hs_unlock();
ble_gap_master_extract_state(&state, 0);
if (ble_gap_has_client(&state)) {
state.cb(&event, state.cb_arg);
}
}
#endif
static int
ble_gap_rd_rem_sup_feat_tx(uint16_t handle)
{
@@ -2509,7 +2625,7 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events)
if (ble_gap_slave[instance].rnd_addr_set) {
break;
}
/* fall through */
/* fall through */
case BLE_OWN_ADDR_PUBLIC:
case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
default:
@@ -2680,7 +2796,7 @@ ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data)
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance,
BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE,
BLE_HCI_LE_SET_DATA_OPER_COMPLETE,
0, *data, len, buf, sizeof(buf));
if (rc) {
return rc;
@@ -2703,7 +2819,7 @@ ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data)
/* complete data */
if (len <= BLE_HCI_MAX_EXT_ADV_DATA_LEN) {
rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance,
BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE,
BLE_HCI_LE_SET_DATA_OPER_COMPLETE,
0, *data, len, buf,sizeof(buf));
if (rc) {
return rc;
@@ -2717,7 +2833,7 @@ ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data)
}
/* first fragment */
op = BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST;
op = BLE_HCI_LE_SET_DATA_OPER_FIRST;
do {
rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, op, 0, *data,
@@ -2736,12 +2852,12 @@ ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data)
}
len -= BLE_HCI_MAX_EXT_ADV_DATA_LEN;
op = BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT;
op = BLE_HCI_LE_SET_DATA_OPER_INT;
} while (len > BLE_HCI_MAX_EXT_ADV_DATA_LEN);
/* last fragment */
rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance,
BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST,
BLE_HCI_LE_SET_DATA_OPER_LAST,
0, *data, len, buf, sizeof(buf));
if (rc) {
return rc;
@@ -2891,6 +3007,529 @@ ble_gap_ext_adv_remove(uint8_t instance)
return 0;
}
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
static int
ble_gap_periodic_adv_params_tx(uint8_t instance,
const struct ble_gap_periodic_adv_params *params)
{
struct hci_periodic_adv_params hci_adv_params;
uint8_t buf[BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN];
int rc;
memset(&hci_adv_params, 0, sizeof(hci_adv_params));
if (params->include_tx_power) {
hci_adv_params.properties |= BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR;
}
/* Fill optional fields if application did not specify them. */
if (params->itvl_min == 0 && params->itvl_max == 0) {
hci_adv_params.min_interval = 30 / 1.25; //30 ms
hci_adv_params.max_interval = 60 / 1.25; //150 ms
} else {
hci_adv_params.min_interval = params->itvl_min;
hci_adv_params.max_interval = params->itvl_max;
}
rc = ble_hs_hci_cmd_build_le_periodic_adv_params(instance, &hci_adv_params, buf,
sizeof(buf));
if (rc != 0) {
return rc;
}
rc = ble_hs_hci_cmd_tx_empty_ack(
BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS), buf,
sizeof(buf));
if (rc != 0) {
return rc;
}
return 0;
}
static int
ble_gap_periodic_adv_params_validate(
const struct ble_gap_periodic_adv_params *params)
{
if (!params) {
return BLE_HS_EINVAL;
}
if (params->itvl_min > 0xffff || params->itvl_min < 6) {
return BLE_HS_EINVAL;
}
if (params->itvl_max > 0xffff || params->itvl_max < 6) {
return BLE_HS_EINVAL;
}
return 0;
}
int
ble_gap_periodic_adv_configure(uint8_t instance,
const struct ble_gap_periodic_adv_params *params)
{
int rc;
if (instance >= BLE_ADV_INSTANCES) {
return BLE_HS_EINVAL;
}
rc = ble_gap_periodic_adv_params_validate(params);
if (rc) {
return rc;
}
ble_hs_lock();
/* The corresponding extended advertising instance should be configured */
if (!ble_gap_slave[instance].configured) {
ble_hs_unlock();
return ENOMEM;
}
/* Periodic advertising shall not be configured while it is already
* running.
* Bluetooth Core Specification, Section 7.8.61
*/
if (ble_gap_slave[instance].periodic_op == BLE_GAP_OP_S_PERIODIC_ADV) {
ble_hs_unlock();
return BLE_HS_EINVAL;
}
rc = ble_gap_periodic_adv_params_tx(instance, params);
if (rc) {
ble_hs_unlock();
return rc;
}
ble_gap_slave[instance].periodic_configured = 1;
ble_hs_unlock();
return 0;
}
int
ble_gap_periodic_adv_start(uint8_t instance)
{
uint8_t buf[BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN];
uint16_t opcode;
int rc;
if (instance >= BLE_ADV_INSTANCES) {
return BLE_HS_EINVAL;
}
ble_hs_lock();
/* Periodic advertising cannot start unless it is configured before */
if (!ble_gap_slave[instance].periodic_configured) {
ble_hs_unlock();
return BLE_HS_EINVAL;
}
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE);
rc = ble_hs_hci_cmd_build_le_periodic_adv_enable(1, instance, buf,
sizeof(buf));
if (rc != 0) {
ble_hs_unlock();
return rc;
}
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
if (rc != 0) {
ble_hs_unlock();
return rc;
}
ble_gap_slave[instance].periodic_op = BLE_GAP_OP_S_PERIODIC_ADV;
ble_hs_unlock();
return 0;
}
static int
ble_gap_periodic_adv_set(uint8_t instance, uint16_t opcode,
struct os_mbuf **data)
{
/* In that case we always fit all data in single HCI command */
#if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN
static uint8_t buf[BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN +
MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
uint16_t len = OS_MBUF_PKTLEN(*data);
int rc;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
rc = ble_hs_hci_cmd_build_le_periodic_adv_data(
instance,
BLE_HCI_LE_SET_DATA_OPER_COMPLETE,
*data, len,
buf, sizeof(buf));
if (rc) {
return rc;
}
os_mbuf_adj(*data, MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE));
*data = os_mbuf_trim_front(*data);
return ble_hs_hci_cmd_tx_empty_ack(opcode, buf,
BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + len);
#else
static uint8_t buf[BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN +
BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN];
uint16_t len = OS_MBUF_PKTLEN(*data);
uint8_t op;
int rc;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
/* Complete data */
if (len <= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN) {
rc = ble_hs_hci_cmd_build_le_periodic_adv_data(instance,
BLE_HCI_LE_SET_DATA_OPER_COMPLETE, *data, len, buf,
sizeof(buf));
if (rc) {
return rc;
}
os_mbuf_adj(*data, len);
*data = os_mbuf_trim_front(*data);
return ble_hs_hci_cmd_tx_empty_ack(opcode, buf,
BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + len);
}
/* If the periodic advertising is already enabled, the periodic advertising
* the op code shall be nothing but 0x03
* Bluetooth Core Specification, section 7.8.62
*/
if (ble_gap_slave[instance].periodic_op == BLE_GAP_OP_S_PERIODIC_ADV) {
return BLE_HS_EINVAL;
}
/* First fragment */
op = BLE_HCI_LE_SET_DATA_OPER_FIRST;
do{
rc = ble_hs_hci_cmd_build_le_periodic_adv_data(instance, op, *data,
BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN, buf, sizeof(buf));
if (rc) {
return rc;
}
os_mbuf_adj(*data, BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN);
*data = os_mbuf_trim_front(*data);
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
if (rc) {
return rc;
}
len -= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN;
op = BLE_HCI_LE_SET_DATA_OPER_INT;
} while (len > BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN);
/* Last fragment */
rc = ble_hs_hci_cmd_build_le_periodic_adv_data(
instance,
BLE_HCI_LE_SET_DATA_OPER_LAST,
*data, len, buf, sizeof(buf));
if (rc) {
return rc;
}
os_mbuf_adj(*data, len);
*data = os_mbuf_trim_front(*data);
return ble_hs_hci_cmd_tx_empty_ack(opcode, buf,
BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + len);
#endif
}
static int
ble_gap_periodic_adv_set_data_validate(uint8_t instance,
struct os_mbuf *data)
{
/* The corresponding extended advertising instance should be configured */
if (!ble_gap_slave[instance].configured) {
return BLE_HS_EINVAL;
}
if (ble_gap_slave[instance].legacy_pdu) {
return BLE_HS_EINVAL;
}
/* One more check states that if the periodic advertising is already
* enabled, the operation shall be 0x03 (Complete).
* This check is handled during sending the data to the controller, as the
* length checks are already checked there, so this saves duplicate code
*/
return 0;
}
int
ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data)
{
int rc;
if (instance >= BLE_ADV_INSTANCES) {
rc = BLE_HS_EINVAL;
goto done;
}
ble_hs_lock();
rc = ble_gap_periodic_adv_set_data_validate(instance, data);
if (rc != 0) {
ble_hs_unlock();
goto done;
}
rc = ble_gap_periodic_adv_set(
instance,
BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA,
&data);
ble_hs_unlock();
done:
os_mbuf_free_chain(data);
return rc;
}
static int
ble_gap_periodic_adv_stop_no_lock(uint8_t instance)
{
uint8_t buf[BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN];
uint16_t opcode;
int rc;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE);
rc = ble_hs_hci_cmd_build_le_periodic_adv_enable(0, instance, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
ble_gap_slave[instance].periodic_op = BLE_GAP_OP_NULL;
return 0;
}
int
ble_gap_periodic_adv_stop(uint8_t instance)
{
int rc;
if (instance >= BLE_ADV_INSTANCES) {
return BLE_HS_EINVAL;
}
ble_hs_lock();
rc = ble_gap_periodic_adv_stop_no_lock(instance);
ble_hs_unlock();
return rc;
}
int
ble_gap_periodic_adv_create_sync(uint8_t filter_policy, uint8_t adv_sid,
uint8_t adv_addr_type, const uint8_t *adv_addr, uint16_t skip,
uint16_t sync_timeout)
{
uint8_t buf[BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN];
uint16_t opcode;
int rc = 0;
if (!ble_hs_periodic_sync_can_alloc()) {
return BLE_HS_ENOMEM;
}
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC);
/* No sync can be created if another sync is still pending */
if (ble_gap_master.pending_create_sync) {
return BLE_HS_EINVAL;
}
rc = ble_hs_hci_cmd_build_le_periodic_adv_create_sync(filter_policy,
adv_sid,
adv_addr_type,
adv_addr,
skip, sync_timeout,
buf, sizeof(buf));
if (rc != 0) {
return rc;
}
/* This shall be reset upon receiving sync_established event,
* or if the sync is cancelled before receiving that event.
*/
ble_gap_master.pending_create_sync = 1;
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
return rc;
}
int
ble_gap_periodic_adv_create_sync_cancel(void)
{
uint16_t opcode;
int rc = 0;
if (!ble_gap_master.pending_create_sync) {
return BLE_HS_EINVAL;
}
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL);
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, NULL, 0);
if (!rc) {
ble_gap_master.pending_create_sync = 0;
}
return rc;
}
int
ble_gap_periodic_adv_terminate_sync(uint16_t sync_handle)
{
uint8_t buf[BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN];
uint16_t opcode;
struct ble_hs_periodic_sync *psync;
int rc = 0;
if (ble_gap_master.pending_create_sync) {
return BLE_HS_EINVAL;
}
ble_hs_lock();
/* The handle must be in the list. If it doesn't exist, it means
* that the sync may have been lost at the same moment in which
* the app wants to terminate that sync handle */
psync = ble_hs_periodic_sync_find(sync_handle);
if (!psync) {
/* Sync already terminated. TODO: Not sure what error code
* describes this scnario the best */
rc = BLE_HS_EALREADY;
goto done;
}
/* Remove the handle from the list */
ble_hs_periodic_sync_remove(psync);
/* Free the memory occupied by psync as it is no longer needed */
ble_hs_periodic_sync_free(psync);
ble_hs_unlock();
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC);
rc = ble_hs_hci_cmd_build_le_periodic_adv_terminate_sync(sync_handle,
buf, sizeof(buf));
if (rc != 0) {
return rc;
}
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
done:
return rc;
}
int
ble_gap_add_dev_to_periodic_adv_list(uint8_t adv_addr_type,
const uint8_t *adv_addr, uint8_t adv_sid)
{
uint8_t buf[BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN];
uint16_t opcode;
int rc = 0;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST);
rc = ble_hs_hci_cmd_build_le_add_dev_to_periodic_adv_list(adv_addr_type,
adv_addr, adv_sid, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
return rc;
}
int
ble_gap_rem_dev_from_periodic_adv_list(uint8_t adv_addr_type,
const uint8_t *adv_addr, uint8_t adv_sid)
{
uint8_t buf[BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN];
uint16_t opcode;
int rc = 0;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST);
rc = ble_hs_hci_cmd_build_le_rem_dev_from_periodic_adv_list(adv_addr_type,
adv_addr, adv_sid, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
return rc;
}
int
ble_gap_clear_periodic_adv_list(void)
{
uint16_t opcode;
int rc = 0;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST);
rc = ble_hs_hci_cmd_tx_empty_ack(opcode, NULL, 0);
return rc;
}
int
ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size)
{
uint8_t rspbuf[1];
uint8_t rsplen;
uint16_t opcode;
int rc = 0;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE);
rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, rspbuf, sizeof(rspbuf), &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != sizeof(rspbuf)) {
return BLE_HS_ECONTROLLER;
}
*per_adv_list_size = rspbuf[0];
return 0;
}
#endif
/*****************************************************************************
@@ -2957,7 +3596,7 @@ ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates,
buf, sizeof(buf));
}
#endif
#endif
#if NIMBLE_BLE_SCAN
#if !MYNEWT_VAL(BLE_EXT_ADV)
static int
@@ -4702,7 +5341,7 @@ ble_gap_preempt_done(void)
disc_preempted = 0;
/* protects slaves from accessing by multiple threads */
/* Protects slaves from accessing by multiple threads */
ble_npl_mutex_pend(&preempt_done_mutex, 0xFFFFFFFF);
memset(slaves, 0, sizeof(slaves));
+5
View File
@@ -82,6 +82,11 @@ void ble_gap_rx_le_scan_timeout(void);
#if MYNEWT_VAL(BLE_EXT_ADV)
void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc);
void ble_gap_rx_adv_set_terminated(struct hci_le_adv_set_terminated *evt);
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
void ble_gap_rx_peroidic_adv_sync_estab(struct hci_le_subev_periodic_adv_sync_estab *evt);
void ble_gap_rx_periodic_adv_rpt(struct hci_le_subev_periodic_adv_rpt *evt);
void ble_gap_rx_periodic_adv_sync_lost(struct hci_le_subev_periodic_adv_sync_lost *evt);
#endif
#endif
void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
void ble_gap_rx_rd_rem_sup_feat_complete(struct hci_le_rd_rem_supp_feat_complete *evt);
+3
View File
@@ -744,6 +744,9 @@ ble_hs_init(void)
rc = ble_hs_conn_init();
SYSINIT_PANIC_ASSERT(rc == 0);
rc = ble_hs_periodic_sync_init();
SYSINIT_PANIC_ASSERT(rc == 0);
rc = ble_l2cap_init();
SYSINIT_PANIC_ASSERT(rc == 0);
+8 -7
View File
@@ -224,10 +224,10 @@ ble_hs_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
}
break;
}
case BLE_HCI_LE_SUBEV_PER_ADV_SYNC_ESTAB:
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
case BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB:
{
struct hci_le_subev_per_adv_sync_estab *data = (void *) evdata;
struct hci_le_subev_periodic_adv_sync_estab *data = (void *) evdata;
if (len != sizeof(*data)) {
BLE_HS_LOG(DEBUG, "Corrupted LE Periodic Advertising Sync "
@@ -241,9 +241,9 @@ ble_hs_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
break;
}
case BLE_HCI_LE_SUBEV_PER_ADV_RPT:
case BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT:
{
struct hci_le_subev_per_adv_rpt *data = (void *) evdata;
struct hci_le_subev_periodic_adv_rpt *data = (void *) evdata;
if (len < sizeof(*data) || len != sizeof(*data) + data->data_length) {
BLE_HS_LOG(DEBUG, "Corrupted LE Periodic Advertising Report "
@@ -258,9 +258,9 @@ ble_hs_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
break;
}
case BLE_HCI_LE_SUBEV_PER_ADV_SYNC_LOST:
case BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST:
{
struct hci_le_subev_per_adv_sync_lost *data = (void *) evdata;
struct hci_le_subev_periodic_adv_sync_lost *data = (void *) evdata;
if (len != sizeof(*data)) {
BLE_HS_LOG(DEBUG, "Corrupted LE Periodic Advertising Sync Lost "
@@ -272,6 +272,7 @@ ble_hs_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
"len=%u handle=0x%04x", len, le16toh(data->sync_handle));
break;
}
#endif
case BLE_HCI_LE_SUBEV_SCAN_TIMEOUT:
if (len) {
+158
View File
@@ -1605,6 +1605,164 @@ ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,
return 0;
}
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
int
ble_hs_hci_cmd_build_le_periodic_adv_params(uint8_t handle,
const struct hci_periodic_adv_params *params,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN);
if (handle > 0xEF){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (params->max_interval > 0xFFFF || params->max_interval < 6){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (params->min_interval > 0xFFFF || params->min_interval < 6){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = handle;
put_le16(&cmd[1], params->min_interval);
put_le16(&cmd[3], params->max_interval);
put_le16(&cmd[5], params->properties);
return 0;
}
int
ble_hs_hci_cmd_build_le_periodic_adv_enable(uint8_t enable,
uint8_t handle,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN);
if (enable > 1){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = enable;
cmd[1] = handle;
return 0;
}
int
ble_hs_hci_cmd_build_le_periodic_adv_data(uint8_t handle,
uint8_t operation,
struct os_mbuf *data,
uint8_t data_len,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= 3 + data_len);
if (!data){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (!data->om_data){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (handle > 0xEF){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = handle;
cmd[1] = operation;
cmd[2] = data_len;
os_mbuf_copydata(data, 0, data_len, cmd + 3);
return 0;
}
int
ble_hs_hci_cmd_build_le_periodic_adv_create_sync(uint8_t filter_policy,
uint8_t adv_sid,
uint8_t adv_add_type,
const uint8_t *adv_addr,
uint16_t skip,
uint16_t sync_timeout,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN);
if (filter_policy > 1 || adv_add_type > 1){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (adv_sid > 0x0f){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (skip > 0x1f3 || sync_timeout > 0x4000 || sync_timeout < 0x0A){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = filter_policy;
cmd[1] = adv_sid;
cmd[2] = adv_add_type;
memcpy(&cmd[3], adv_addr, 6);
put_le16(&cmd[9], skip);
put_le16(&cmd[11], sync_timeout);
cmd[13] = 0x00;
return 0;
}
int
ble_hs_hci_cmd_build_le_periodic_adv_terminate_sync(uint16_t sync_handle,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN);
if (sync_handle > 0xEF){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = sync_handle;
return 0;
}
int
ble_hs_hci_cmd_build_le_add_dev_to_periodic_adv_list(
uint8_t adv_add_type,
const uint8_t *adv_addr,
uint8_t adv_sid,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN);
if (adv_add_type > 1 || adv_sid > 0x0f){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = adv_add_type;
memcpy(&cmd[1], adv_addr, 6);
cmd[7] = adv_sid;
return 0;
}
int
ble_hs_hci_cmd_build_le_rem_dev_from_periodic_adv_list(
uint8_t adv_add_type,
const uint8_t *adv_addr,
uint8_t adv_sid,
uint8_t *cmd, int cmd_len)
{
BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN);
if (adv_add_type > 1 || adv_sid > 0x0f){
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd[0] = adv_add_type;
memcpy(&cmd[1], adv_addr, 6);
cmd[7] = adv_sid;
return 0;
}
#endif
#endif
static int
+83 -4
View File
@@ -51,7 +51,9 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_ext_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_rem_used_feat_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_timeout;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_adv_set_terminated;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_estab;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_lost;
/* Statistics */
struct host_hci_stats
{
@@ -100,6 +102,11 @@ static const struct ble_hs_hci_evt_le_dispatch_entry
{ BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE,
ble_hs_hci_evt_le_phy_update_complete },
{ BLE_HCI_LE_SUBEV_EXT_ADV_RPT, ble_hs_hci_evt_le_ext_adv_rpt },
{ BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB,
ble_hs_hci_evt_le_periodic_adv_sync_estab},
{ BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT, ble_hs_hci_evt_le_periodic_adv_rpt},
{ BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST,
ble_hs_hci_evt_le_periodic_adv_sync_lost},
{ BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT,
ble_hs_hci_evt_le_rd_rem_used_feat_complete },
{ BLE_HCI_LE_SUBEV_SCAN_TIMEOUT,
@@ -226,7 +233,8 @@ ble_hs_hci_evt_enc_key_refresh(uint8_t event_code, uint8_t *data, int len)
}
static int
ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, uint8_t *data, int len)
ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, uint8_t *data,
int len)
{
struct ble_hs_conn *conn;
uint16_t num_pkts;
@@ -501,8 +509,9 @@ ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
}
static int
ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, uint8_t *data,
int len)
ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent,
uint8_t *data,
int len)
{
struct hci_le_rd_rem_supp_feat_complete evt;
@@ -614,6 +623,76 @@ ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, uint8_t *data, int len)
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_sync_estab(uint8_t subevent, uint8_t *data,
int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV)
struct hci_le_subev_periodic_adv_sync_estab evt;
if (len < BLE_HCI_LE_PERIODIC_ADV_SYNC_ESTAB_LEN) {
return BLE_HS_ECONTROLLER;
}
evt.status = data[1];
evt.sync_handle = get_le16(data + 2);
evt.sid = data[4];
evt.adv_addr_type = data[5];
memcpy(evt.adv_addr, &data[6], 6);
evt.adv_phy = data[12];
evt.per_adv_ival = get_le16(data + 13);
evt.adv_clk_accuracy = data[15];
ble_gap_rx_peroidic_adv_sync_estab(&evt);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_rpt(uint8_t subevent, uint8_t *data,
int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV)
struct hci_le_subev_periodic_adv_rpt evt;
if (len < BLE_HCI_LE_PERIODIC_ADV_RPT_LEN) {
return BLE_HS_EBADDATA;
}
evt.sync_handle = get_le16(data + 1);
evt.tx_power = data[3];
evt.rssi = data[4];
evt.data_status = data[6];
evt.data_length = data[7];
memcpy(evt.data, &data[8], evt.data_length);
ble_gap_rx_periodic_adv_rpt(&evt);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_sync_lost(uint8_t subevent, uint8_t *data,
int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV)
struct hci_le_subev_periodic_adv_sync_lost evt;
if (len < BLE_HCI_LE_PERIODIC_ADV_SYNC_LOST_LEN) {
return BLE_HS_EBADDATA;
}
evt.sync_handle = get_le16(data + 1);
ble_gap_rx_periodic_adv_sync_lost(&evt);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_scan_timeout(uint8_t subevent, uint8_t *data, int len)
{
+42
View File
@@ -235,6 +235,48 @@ ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,
int
ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,
uint8_t *cmd, int cmd_len);
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
int
ble_hs_hci_cmd_build_le_periodic_adv_params(uint8_t handle,
const struct hci_periodic_adv_params *params,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_periodic_adv_enable(uint8_t enable,
uint8_t handle,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_periodic_adv_data(uint8_t handle, uint8_t operation,
struct os_mbuf *data,
uint8_t data_len,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_periodic_adv_create_sync(uint8_t filter_policy,
uint8_t adv_sid,
uint8_t adv_add_type,
const uint8_t *adv_addr,
uint16_t skip,
uint16_t sync_timeout,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_periodic_adv_terminate_sync(uint16_t sync_handle,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_add_dev_to_periodic_adv_list(uint8_t adv_add_type,
const uint8_t *adv_addr,
uint8_t adv_sid,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_rem_dev_from_periodic_adv_list(uint8_t adv_add_type,
const uint8_t *adv_addr,
uint8_t adv_sid,
uint8_t *cmd, int cmd_len);
#endif
#endif
int ble_hs_hci_cmd_build_le_enh_recv_test(uint8_t rx_chan, uint8_t phy,
+230
View File
@@ -0,0 +1,230 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <string.h>
#include <errno.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
#include "host/ble_hs_id.h"
#include "ble_hs_priv.h"
static SLIST_HEAD(, ble_hs_periodic_sync) ble_hs_periodic_sync_handles;
static struct os_mempool ble_hs_periodic_sync_pool;
static os_membuf_t ble_hs_psync_elem_mem[
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_PERIODIC_SCANNING_SM),
sizeof (struct ble_hs_periodic_sync))
];
int
ble_hs_periodic_sync_can_alloc(void)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return 0;
#endif
return (ble_hs_periodic_sync_pool.mp_num_free >= 1);
}
struct ble_hs_periodic_sync *
ble_hs_periodic_sync_alloc(void)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return NULL;
#endif
struct ble_hs_periodic_sync *psync;
psync = os_memblock_get(&ble_hs_periodic_sync_pool);
if (psync == NULL) {
goto err;
}
memset(psync, 0, sizeof *psync);
return psync;
err:
ble_hs_periodic_sync_free(psync);
return NULL;
}
void
ble_hs_periodic_sync_free(struct ble_hs_periodic_sync *psync)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return;
#endif
int rc;
if (psync == NULL) {
return;
}
#if MYNEWT_VAL(BLE_HS_DEBUG)
memset(psync, 0xff, sizeof *psync);
#endif
rc = os_memblock_put(&ble_hs_periodic_sync_pool, psync);
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
}
void
ble_hs_periodic_sync_insert(struct ble_hs_periodic_sync *psync)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return;
#endif
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
BLE_HS_DBG_ASSERT_EVAL(
ble_hs_periodic_sync_find(psync->sync_handle) == NULL);
SLIST_INSERT_HEAD(&ble_hs_periodic_sync_handles, psync, bhc_next);
}
void
ble_hs_periodic_sync_remove(struct ble_hs_periodic_sync *psync)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return;
#endif
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
SLIST_REMOVE(&ble_hs_periodic_sync_handles,
psync,
ble_hs_periodic_sync,
bhc_next);
}
struct ble_hs_periodic_sync *
ble_hs_periodic_sync_find(uint16_t sync_handle)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return NULL;
#endif
struct ble_hs_periodic_sync *psync;
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
SLIST_FOREACH(psync, &ble_hs_periodic_sync_handles, bhc_next) {
if (psync->sync_handle == sync_handle) {
return psync;
}
}
return NULL;
}
struct ble_hs_periodic_sync *
ble_hs_periodic_sync_find_assert(uint16_t sync_handle)
{
struct ble_hs_periodic_sync *psync;
psync = ble_hs_periodic_sync_find(sync_handle);
BLE_HS_DBG_ASSERT(psync != NULL);
return psync;
}
struct ble_hs_periodic_sync *
ble_hs_periodic_sync_find_by_adv_addr(const ble_addr_t *addr)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return NULL;
#endif
struct ble_hs_periodic_sync *psync;
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
if (!addr) {
return NULL;
}
SLIST_FOREACH(psync, &ble_hs_periodic_sync_handles, bhc_next) {
if (ble_addr_cmp(&psync->advertiser_addr, addr) == 0) {
return psync;
}
}
return NULL;
}
struct ble_hs_periodic_sync *
ble_hs_periodic_sync_find_by_adv_sid(uint16_t sid)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return 0;
#endif
struct ble_hs_periodic_sync *psync;
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
SLIST_FOREACH(psync, &ble_hs_periodic_sync_handles, bhc_next) {
if (psync->adv_sid == sid) {
return psync;
}
}
return NULL;
}
int
ble_hs_periodic_sync_exists(uint16_t sync_handle)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return 0;
#endif
return ble_hs_periodic_sync_find(sync_handle) != NULL;
}
/**
* Retrieves the first periodic discovery handle in the list.
*/
struct ble_hs_periodic_sync *
ble_hs_periodic_sync_first(void)
{
#if !MYNEWT_VAL(BLE_PERIODIC_ADV)
return NULL;
#endif
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
return SLIST_FIRST(&ble_hs_periodic_sync_handles);
}
int
ble_hs_periodic_sync_init(void)
{
int rc;
rc = os_mempool_init(&ble_hs_periodic_sync_pool,
MYNEWT_VAL(BLE_MAX_PERIODIC_SCANNING_SM),
sizeof (struct ble_hs_periodic_sync),
ble_hs_psync_elem_mem, "ble_hs_periodic_disc_pool");
if (rc != 0) {
return BLE_HS_EOS;
}
SLIST_INIT(&ble_hs_periodic_sync_handles);
return 0;
}
@@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_BLE_HS_PERIODIC_DISC_
#define H_BLE_HS_PERIODIC_DISC_
#include <inttypes.h>
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct ble_hs_periodic_sync {
SLIST_ENTRY(ble_hs_periodic_sync) bhc_next;
uint16_t sync_handle;
uint8_t adv_sid;
uint8_t advertiser_addr_type;
ble_addr_t advertiser_addr;
uint8_t advertiser_phy;
uint16_t periodic_adv_itvl;
uint8_t advertiser_clock_accuracy;
};
int ble_hs_periodic_sync_can_alloc(void);
struct ble_hs_periodic_sync *ble_hs_periodic_sync_alloc(void);
void ble_hs_periodic_sync_free(struct ble_hs_periodic_sync *psync);
void ble_hs_periodic_sync_insert(struct ble_hs_periodic_sync *psync);
void ble_hs_periodic_sync_remove(struct ble_hs_periodic_sync *psync);
struct ble_hs_periodic_sync *ble_hs_periodic_sync_find(
uint16_t sync_handle);
struct ble_hs_periodic_sync *ble_hs_periodic_sync_find_assert(
uint16_t sync_handle);
struct ble_hs_periodic_sync *ble_hs_periodic_sync_find_by_adv_addr(
const ble_addr_t *addr);
struct ble_hs_periodic_sync *ble_hs_periodic_sync_find_by_adv_sid(
uint16_t sid);
int ble_hs_periodic_sync_exists(uint16_t sync_handle);
struct ble_hs_periodic_sync *ble_hs_periodic_sync_first(void);
int ble_hs_periodic_sync_init(void);
#ifdef __cplusplus
}
#endif
#endif
+1
View File
@@ -30,6 +30,7 @@
#include "ble_hs_hci_priv.h"
#include "ble_hs_atomic_priv.h"
#include "ble_hs_conn_priv.h"
#include "ble_hs_periodic_disc_priv.h"
#include "ble_hs_atomic_priv.h"
#include "ble_hs_mbuf_priv.h"
#include "ble_hs_startup_priv.h"
+4 -1
View File
@@ -256,12 +256,15 @@ ble_hs_startup_le_set_evmask_tx(void)
* Enable the following LE events:
* 0x0000000000000800 LE PHY Update Complete Event
* 0x0000000000001000 LE Extended Advertising Report Event
* 0x0000000000002000 LE Periodic Advertising Sync Established Event
* 0x0000000000004000 LE Periodic Advertising Report Event
* 0x0000000000008000 LE Periodic Advertising Sync Lost Event
* 0x0000000000010000 LE Extended Scan Timeout Event
* 0x0000000000020000 LE Extended Advertising Set Terminated Event
* 0x0000000000040000 LE Scan Request Received Event
* 0x0000000000080000 LE Channel Selection Algorithm Event
*/
mask |= 0x00000000000f1800;
mask |= 0x00000000000ff800;
}
ble_hs_hci_cmd_build_le_set_event_mask(mask, buf, sizeof buf);
+45 -3
View File
@@ -58,10 +58,52 @@ ble_hs_stop_done(int status)
}
}
/**
* Terminates all active periodic sync handles
*
* If there are no active periodic sync handles, signals completion of the
* close procedure.
*/
static int
ble_hs_stop_terminate_next_periodic_sync(void)
{
int rc = 0;
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
struct ble_hs_periodic_sync *psync;
while((psync = ble_hs_periodic_sync_first())){
/* Terminate sync command waits a command complete event, so there
* is no need to wait for GAP event, as the calling thread will be
* blocked on the hci semaphore until the command complete is received.
*
* Also, once the sync is terminated, the psync will be freed and
* removed from the list such that the next call to
* ble_hs_periodic_sync_first yields the next psync handle
*/
rc = ble_gap_periodic_adv_terminate_sync(psync->sync_handle);
if (!rc){
BLE_HS_LOG(ERROR,
"ble_hs_stop: failed to terminate connection; rc=%d\n",
rc);
ble_hs_stop_done(rc);
}
}
#endif
/* No more active periodic sync handles (Or periodic advertising
* is not supported), Signal completion of the stop procedure.
*/
ble_hs_stop_done(0);
return rc;
}
/**
* Terminates the first open connection.
*
* If there are no open connections, signals completion of the close procedure.
* If there are no open connections, Check for any active periodic sync
* handles.
*/
static void
ble_hs_stop_terminate_next_conn(void)
@@ -71,8 +113,8 @@ ble_hs_stop_terminate_next_conn(void)
handle = ble_hs_atomic_first_conn_handle();
if (handle == BLE_HS_CONN_HANDLE_NONE) {
/* No open connections. Signal completion of the stop procedure. */
ble_hs_stop_done(0);
/* No open connections. Check for any active periodic sync */
ble_hs_stop_terminate_next_periodic_sync();
return;
}
+53 -33
View File
@@ -149,19 +149,19 @@ extern "C" {
#define BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS (0x003B)
#define BLE_HCI_OCF_LE_REMOVE_ADV_SET (0x003C)
#define BLE_HCI_OCF_LE_CLEAR_ADV_SETS (0x003D)
#define BLE_HCI_OCF_LE_SET_PER_ADV_PARAMS (0x003E)
#define BLE_HCI_OCF_LE_SET_PER_ADV_DATA (0x003F)
#define BLE_HCI_OCF_LE_SET_PER_ADV_ENABLE (0x0040)
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS (0x003E)
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA (0x003F)
#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE (0x0040)
#define BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM (0x0041)
#define BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE (0x0042)
#define BLE_HCI_OCF_LE_EXT_CREATE_CONN (0x0043)
#define BLE_HCI_OCF_LE_PER_ADV_CREATE_SYNC (0x0044)
#define BLE_HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL (0x0045)
#define BLE_HCI_OCF_LE_PER_ADV_TERM_SYNC (0x0046)
#define BLE_HCI_OCF_LE_ADD_DEV_TO_PER_ADV_LIST (0x0047)
#define BLE_HCI_OCF_LE_REM_DEV_FROM_PER_ADV_LIST (0x0048)
#define BLE_HCI_OCF_LE_CLEAR_PER_ADV_LIST (0x0049)
#define BLE_HCI_OCF_LE_RD_PER_ADV_LIST_SIZE (0x004A)
#define BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC (0x0044)
#define BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL (0x0045)
#define BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC (0x0046)
#define BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST (0x0047)
#define BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST (0x0048)
#define BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST (0x0049)
#define BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE (0x004A)
#define BLE_HCI_OCF_LE_RD_TRANSMIT_POWER (0x004B)
#define BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION (0x004C)
#define BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION (0x004D)
@@ -522,21 +522,18 @@ extern "C" {
#define BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN (4)
#define BLE_HCI_LE_SET_EXT_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN
#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT (0)
#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST (1)
#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST (2)
#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE (3)
#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED (4)
#define BLE_HCI_LE_SET_DATA_OPER_INT (0)
#define BLE_HCI_LE_SET_DATA_OPER_FIRST (1)
#define BLE_HCI_LE_SET_DATA_OPER_LAST (2)
#define BLE_HCI_LE_SET_DATA_OPER_COMPLETE (3)
#define BLE_HCI_LE_SET_DATA_OPER_UNCHANGED (4)
/* --- LE set extended scan response data (OCF 0x0038) */
#define BLE_HCI_MAX_EXT_SCAN_RSP_DATA_LEN (251)
#define BLE_HCI_SET_EXT_SCAN_RSP_DATA_HDR_LEN (4)
#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_LEN BLE_HCI_VARIABLE_LEN
#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT (0)
#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST (1)
#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_LAST (2)
#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE (3)
/* --- LE set extended advertising enable (OCF 0x0039) */
#define BLE_HCI_LE_SET_EXT_ADV_ENABLE_LEN BLE_HCI_VARIABLE_LEN
@@ -551,13 +548,18 @@ extern "C" {
#define BLE_HCI_RD_NR_SUP_ADV_SETS (1)
/* --- LE set periodic advertising parameters (OCF 0x003E) */
#define BLE_HCI_LE_SET_PER_ADV_PARAMS_LEN (7)
#define BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN (7)
#define BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR (0x0040)
/* --- LE set periodic advertising data (OCF 0x003F) */
#define BLE_HCI_LE_SET_PER_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN
#define BLE_HCI_LE_SET_PERIODIC_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN
#define BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN (252)
#define BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN (3)
/* --- LE periodic advertising enable (OCF 0x0040) */
#define BLE_HCI_LE_SET_PER_ADV_ENABLE_LEN (2)
#define BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN (2)
/* --- LE set extended scan parameters (OCF 0x0041) */
#define BLE_HCI_LE_SET_EXT_SCAN_PARAM_LEN BLE_HCI_VARIABLE_LEN
@@ -572,16 +574,16 @@ extern "C" {
#define BLE_HCI_LE_EXT_CREATE_CONN_BASE_LEN (10)
/* --- LE periodic advertising create sync (OCF 0x0044) */
#define BLE_HCI_LE_PER_ADV_CREATE_SYNC_LEN (14)
#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN (14)
/* --- LE periodic advertising terminate (OCF 0x0046) */
#define BLE_HCI_LE_PER_ADV_TERM_SYNC_LEN (2)
#define BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN (2)
/* --- LE add device to periodic advertising list (OCF 0x0047) */
#define BLE_HCI_LE_ADD_DEV_TO_PER_ADV_LIST_LEN (8)
#define BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN (8)
/* --- LE remove device from periodic advertising list (OCF 0x0048) */
#define BLE_HCI_LE_REM_DEV_FROM_PER_ADV_LIST_LEN (8)
#define BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN (8)
/* --- LE write RF path (OCF 0x004D) */
#define BLE_HCI_LE_WR_RF_PATH_COMPENSATION_LEN (4)
@@ -685,9 +687,9 @@ extern "C" {
#define BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT (0x0B)
#define BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE (0x0C)
#define BLE_HCI_LE_SUBEV_EXT_ADV_RPT (0x0D)
#define BLE_HCI_LE_SUBEV_PER_ADV_SYNC_ESTAB (0x0E)
#define BLE_HCI_LE_SUBEV_PER_ADV_RPT (0x0F)
#define BLE_HCI_LE_SUBEV_PER_ADV_SYNC_LOST (0x10)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT (0x0F)
#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST (0x10)
#define BLE_HCI_LE_SUBEV_SCAN_TIMEOUT (0x11)
#define BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED (0x12)
#define BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD (0x13)
@@ -780,6 +782,15 @@ extern "C" {
/* LE PHY update complete event (sub event 0x0C) */
#define BLE_HCI_LE_PHY_UPD_LEN (6)
/* LE Periodic Advertising Sync Established Event (sub event 0x0e) */
#define BLE_HCI_LE_PERIODIC_ADV_SYNC_ESTAB_LEN (16)
/* LE Periodic Advertising Report Event (sub event 0x0f) */
#define BLE_HCI_LE_PERIODIC_ADV_RPT_LEN (8)
/* LE Periodic Advertising Sync Lost Event (sub event 0x10) */
#define BLE_HCI_LE_PERIODIC_ADV_SYNC_LOST_LEN (3)
/* LE Scan Timeout Event (sub event 0x11) */
#define BLE_HCI_LE_SUBEV_SCAN_TIMEOUT_LEN (1)
@@ -990,8 +1001,17 @@ struct hci_le_subev_ext_adv_rpt {
struct hci_ext_adv_report_param params[0];
} __attribute__((packed));
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
/* Periodic Advertising Parameters */
struct hci_periodic_adv_params
{
uint16_t min_interval;
uint16_t max_interval;
uint16_t properties;
};
/* LE Periodic Advertising Sync Established Event */
struct hci_le_subev_per_adv_sync_estab {
struct hci_le_subev_periodic_adv_sync_estab {
uint8_t status;
uint16_t sync_handle;
uint8_t sid;
@@ -1003,20 +1023,20 @@ struct hci_le_subev_per_adv_sync_estab {
} __attribute__((packed));
/* LE Periodic Advertising Report Event */
struct hci_le_subev_per_adv_rpt {
struct hci_le_subev_periodic_adv_rpt {
uint16_t sync_handle;
uint8_t tx_power;
int8_t rssi;
uint8_t _unused;
uint8_t data_status;
uint8_t data_length;
uint8_t data[0];
} __attribute__((packed));
/* LE Periodic Advertising Sync Lost Event */
struct hci_le_subev_per_adv_sync_lost {
struct hci_le_subev_periodic_adv_sync_lost {
uint16_t sync_handle;
} __attribute__((packed));
#endif
/* LE Advertising Set Terminated Event */
struct hci_le_subev_adv_set_terminated {
+9
View File
@@ -34,6 +34,11 @@ syscfg.defs:
BLE_MAX_CONNECTIONS:
description: 'The maximum number of concurrent connections.'
value: 1
BLE_MAX_PERIODIC_SCANNING_SM:
description: >
The maximum number of concurrent periodic syncs that can
be created
value: 1
BLE_WHITELIST:
description: >
Enables the BLE whitelist for controlling who to connect to or
@@ -50,6 +55,10 @@ syscfg.defs:
description: >
This enables extended advertising feature.
value: 0
BLE_PERIODIC_ADV:
description: >
This enables periodic advertising feature.
value: 0
BLE_EXT_ADV_MAX_SIZE:
description: >
This allows to configure maximum size of advertising data and
@@ -247,6 +247,10 @@
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
#endif
#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM
#define MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM (0)
#endif
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
#endif
@@ -247,6 +247,10 @@
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
#endif
#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM
#define MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM (0)
#endif
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
#endif
+1
View File
@@ -50,6 +50,7 @@ NIMBLE_SRC := \
$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/lls/src/*.c)) \
$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/tps/src/*.c)) \
$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/store/ram/src/*.c)) \
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_periodic_disc.c \
$(NULL)
ifneq (,$(NIMBLE_CFG_CONTROLLER))
+9
View File
@@ -389,6 +389,10 @@
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
#endif
#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM
#define MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM (0)
#endif
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
#endif
@@ -418,6 +422,11 @@
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
#endif
#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV
#define MYNEWT_VAL_BLE_PERIODIC_ADV (0)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO
#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1)
#endif
+4
View File
@@ -410,6 +410,10 @@
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
#endif
#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM
#define MYNEWT_VAL_BLE_MAX_PERIODIC_SCANNING_SM (0)
#endif
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
#endif