nimble: Use packed structures for HCI commands and events

This patch changes way HCI protocol is passed between host and
controller. Rule of thumb is that structures defined as packed
represent protocol order (LE) binary data, while normal structs
hold host order decoded (unpacked) data.

Packed structs are always used to parse or prepare HCI data. In
general HCI data is parsed only where needed and pass 'as-is'
up to stack as much as possible (this is to minimize need to copy
data).

Some additional changes and cleanups are also part of this commit
(due to invasive nature of this commit) to avoid unnecessary rebases
and conflicts:
 - constified pointers where needed (when passing packed data up)
 - updated HCI names as specified in Core 5.1

This commit not only improves code readiblity (ie it is easy to
check where data is used, as well as when it is expected to be
in host or in protocol order) but also reduces code size. Some
numbers for build with most features enabled (optimized build):
nimble_controller.a     55602 -> 55246
nimble_host.a           68001 -> 65285
This commit is contained in:
Szymon Janc
2019-10-15 08:24:27 +02:00
parent 89e49d6bae
commit 9c6f8b1ac9
60 changed files with 4548 additions and 6178 deletions
+2 -2
View File
@@ -161,7 +161,7 @@ btshell_print_error(char *msg, uint16_t conn_handle,
static void
btshell_print_adv_fields(const struct ble_hs_adv_fields *fields)
{
uint8_t *u8p;
const uint8_t *u8p;
int i;
if (fields->flags != 0) {
@@ -939,7 +939,7 @@ btshell_on_write_reliable(uint16_t conn_handle,
}
static void
btshell_decode_adv_data(uint8_t *adv_data, uint8_t adv_data_len, void *arg)
btshell_decode_adv_data(const uint8_t *adv_data, uint8_t adv_data_len, void *arg)
{
struct btshell_scan_opts *scan_opts = arg;
struct ble_hs_adv_fields fields;
+3 -3
View File
@@ -397,7 +397,7 @@ static void stop_advertising(const u8_t *data, u16_t len)
(u8_t *) &rp, sizeof(rp));
}
static u8_t get_ad_flags(u8_t *data, u8_t data_len)
static u8_t get_ad_flags(const u8_t *data, u8_t data_len)
{
u8_t len, i;
@@ -428,7 +428,7 @@ static u8_t discovery_flags;
static struct os_mbuf *adv_buf;
static void store_adv(const ble_addr_t *addr, s8_t rssi,
u8_t *data, u8_t len)
const u8_t *data, u8_t len)
{
struct gap_device_found_ev *ev;
@@ -446,7 +446,7 @@ static void store_adv(const ble_addr_t *addr, s8_t rssi,
}
static void device_found(ble_addr_t *addr, s8_t rssi, u8_t evtype,
u8_t *data, u8_t len)
const u8_t *data, u8_t len)
{
struct gap_device_found_ev *ev;
ble_addr_t a;
@@ -39,10 +39,10 @@ uint8_t ble_hw_whitelist_size(void);
void ble_hw_whitelist_clear(void);
/* Remove a device from the hw whitelist */
void ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type);
void ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type);
/* Add a device to the hw whitelist */
int ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type);
int ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type);
/* Enable hw whitelisting */
void ble_hw_whitelist_enable(void);
@@ -426,7 +426,7 @@ void ble_ll_init(void);
int ble_ll_reset(void);
/* 'Boolean' function returning true if address is a valid random address */
int ble_ll_is_valid_random_addr(uint8_t *addr);
int ble_ll_is_valid_random_addr(const uint8_t *addr);
/* Calculate the amount of time in microseconds a PDU with payload length of
* 'payload_len' will take to transmit on a PHY 'phy_mode'. */
@@ -437,7 +437,7 @@ uint32_t ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode);
uint16_t ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode);
/* Is this address a resolvable private address? */
int ble_ll_is_rpa(uint8_t *addr, uint8_t addr_type);
int ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type);
/* Is this address an identity address? */
int ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type);
@@ -513,7 +513,7 @@ void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu);
int ble_ll_set_public_addr(const uint8_t *addr);
/* Set random address */
int ble_ll_set_random_addr(uint8_t *addr, bool hci_adv_ext);
int ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext);
/* Enable wait for response timer */
void ble_ll_wfr_enable(uint32_t cputime);
@@ -117,19 +117,16 @@ int ble_ll_adv_start_req(uint8_t adv_chanmask, uint8_t adv_type,
uint8_t *init_addr, uint16_t adv_itvl, void *handle);
/* Start or stop advertising */
int ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, int duration,
uint8_t event);
int ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len);
/* Set advertising data */
int ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
uint8_t operation);
/* Set legacy advertising data */
int ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len);
/* Set scan response data */
int ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len,
uint8_t instance, uint8_t operation);
int ble_ll_hci_set_scan_rsp_data(const uint8_t *cmd, uint8_t cmd_len);
/* Set advertising parameters */
int ble_ll_adv_set_adv_params(uint8_t *cmd);
int ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len);
/* Read advertising channel power */
int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen);
@@ -185,17 +182,19 @@ void ble_ll_adv_halt(void);
/* Called to determine if advertising is enabled */
uint8_t ble_ll_adv_enabled(void);
int ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance);
int ble_ll_adv_remove(uint8_t instance);
int ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance);
int ble_ll_adv_remove(const uint8_t *addr, uint8_t len);
int ble_ll_adv_clear_all(void);
int ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_adv_ext_set_adv_data(uint8_t *cmdbuf, uint8_t cmdlen);
int ble_ll_adv_ext_set_scan_rsp(uint8_t *cmdbuf, uint8_t cmdlen);
int ble_ll_adv_ext_set_enable(uint8_t *cmdbuf, uint8_t len);
int ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen);
int ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen);
int ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_adv_periodic_set_param(uint8_t *cmdbuf);
int ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen);
int ble_ll_adv_periodic_enable(uint8_t *cmdbuf);
int ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len);
/* Called to notify adv code about RPA rotation */
void ble_ll_adv_rpa_timeout(void);
@@ -175,6 +175,39 @@ struct ble_ll_conn_phy_data
#define BLE_PHY_TRANSITION_INVALID (0xFF)
struct hci_conn_update
{
uint16_t handle;
uint16_t conn_itvl_min;
uint16_t conn_itvl_max;
uint16_t conn_latency;
uint16_t supervision_timeout;
uint16_t min_ce_len;
uint16_t max_ce_len;
};
struct hci_ext_conn_params
{
uint16_t scan_itvl;
uint16_t scan_window;
uint16_t conn_itvl_min;
uint16_t conn_itvl_max;
uint16_t conn_latency;
uint16_t supervision_timeout;
uint16_t min_ce_len;
uint16_t max_ce_len;
};
struct hci_ext_create_conn
{
uint8_t filter_policy;
uint8_t own_addr_type;
uint8_t peer_addr_type;
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
uint8_t init_phy_mask;
struct hci_ext_conn_params params[3];
};
/* Connection state machine */
struct ble_ll_conn_sm
{
@@ -280,7 +280,7 @@ int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status);
void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm);
void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm);
void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm);
void ble_ll_hci_ev_send_vendor_err(char *file, uint32_t line);
void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line);
#ifdef __cplusplus
}
@@ -24,6 +24,8 @@
extern "C" {
#endif
#include "nimble/hci_common.h"
/* For supported commands */
#define BLE_LL_SUPP_CMD_LEN (40)
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
@@ -45,19 +47,20 @@ typedef void (*ble_ll_hci_post_cmd_complete_cb)(void);
void ble_ll_hci_init(void);
/* Used to determine if the LE event is enabled/disabled */
uint8_t ble_ll_hci_is_le_event_enabled(int subev);
bool ble_ll_hci_is_le_event_enabled(unsigned int subev);
/* Used to determine if event is enabled/disabled */
uint8_t ble_ll_hci_is_event_enabled(int evcode);
bool ble_ll_hci_is_event_enabled(unsigned int evcode);
/* Send event from controller to host */
int ble_ll_hci_event_send(uint8_t *evbuf);
int ble_ll_hci_event_send(struct ble_hci_ev *hci_ev);
/* Sends a command complete with a no-op opcode to host */
int ble_ll_hci_send_noop(void);
void ble_ll_hci_send_noop(void);
/* Checks the preferref phy masks from set default phy and set phy commands */
int ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy);
int ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys,
uint8_t *txphy, uint8_t *rxphy);
/* Returns true if Extended Advertising HCI commands are in use */
bool ble_ll_hci_adv_mode_ext(void);
@@ -51,22 +51,22 @@ int ble_ll_resolv_list_clr(void);
int ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen);
/* Add a device to the resolving list */
int ble_ll_resolv_list_add(uint8_t *cmdbuf);
int ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len);
/* Remove a device from the resolving list */
int ble_ll_resolv_list_rmv(uint8_t *cmdbuf);
int ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len);
/* Address resolution enable command */
int ble_ll_resolv_enable_cmd(uint8_t *cmdbuf);
int ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_resolv_peer_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */
struct ble_ll_resolv_entry *
ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type);
ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type);
/* Called to determine if the IRK is all zero. */
int ble_ll_resolv_irk_nonzero(uint8_t *irk);
@@ -88,10 +88,10 @@ int ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa,
int local);
/* Set the resolvable private address timeout */
int ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf);
int ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len);
/* Set the privacy mode */
int ble_ll_resolve_set_priv_mode(uint8_t *cmdbuf);
int ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len);
/* Get the RPA timeout, in seconds */
uint32_t ble_ll_resolv_get_rpa_tmo(void);
@@ -116,9 +116,9 @@ struct ble_ll_aux_data {
uint8_t addr_type;
uint8_t dir_addr[6];
uint8_t dir_addr_type;
uint8_t evt_type;
uint16_t evt_type;
struct ble_ll_sched_item sch;
struct ble_ll_ext_adv_report *evt;
struct ble_hci_ev *evt;
struct ble_npl_event ev;
};
@@ -178,13 +178,14 @@ struct ble_ll_scan_sm
/*---- HCI ----*/
/* Set scanning parameters */
int ble_ll_scan_set_scan_params(uint8_t *cmd);
int ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len);
/* Turn scanning on/off */
int ble_ll_scan_set_enable(uint8_t *cmd, uint8_t ext);
int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int ble_ll_set_ext_scan_params(uint8_t *cmd, uint8_t cmdlen);
int ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len);
#endif
/*--- Controller Internal API ---*/
@@ -258,13 +259,6 @@ int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
struct ble_ll_scan_sm **sm);
/* Called to parse extended advertising*/
struct ble_ll_ext_adv_report;
int ble_ll_scan_parse_ext_hdr(struct os_mbuf *om,
uint8_t *adva, uint8_t adva_type,
uint8_t *inita, uint8_t inita_type,
struct ble_mbuf_hdr *ble_hdr,
struct ble_ll_ext_adv_report *parsed_evt);
struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan);
void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan);
void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
@@ -29,11 +29,11 @@
extern "C" {
#endif
int ble_ll_sync_create(uint8_t *cmdbuf);
int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb);
int ble_ll_sync_terminate(uint8_t *cmdbuf);
int ble_ll_sync_list_add(uint8_t *cmdbuf);
int ble_ll_sync_list_remove(uint8_t *cmdbuf);
int ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_list_clear(void);
int ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen);
@@ -31,10 +31,10 @@ int ble_ll_whitelist_clear(void);
int ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen);
/* Add a device to the whitelist */
int ble_ll_whitelist_add(uint8_t *addr, uint8_t addr_type);
int ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len);
/* Remove a device fromthe whitelist */
int ble_ll_whitelist_rmv(uint8_t *addr, uint8_t addr_type);
int ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len);
/* Enable whitelisting */
void ble_ll_whitelist_enable(void);
+12 -6
View File
@@ -421,7 +421,7 @@ ble_ll_chk_txrx_time(uint16_t time)
* @return int
*/
int
ble_ll_is_rpa(uint8_t *addr, uint8_t addr_type)
ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type)
{
int rc;
@@ -441,7 +441,7 @@ ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type)
/* Checks to see that the device is a valid random address */
int
ble_ll_is_valid_random_addr(uint8_t *addr)
ble_ll_is_valid_random_addr(const uint8_t *addr)
{
int i;
int rc;
@@ -502,8 +502,14 @@ ble_ll_set_public_addr(const uint8_t *addr)
* @return int 0: success
*/
int
ble_ll_set_random_addr(uint8_t *addr, bool hci_adv_ext)
ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext)
{
const struct ble_hci_le_set_rand_addr_cp *cmd = (const void *) cmdbuf;
if (len < sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* If the Host issues this command when scanning or legacy advertising is
* enabled, the Controller shall return the error code Command Disallowed.
*
@@ -515,11 +521,11 @@ ble_ll_set_random_addr(uint8_t *addr, bool hci_adv_ext)
return BLE_ERR_CMD_DISALLOWED;
}
if (!ble_ll_is_valid_random_addr(addr)) {
if (!ble_ll_is_valid_random_addr(cmd->addr)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
memcpy(g_random_addr, addr, BLE_DEV_ADDR_LEN);
memcpy(g_random_addr, cmd->addr, BLE_DEV_ADDR_LEN);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
/* For instance 0 we need same address if legacy advertising might be
@@ -527,7 +533,7 @@ ble_ll_set_random_addr(uint8_t *addr, bool hci_adv_ext)
* affect instance 0.
*/
if (!hci_adv_ext)
ble_ll_adv_set_random_addr(addr, 0);
ble_ll_adv_set_random_addr(cmd->addr, 0);
#endif
return BLE_ERR_SUCCESS;
+214 -197
View File
@@ -1617,38 +1617,38 @@ ble_ll_adv_halt(void)
* @return int
*/
int
ble_ll_adv_set_adv_params(uint8_t *cmd)
ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len)
{
uint8_t adv_type;
const struct ble_hci_le_set_adv_params_cp *cmd = (const void *) cmdbuf;
struct ble_ll_adv_sm *advsm;
uint8_t adv_filter_policy;
uint8_t adv_chanmask;
uint8_t own_addr_type;
uint8_t peer_addr_type;
uint16_t adv_itvl_min;
uint16_t adv_itvl_max;
struct ble_ll_adv_sm *advsm;
uint16_t props;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[0];
if (advsm->adv_enabled) {
return BLE_ERR_CMD_DISALLOWED;
}
/* Make sure intervals are OK (along with advertising type */
adv_itvl_min = get_le16(cmd);
adv_itvl_max = get_le16(cmd + 2);
adv_type = cmd[4];
adv_itvl_min = le16toh(cmd->min_interval);
adv_itvl_max = le16toh(cmd->max_interval);
/*
* Get the filter policy now since we will ignore it if we are doing
* directed advertising
*/
adv_filter_policy = cmd[14];
adv_filter_policy = cmd->filter_policy;
switch (adv_type) {
switch (cmd->type) {
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
adv_filter_policy = BLE_HCI_ADV_FILT_NONE;
memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
/* Ignore min/max interval */
adv_itvl_min = 0;
@@ -1658,7 +1658,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
break;
case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
adv_filter_policy = BLE_HCI_ADV_FILT_NONE;
memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR ;
break;
@@ -1688,32 +1688,27 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
}
}
/* Check own and peer address type */
own_addr_type = cmd[5];
peer_addr_type = cmd[6];
if ((own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
(peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) {
if ((cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
(cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
/* Copy peer address */
memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
}
#else
/* If we dont support privacy some address types wont work */
if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
return BLE_ERR_UNSUPPORTED;
}
#endif
/* There are only three adv channels, so check for any outside the range */
adv_chanmask = cmd[13];
if (((adv_chanmask & 0xF8) != 0) || (adv_chanmask == 0)) {
if (((cmd->chan_map & 0xF8) != 0) || (cmd->chan_map == 0)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -1723,10 +1718,10 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
}
/* Fill out rest of advertising state machine */
advsm->own_addr_type = own_addr_type;
advsm->peer_addr_type = peer_addr_type;
advsm->own_addr_type = cmd->own_addr_type;
advsm->peer_addr_type = cmd->peer_addr_type;
advsm->adv_filter_policy = adv_filter_policy;
advsm->adv_chanmask = adv_chanmask;
advsm->adv_chanmask = cmd->chan_map;
advsm->adv_itvl_min = adv_itvl_min;
advsm->adv_itvl_max = adv_itvl_max;
advsm->props = props;
@@ -2641,8 +2636,11 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
int
ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen)
{
rspbuf[0] = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
*rsplen = 1;
struct ble_hci_le_rd_adv_chan_txpwr_rp *rsp = (void *) rspbuf;
rsp->power_level = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
*rsplen = sizeof(*rsp);
return BLE_ERR_SUCCESS;
}
@@ -2655,9 +2653,9 @@ ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen)
*
* @return int
*/
int
static int
ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, int duration,
uint8_t events)
uint8_t events)
{
int rc;
struct ble_ll_adv_sm *advsm;
@@ -2709,6 +2707,18 @@ ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, int duration,
return rc;
}
int
ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_adv_enable_cp *cmd = (const void *) cmdbuf;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_adv_set_enable(0, cmd->enable, -1, 0);
}
static void
ble_ll_adv_update_data_mbuf(struct os_mbuf **omp, bool new_data, uint16_t maxlen,
const void *data, uint16_t datalen)
@@ -2768,11 +2778,10 @@ instance_configured(struct ble_ll_adv_sm *advsm)
*
* @return int
*/
int
ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
uint8_t operation)
static int
ble_ll_adv_set_scan_rsp_data(const uint8_t *data, uint8_t datalen,
uint8_t instance, uint8_t operation)
{
uint8_t datalen;
struct ble_ll_adv_sm *advsm;
bool new_data;
@@ -2781,11 +2790,6 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
}
advsm = &g_ble_ll_adv_sm[instance];
datalen = cmd[0];
if (datalen > 251 || datalen > cmd_len - 1) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (!instance_configured(advsm)) {
return BLE_ERR_UNK_ADV_INDENT;
@@ -2858,16 +2862,14 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
}
ble_ll_adv_update_data_mbuf(&advsm->new_scan_rsp_data, new_data,
BLE_ADV_DATA_MAX_LEN,
cmd + 1, datalen);
BLE_ADV_DATA_MAX_LEN, data, datalen);
if (!advsm->new_scan_rsp_data) {
return BLE_ERR_MEM_CAPACITY;
}
ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA);
} else {
ble_ll_adv_update_data_mbuf(&advsm->scan_rsp_data, new_data,
BLE_SCAN_RSP_DATA_MAX_LEN,
cmd + 1, datalen);
BLE_SCAN_RSP_DATA_MAX_LEN, data, datalen);
if (!advsm->scan_rsp_data) {
return BLE_ERR_MEM_CAPACITY;
}
@@ -2881,6 +2883,18 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
return BLE_ERR_SUCCESS;
}
int
ble_ll_hci_set_scan_rsp_data(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_scan_rsp_data_cp *cmd = (const void *) cmdbuf;
if ((len != sizeof(*cmd)) || (cmd->scan_rsp_len > sizeof(cmd->scan_rsp))) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_adv_set_scan_rsp_data(cmd->scan_rsp, cmd->scan_rsp_len, 0,
BLE_HCI_LE_SET_DATA_OPER_COMPLETE);
}
/**
* Called by the LL HCI command parser when a set advertising
* data command has been sent from the host to the controller.
@@ -2890,11 +2904,10 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
*
* @return int 0: success; BLE_ERR_INV_HCI_CMD_PARMS otherwise.
*/
int
ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
static int
ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance,
uint8_t operation)
{
uint8_t datalen;
struct ble_ll_adv_sm *advsm;
bool new_data;
@@ -2903,11 +2916,6 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
}
advsm = &g_ble_ll_adv_sm[instance];
datalen = cmd[0];
if (datalen > 251 || datalen > cmd_len - 1) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (!instance_configured(advsm)) {
return BLE_ERR_UNK_ADV_INDENT;
@@ -3001,16 +3009,14 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
}
ble_ll_adv_update_data_mbuf(&advsm->new_adv_data, new_data,
BLE_ADV_DATA_MAX_LEN,
cmd + 1, datalen);
BLE_ADV_DATA_MAX_LEN, data, datalen);
if (!advsm->new_adv_data) {
return BLE_ERR_MEM_CAPACITY;
}
ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA);
} else {
ble_ll_adv_update_data_mbuf(&advsm->adv_data, new_data,
BLE_ADV_DATA_MAX_LEN,
cmd + 1, datalen);
BLE_ADV_DATA_MAX_LEN, data, datalen);
if (!advsm->adv_data) {
return BLE_ERR_MEM_CAPACITY;
}
@@ -3024,6 +3030,19 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
return BLE_ERR_SUCCESS;
}
int
ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_adv_data_cp *cmd = (const void *) cmdbuf;
if ((len != sizeof(*cmd)) || (cmd->adv_data_len > sizeof(cmd->adv_data))) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_adv_set_adv_data(cmd->adv_data, cmd->adv_data_len, 0,
BLE_HCI_LE_SET_DATA_OPER_COMPLETE);
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
static bool
pri_phy_valid(uint8_t phy)
@@ -3057,35 +3076,33 @@ sec_phy_valid(uint8_t phy)
}
int
ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
int rc;
uint8_t adv_filter_policy;
uint8_t adv_chanmask;
uint8_t own_addr_type;
uint8_t peer_addr_type;
const struct ble_hci_le_set_ext_adv_params_cp *cmd = (const void *) cmdbuf;
struct ble_hci_le_set_ext_adv_params_rp *rsp = (void *) rspbuf;
struct ble_ll_adv_sm *advsm;
uint32_t adv_itvl_min;
uint32_t adv_itvl_max;
uint16_t props;
struct ble_ll_adv_sm *advsm;
uint8_t pri_phy;
uint8_t sec_phy;
uint8_t sid;
uint8_t scan_req_notif;
int8_t tx_power = 0;
int rc;
if (cmdbuf[0] >= BLE_ADV_INSTANCES) {
if (len != sizeof(*cmd )) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (cmd->adv_handle >= BLE_ADV_INSTANCES) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
advsm = &g_ble_ll_adv_sm[cmdbuf[0]];
advsm = &g_ble_ll_adv_sm[cmd->adv_handle];
if (advsm->adv_enabled) {
rc = BLE_ERR_CMD_DISALLOWED;
goto done;
}
props = get_le16(&cmdbuf[1]);
props = le16toh(cmd->props);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
/* For now just disallow to reconfigure instance that has periodic
@@ -3111,8 +3128,10 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
}
#endif
adv_itvl_min = cmdbuf[5] << 16 | cmdbuf[4] << 8 | cmdbuf[3];
adv_itvl_max = cmdbuf[8] << 16 | cmdbuf[7] << 8 | cmdbuf[6];
adv_itvl_min = cmd->pri_itvl_min[2] << 16 | cmd->pri_itvl_min[1] << 8 |
cmd->pri_itvl_min[0];
adv_itvl_max = cmd->pri_itvl_max[2] << 16 | cmd->pri_itvl_max[1] << 8 |
cmd->pri_itvl_max[0];
if (props & ~BLE_HCI_LE_SET_EXT_ADV_PROP_MASK) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
@@ -3188,58 +3207,48 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
}
/* There are only three adv channels, so check for any outside the range */
adv_chanmask = cmdbuf[9];
if (((adv_chanmask & 0xF8) != 0) || (adv_chanmask == 0)) {
if (((cmd->pri_chan_map & 0xF8) != 0) || (cmd->pri_chan_map == 0)) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
/* Check own and peer address type */
own_addr_type = cmdbuf[10];
peer_addr_type = cmdbuf[11];
if ((own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
(peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) {
if ((cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
(cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/* If we dont support privacy some address types wont work */
if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
rc = BLE_ERR_UNSUPPORTED;
goto done;
}
#endif
adv_filter_policy = cmdbuf[18];
/* Check filter policy (valid only for undirected */
if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) &&
adv_filter_policy > BLE_HCI_ADV_FILT_MAX) {
cmd->filter_policy > BLE_HCI_ADV_FILT_MAX) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
pri_phy = cmdbuf[20];
if (!pri_phy_valid(pri_phy)) {
if (!pri_phy_valid(cmd->pri_phy)) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
sec_phy = cmdbuf[22];
if (!sec_phy_valid(sec_phy)) {
if (!sec_phy_valid(cmd->sec_phy)) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
sid = cmdbuf[23];
if (sid > 0x0f) {
if (cmd->sid > 0x0f) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
scan_req_notif = cmdbuf[24];
if (scan_req_notif > 0x01) {
if (cmd->scan_req_notif > 0x01) {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
goto done;
}
@@ -3250,12 +3259,11 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
memcpy(advsm->peer_addr, &cmdbuf[12], BLE_DEV_ADDR_LEN);
}
tx_power = (int8_t) cmdbuf[19];
if (tx_power == 127) {
if (cmd->tx_power == 127) {
/* no preference */
advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
} else {
advsm->adv_txpwr = ble_phy_txpower_round(tx_power);
advsm->adv_txpwr = ble_phy_txpower_round(cmd->tx_power);
}
if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
@@ -3263,18 +3271,18 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
/* For anonymous don't care about address type */
advsm->own_addr_type = 0;
} else {
advsm->own_addr_type = own_addr_type;
advsm->own_addr_type = cmd->own_addr_type;
}
advsm->peer_addr_type = peer_addr_type;
advsm->adv_filter_policy = adv_filter_policy;
advsm->adv_chanmask = adv_chanmask;
advsm->peer_addr_type = cmd->peer_addr_type;
advsm->adv_filter_policy = cmd->filter_policy;
advsm->adv_chanmask = cmd->pri_chan_map;
advsm->adv_itvl_min = adv_itvl_min;
advsm->adv_itvl_max = adv_itvl_max;
advsm->pri_phy = pri_phy;
advsm->sec_phy = sec_phy;
advsm->pri_phy = cmd->pri_phy;
advsm->sec_phy = cmd->sec_phy;
/* Update SID only */
advsm->adi = (advsm->adi & 0x0fff) | ((sid << 12));
advsm->adi = (advsm->adi & 0x0fff) | ((cmd->sid << 12));
advsm->props = props;
@@ -3287,7 +3295,7 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
advsm->aux_data = &advsm->adv_data;
}
if (scan_req_notif) {
if (cmd->scan_req_notif) {
ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF);
} else {
ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF);
@@ -3297,46 +3305,52 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
done:
/* Update TX power */
rspbuf[0] = ble_phy_txpower_round(tx_power);
*rsplen = 1;
rsp->tx_power = ble_phy_txpower_round(cmd->tx_power);
*rsplen = sizeof(*rsp);
return rc;
}
int
ble_ll_adv_ext_set_adv_data(uint8_t *cmdbuf, uint8_t cmdlen)
ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen)
{
/* check if length is correct */
if (cmdlen < 4) {
const struct ble_hci_le_set_ext_adv_data_cp *cmd = (const void *) cmdbuf;
if (cmdlen < sizeof(*cmd )) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (cmd->adv_data_len > BLE_HCI_MAX_EXT_ADV_DATA_LEN ||
cmd->adv_data_len > cmdlen - sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* TODO fragment preference ignored for now */
return ble_ll_adv_set_adv_data(cmdbuf + 3, cmdlen - 3, cmdbuf[0],
cmdbuf[1]);
return ble_ll_adv_set_adv_data(cmd->adv_data, cmd->adv_data_len,
cmd->adv_handle, cmd->operation);
}
int
ble_ll_adv_ext_set_scan_rsp(uint8_t *cmdbuf, uint8_t cmdlen)
ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen)
{
/* check if length is correct */
if (cmdlen < 4) {
const struct ble_hci_le_set_ext_scan_rsp_data_cp *cmd = (const void *) cmdbuf;
if (cmdlen < sizeof(*cmd )) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (cmd->scan_rsp_len > BLE_HCI_MAX_EXT_ADV_DATA_LEN ||
cmd->scan_rsp_len > cmdlen - sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* TODO fragment preference ignored for now */
return ble_ll_adv_set_scan_rsp_data(cmdbuf + 3, cmdlen - 3, cmdbuf[0],
cmdbuf[1]);
return ble_ll_adv_set_scan_rsp_data(cmd->scan_rsp, cmd->scan_rsp_len,
cmd->adv_handle, cmd->operation);
}
struct ext_adv_set {
uint8_t handle;
uint16_t duration;
uint8_t events;
} __attribute__((packed));
/**
* HCI LE extended advertising enable command
*
@@ -3346,33 +3360,27 @@ struct ext_adv_set {
* @return int BLE error code
*/
int
ble_ll_adv_ext_set_enable(uint8_t *cmd, uint8_t len)
ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_ext_adv_enable_cp *cmd = (const void *) cmdbuf;
struct ble_ll_adv_sm *advsm;
struct ext_adv_set* set;
uint8_t enable;
uint8_t sets;
int i, j, rc;
if (len < 2) {
if (len < sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
enable = cmd[0];
sets = cmd[1];
cmd += 2;
/* check if length is correct */
if (len != 2 + (sets * sizeof (*set))) {
if (len != 2 + (cmd->num_sets * sizeof(cmd->sets[0]))) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (sets > BLE_ADV_INSTANCES) {
if (cmd->num_sets > BLE_ADV_INSTANCES) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (sets == 0) {
if (enable) {
if (cmd->sets == 0) {
if (cmd->enable) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -3384,53 +3392,49 @@ ble_ll_adv_ext_set_enable(uint8_t *cmd, uint8_t len)
return BLE_ERR_SUCCESS;
}
set = (void *) cmd;
/* validate instances */
for (i = 0; i < sets; i++) {
if (set->handle >= BLE_ADV_INSTANCES) {
for (i = 0; i < cmd->num_sets; i++) {
if (cmd->sets[i].adv_handle >= BLE_ADV_INSTANCES) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* validate duplicated sets */
for (j = 1; j < sets - i; j++) {
if (set->handle == set[j].handle) {
for (j = 1; j < cmd->num_sets - i; j++) {
if (cmd->sets[i].adv_handle == cmd->sets[j].adv_handle) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
}
advsm = &g_ble_ll_adv_sm[set->handle];
advsm = &g_ble_ll_adv_sm[cmd->sets[i].adv_handle];
if (!instance_configured(advsm)) {
return BLE_ERR_UNK_ADV_INDENT;
}
if (enable) {
if (cmd->enable) {
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
if (set->duration == 0 || le16toh(set->duration) > 128) {
if (cmd->sets[i].duration == 0 ||
le16toh(cmd->sets[i].duration) > 128) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
}
}
set++;
}
set = (void *) cmd;
for (i = 0; i < sets; i++) {
rc = ble_ll_adv_set_enable(set->handle, enable, le16toh(set->duration),
set->events);
for (i = 0; i < cmd->num_sets; i++) {
rc = ble_ll_adv_set_enable(cmd->sets[i].adv_handle, cmd->enable,
le16toh(cmd->sets[i].duration),
cmd->sets[i].max_events);
if (rc) {
return rc;
}
set++;
}
return BLE_ERR_SUCCESS;
}
int
ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance)
ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance)
{
struct ble_ll_adv_sm *advsm;
@@ -3453,27 +3457,42 @@ ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance)
return BLE_ERR_SUCCESS;
}
int
ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_adv_set_rnd_addr_cp *cmd = (const void *) cmdbuf;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_adv_set_random_addr(cmd->addr, cmd->adv_handle);
}
/**
* HCI LE extended advertising remove command
*
* @param instance Advertising instance to be removed
*
* @return int BLE error code
*/
int
ble_ll_adv_remove(uint8_t instance)
ble_ll_adv_remove(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_remove_adv_set_cp *cmd = (const void *) cmdbuf;
struct ble_ll_adv_sm *advsm;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* TODO
* Should we allow any value for instance ID?
*/
if (instance >= BLE_ADV_INSTANCES) {
if (cmd->adv_handle >= BLE_ADV_INSTANCES) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[instance];
advsm = &g_ble_ll_adv_sm[cmd->adv_handle];
if (!instance_configured(advsm)) {
return BLE_ERR_UNK_ADV_INDENT;
@@ -3533,24 +3552,27 @@ ble_ll_adv_clear_all(void)
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
int
ble_ll_adv_periodic_set_param(uint8_t *cmdbuf)
ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_periodic_adv_params_cp *cmd = (const void *) cmdbuf;
struct ble_ll_adv_sm *advsm;
uint16_t adv_itvl_min;
uint16_t adv_itvl_max;
uint8_t instance;
uint16_t props;
instance = cmdbuf[0];
adv_itvl_min = get_le16(cmdbuf + 1);
adv_itvl_max = get_le16(cmdbuf + 3);
props = get_le16(cmdbuf + 5);
if (instance >= BLE_ADV_INSTANCES) {
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[instance];
adv_itvl_min = le16toh(cmd->min_itvl);
adv_itvl_max = le16toh(cmd->max_itvl);
props = le16toh(cmd->props);
if (cmd->adv_handle >= BLE_ADV_INSTANCES) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[cmd->adv_handle];
if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED)) {
return BLE_ERR_UNK_ADV_INDENT;
}
@@ -3598,27 +3620,26 @@ ble_ll_adv_periodic_set_param(uint8_t *cmdbuf)
}
int
ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen)
ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_periodic_adv_data_cp *cmd = (const void *) cmdbuf;
struct ble_ll_adv_sm *advsm;
bool new_data = false;
uint8_t instance;
uint8_t operation;
uint8_t adv_data_len;
if (cmdlen < 3) {
if (len < sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
instance = cmdbuf[0];
operation = cmdbuf[1];
adv_data_len = cmdbuf[2];
if (instance >= BLE_ADV_INSTANCES) {
if (cmd->adv_data_len > BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN ||
cmd->adv_data_len != len - sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[instance];
if (cmd->adv_handle >= BLE_ADV_INSTANCES) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[cmd->adv_handle];
if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED)) {
return BLE_ERR_UNK_ADV_INDENT;
}
@@ -3627,18 +3648,14 @@ ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen)
return BLE_ERR_CMD_DISALLOWED;
}
if ((adv_data_len > 252) || (adv_data_len != cmdlen - 3)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
switch (operation) {
switch (cmd->operation) {
case BLE_HCI_LE_SET_DATA_OPER_LAST:
case BLE_HCI_LE_SET_DATA_OPER_INT:
if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (!advsm->periodic_adv_data || !adv_data_len) {
if (!advsm->periodic_adv_data || !cmd->adv_data_len) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -3651,7 +3668,7 @@ ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen)
return BLE_ERR_CMD_DISALLOWED;
}
if (!adv_data_len) {
if (!cmd->adv_data_len) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
new_data = true;
@@ -3668,7 +3685,7 @@ ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen)
ble_ll_adv_update_data_mbuf(&advsm->periodic_new_data, true,
BLE_ADV_DATA_MAX_LEN,
cmdbuf + 3, adv_data_len);
cmd->adv_data, cmd->adv_data_len);
if (!advsm->periodic_new_data) {
return BLE_ERR_MEM_CAPACITY;
}
@@ -3676,15 +3693,15 @@ ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen)
ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA);
} else {
ble_ll_adv_update_data_mbuf(&advsm->periodic_adv_data, new_data,
BLE_ADV_DATA_MAX_LEN, cmdbuf + 3,
adv_data_len);
BLE_ADV_DATA_MAX_LEN, cmd->adv_data,
cmd->adv_data_len);
if (!advsm->periodic_adv_data) {
return BLE_ERR_MEM_CAPACITY;
}
}
/* set/clear incomplete data flag only on success */
switch (operation) {
switch (cmd->operation) {
case BLE_HCI_LE_SET_DATA_OPER_LAST:
case BLE_HCI_LE_SET_DATA_OPER_COMPLETE:
ble_ll_adv_flags_clear(advsm,
@@ -3702,25 +3719,25 @@ ble_ll_adv_periodic_set_data(uint8_t *cmdbuf, uint8_t cmdlen)
}
int
ble_ll_adv_periodic_enable(uint8_t *cmdbuf)
ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_periodic_adv_enable_cp *cmd = (const void *)cmdbuf;
struct ble_ll_adv_sm *advsm;
uint8_t instance;
uint8_t enable;
enable = cmdbuf[0];
instance = cmdbuf[1];
if (instance >= BLE_ADV_INSTANCES) {
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[instance];
if (cmd->adv_handle >= BLE_ADV_INSTANCES) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
advsm = &g_ble_ll_adv_sm[cmd->adv_handle];
if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED)) {
return BLE_ERR_UNK_ADV_INDENT;
}
if (enable) {
if (cmd->enable) {
if (advsm->props & BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE) {
return BLE_ERR_CMD_DISALLOWED;
}
@@ -3738,7 +3755,7 @@ ble_ll_adv_periodic_enable(uint8_t *cmdbuf)
ble_ll_adv_sm_stop_periodic(advsm);
}
advsm->periodic_adv_enabled = enable;
advsm->periodic_adv_enabled = cmd->enable;
return BLE_ERR_SUCCESS;
}
+1 -1
View File
@@ -3911,7 +3911,7 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length)
* @param chanmap
*/
void
ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap)
ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap)
{
struct ble_ll_conn_sm *connsm;
struct ble_ll_conn_global_params *conn_params;
File diff suppressed because it is too large Load Diff
+46 -28
View File
@@ -88,10 +88,25 @@ extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
/* Generic interface */
struct ble_ll_len_req;
struct hci_create_conn;
struct ble_mbuf_hdr;
struct ble_ll_adv_sm;
struct hci_create_conn
{
uint16_t scan_itvl;
uint16_t scan_window;
uint8_t filter_policy;
uint8_t peer_addr_type;
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
uint8_t own_addr_type;
uint16_t conn_itvl_min;
uint16_t conn_itvl_max;
uint16_t conn_latency;
uint16_t supervision_timeout;
uint16_t min_ce_len;
uint16_t max_ce_len;
};
void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm);
void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
@@ -118,7 +133,7 @@ int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat,
/* Link Layer interface */
void ble_ll_conn_module_init(void);
void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap);
void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap);
void ble_ll_conn_module_reset(void);
void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa);
@@ -140,13 +155,15 @@ bool ble_ll_conn_init_pending_aux_conn_rsp(void);
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
uint8_t reason);
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
int ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf);
int ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t *cmdbuf);
int ble_ll_conn_create(uint8_t *cmdbuf);
int ble_ll_conn_hci_update(uint8_t *cmdbuf);
int ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf);
int ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int negative_reply,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb);
void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm);
void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
@@ -154,22 +171,22 @@ void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
uint16_t latency, uint16_t spvn_tmo);
int ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf);
int ble_ll_conn_hci_read_rem_features_complete(void);
int ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_conn_hci_set_data_len(uint8_t *cmdbuf, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_conn_hci_le_start_encrypt(uint8_t *cmdbuf);
int ble_ll_conn_hci_le_ltk_reply(uint8_t *cmdbuf, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_conn_hci_le_ltk_neg_reply(uint8_t *cmdbuf, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp,
uint8_t *rsplen);
int ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp,
uint8_t *rsplen);
int ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf,
uint8_t *rsplen);
int ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
#else
@@ -179,11 +196,12 @@ void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
int ble_ll_conn_hci_le_rd_phy(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen);
int ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf);
int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rsp, uint8_t *rsplen);
int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int ble_ll_ext_conn_create(uint8_t *cmdbuf, uint8_t cmdlen);
int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen);
#endif
#ifdef __cplusplus
}
+118 -62
View File
@@ -470,65 +470,41 @@ ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)
OS_EXIT_CRITICAL(sr);
}
int
ble_ll_dtm_tx_test(uint8_t *cmdbuf, uint8_t cmdlen, bool enhanced)
static int
ble_ll_dtm_tx_test(uint8_t tx_chan, uint8_t len, uint8_t packet_payload,
uint8_t hci_phy, uint16_t interval, uint16_t pkt_count)
{
uint8_t cmdlen_valid;
uint8_t tx_chan = cmdbuf[0];
uint8_t len = cmdbuf[1];
uint8_t packet_payload = cmdbuf[2];
uint8_t phy_mode = BLE_PHY_MODE_1M;
uint16_t interval = 0;
uint16_t pkt_count = 0;
uint8_t phy_mode;
if (g_ble_ll_dtm_ctx.active) {
return BLE_ERR_CTLR_BUSY;
}
cmdlen_valid = enhanced ? BLE_HCI_LE_ENH_TX_TEST_LEN : BLE_HCI_TX_TEST_LEN;
#if !MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
if (cmdlen != cmdlen_valid) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
#endif
if (enhanced) {
switch (cmdbuf[3]) {
case BLE_HCI_LE_PHY_1M:
phy_mode = BLE_PHY_MODE_1M;
break;
switch (hci_phy) {
case BLE_HCI_LE_PHY_1M:
phy_mode = BLE_PHY_MODE_1M;
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
case BLE_HCI_LE_PHY_2M:
phy_mode = BLE_PHY_MODE_2M;
break;
case BLE_HCI_LE_PHY_2M:
phy_mode = BLE_PHY_MODE_2M;
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
case BLE_HCI_LE_PHY_CODED_S8:
phy_mode = BLE_PHY_MODE_CODED_125KBPS;
break;
case BLE_HCI_LE_PHY_CODED_S2:
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
break;
case BLE_HCI_LE_PHY_CODED_S8:
phy_mode = BLE_PHY_MODE_CODED_125KBPS;
break;
case BLE_HCI_LE_PHY_CODED_S2:
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
break;
#endif
default:
return BLE_ERR_INV_HCI_CMD_PARMS;
}
default:
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (tx_chan > 0x27 || packet_payload > 0x07) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
if (cmdlen == cmdlen_valid + 4) {
interval = get_le16(cmdbuf + cmdlen_valid );
pkt_count = get_le16(cmdbuf + cmdlen_valid + 2);
} else if (cmdlen != cmdlen_valid) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
#endif
if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode,
interval, pkt_count)) {
return BLE_ERR_UNSPECIFIED;
@@ -537,35 +513,91 @@ ble_ll_dtm_tx_test(uint8_t *cmdbuf, uint8_t cmdlen, bool enhanced)
return BLE_ERR_SUCCESS;
}
int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced)
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
static int
ble_ll_hci_dtm_tx_test_ext(const uint8_t *cmdbuf)
{
uint8_t rx_chan = cmdbuf[0];
uint8_t phy_mode = BLE_PHY_MODE_1M;
const struct ble_hci_le_tx_test_ext_cp *cmd = (const void *) cmdbuf;
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
BLE_HCI_LE_PHY_1M, le16toh(cmd->interval),
le16toh(cmd->pkt_count));
}
static int
ble_ll_hci_dtm_tx_test_v2_ext(const uint8_t *cmdbuf)
{
const struct ble_hci_le_tx_test_v2_ext_cp *cmd = (const void *) cmdbuf;
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
cmd->phy, le16toh(cmd->interval),
le16toh(cmd->pkt_count));
}
#endif
int
ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_tx_test_cp *cmd = (const void *) cmdbuf;
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
if (len == sizeof(struct ble_hci_le_tx_test_ext_cp)) {
return ble_ll_hci_dtm_tx_test_ext(cmdbuf);
}
#endif
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
BLE_HCI_LE_PHY_1M, 0, 0);
}
int
ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_tx_test_v2_cp *cmd = (const void *) cmdbuf;
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
if (len == sizeof(struct ble_hci_le_tx_test_v2_ext_cp)) {
return ble_ll_hci_dtm_tx_test_v2_ext(cmdbuf);
}
#endif
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
cmd->phy, 0, 0);
}
static int
ble_ll_dtm_rx_test(uint8_t rx_chan, uint8_t hci_phy)
{
uint8_t phy_mode;
if (g_ble_ll_dtm_ctx.active) {
return BLE_ERR_CTLR_BUSY;
}
/*XXX What to do with modulation cmdbuf[2]? */
if (enhanced) {
switch (cmdbuf[1]) {
case BLE_HCI_LE_PHY_1M:
phy_mode = BLE_PHY_MODE_1M;
break;
switch (hci_phy) {
case BLE_HCI_LE_PHY_1M:
phy_mode = BLE_PHY_MODE_1M;
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
case BLE_HCI_LE_PHY_2M:
phy_mode = BLE_PHY_MODE_2M;
break;
case BLE_HCI_LE_PHY_2M:
phy_mode = BLE_PHY_MODE_2M;
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
case BLE_HCI_LE_PHY_CODED:
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
break;
case BLE_HCI_LE_PHY_CODED:
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
break;
#endif
default:
return BLE_ERR_INV_HCI_CMD_PARMS;
}
default:
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (rx_chan > 0x27) {
@@ -579,6 +611,30 @@ int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced)
return BLE_ERR_SUCCESS;
}
int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_rx_test_cp *cmd = (const void *) cmdbuf;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_ll_dtm_rx_test(cmd->rx_chan, BLE_HCI_LE_PHY_1M);
}
int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_rx_test_v2_cp *cmd = (const void *) cmdbuf;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* TODO ignoring modulation index */
return ble_ll_dtm_rx_test(cmd->rx_chan, cmd->phy);
}
int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen)
{
put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets);
+6 -2
View File
@@ -24,8 +24,12 @@
#include <stdbool.h>
#include "nimble/ble.h"
int ble_ll_dtm_tx_test(uint8_t *cmdbuf, uint8_t cmdlen, bool enhanced);
int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced);
int ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen);
int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa);
File diff suppressed because it is too large Load Diff
+268 -169
View File
@@ -40,20 +40,25 @@ extern void bletest_ltk_req_reply(uint16_t handle);
void
ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_data_len_chg *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DATA_LEN_CHG)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_DATA_LEN_CHG_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_DATA_LEN_CHG;
put_le16(evbuf + 3, connsm->conn_handle);
put_le16(evbuf + 5, connsm->eff_max_tx_octets);
put_le16(evbuf + 7, connsm->eff_max_tx_time);
put_le16(evbuf + 9, connsm->eff_max_rx_octets);
put_le16(evbuf + 11, connsm->eff_max_rx_time);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_DATA_LEN_CHG;
ev->conn_handle = htole16(connsm->conn_handle);
ev->max_tx_octets = htole16(connsm->eff_max_tx_octets);
ev->max_tx_time = htole16(connsm->eff_max_tx_time);
ev->max_rx_octets = htole16(connsm->eff_max_rx_octets);
ev->max_rx_time = htole16(connsm->eff_max_rx_time);
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -67,20 +72,24 @@ void
ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm,
struct ble_ll_conn_params *cp)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_rem_conn_param_req *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_REM_CONN_PARM_REQ_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
put_le16(evbuf + 3, connsm->conn_handle);
put_le16(evbuf + 5, cp->interval_min);
put_le16(evbuf + 7, cp->interval_max);
put_le16(evbuf + 9, cp->latency);
put_le16(evbuf + 11, cp->timeout);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
ev->conn_handle = htole16(connsm->conn_handle);
ev->min_interval = htole16(cp->interval_min);
ev->max_interval = htole16(cp->interval_max);
ev->latency = htole16(cp->latency);
ev->timeout = htole16(cp->timeout);
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -94,20 +103,24 @@ ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm,
void
ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_conn_upd_complete *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_CONN_UPD_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
evbuf[3] = status;
put_le16(evbuf + 4, connsm->conn_handle);
put_le16(evbuf + 6, connsm->conn_itvl);
put_le16(evbuf + 8, connsm->slave_latency);
put_le16(evbuf + 10, connsm->supervision_tmo);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
ev->status = status;
ev->conn_handle = htole16(connsm->conn_handle);
ev->conn_itvl = htole16(connsm->conn_itvl);
ev->conn_latency = htole16(connsm->slave_latency);
ev->supervision_timeout = htole16(connsm->supervision_tmo);
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -116,36 +129,43 @@ ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status)
void
ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status)
{
uint8_t evcode;
uint8_t *evbuf;
uint8_t evlen;
struct ble_hci_ev_enc_key_refresh *ev_key_refresh;
struct ble_hci_ev_enrypt_chg *ev_enc_chf;
struct ble_hci_ev *hci_ev;
if (CONN_F_ENC_CHANGE_SENT(connsm) == 0) {
evcode = BLE_HCI_EVCODE_ENCRYPT_CHG;
evlen = BLE_HCI_EVENT_ENCRYPT_CHG_LEN;
} else {
evcode = BLE_HCI_EVCODE_ENC_KEY_REFRESH;
evlen = BLE_HCI_EVENT_ENC_KEY_REFRESH_LEN;
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENCRYPT_CHG)) {
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_ENCRYPT_CHG;
hci_ev->length = sizeof(*ev_enc_chf);
ev_enc_chf = (void *) hci_ev->data;
ev_enc_chf->status = status;
ev_enc_chf->connection_handle = htole16(connsm->conn_handle);
ev_enc_chf->enabled = (status == BLE_ERR_SUCCESS) ? 0x01 : 0x00;
ble_ll_hci_event_send(hci_ev);
}
}
CONN_F_ENC_CHANGE_SENT(connsm) = 1;
return;
}
if (ble_ll_hci_is_event_enabled(evcode)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = evcode;
evbuf[1] = evlen;
evbuf[2] = status;
put_le16(evbuf + 3, connsm->conn_handle);
if (evcode == BLE_HCI_EVCODE_ENCRYPT_CHG) {
if (status == BLE_ERR_SUCCESS) {
evbuf[5] = 0x01;
} else {
evbuf[5] = 0;
}
}
ble_ll_hci_event_send(evbuf);
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENC_KEY_REFRESH)) {
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_ENC_KEY_REFRESH;
hci_ev->length = sizeof(*ev_key_refresh);
ev_key_refresh = (void *) hci_ev->data;
ev_key_refresh->status = status;
ev_key_refresh->conn_handle = htole16(connsm->conn_handle);
ble_ll_hci_event_send(hci_ev);
}
}
CONN_F_ENC_CHANGE_SENT(connsm) = 1;
}
/**
@@ -156,19 +176,23 @@ ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status)
int
ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm)
{
struct ble_hci_ev_le_subev_lt_key_req *ev;
struct ble_hci_ev *hci_ev;
int rc;
uint8_t *evbuf;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_LT_KEY_REQ)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_LT_KEY_REQ_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_LT_KEY_REQ;
put_le16(evbuf + 3, connsm->conn_handle);
put_le64(evbuf + 5, connsm->enc_data.host_rand_num);
put_le16(evbuf + 13, connsm->enc_data.enc_div);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ;
ev->conn_handle = htole16(connsm->conn_handle);
ev->rand = htole64(connsm->enc_data.host_rand_num);
ev->div = htole16(connsm->enc_data.enc_div);
ble_ll_hci_event_send(hci_ev);
}
rc = 0;
} else {
@@ -187,20 +211,23 @@ ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm)
void
ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, uint8_t status)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_rd_rem_used_feat *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_RD_REM_USED_FEAT_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
evbuf[3] = status;
put_le16(evbuf + 4, connsm->conn_handle);
memset(evbuf + 6, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN);
evbuf[6] = connsm->conn_features;
memcpy(evbuf + 7, connsm->remote_features, 7);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
ev->status = status;
ev->conn_handle = htole16(connsm->conn_handle);
ev->features[0] = connsm->conn_features;
memcpy(ev->features + 1, connsm->remote_features, 7);
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -208,19 +235,23 @@ ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, uint8_t status)
void
ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status)
{
uint8_t *evbuf;
struct ble_hci_ev_rd_rem_ver_info_cmp *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP;
evbuf[1] = BLE_HCI_EVENT_RD_RM_VER_LEN;
evbuf[2] = status;
put_le16(evbuf + 3, connsm->conn_handle);
evbuf[5] = connsm->vers_nr;
put_le16(evbuf + 6, connsm->comp_id);
put_le16(evbuf + 8, connsm->sub_vers_nr);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->status = status;
ev->conn_handle = htole16(connsm->conn_handle);
ev->version = connsm->vers_nr;
ev->manufacturer = htole16(connsm->comp_id);
ev->subversion = htole16(connsm->sub_vers_nr);
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -235,17 +266,21 @@ ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status)
int
ble_ll_hci_ev_hw_err(uint8_t hw_err)
{
struct ble_hci_ev_hw_error *ev;
struct ble_hci_ev *hci_ev;
int rc;
uint8_t *evbuf;
rc = 0;
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_HW_ERROR)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_HW_ERROR;
evbuf[1] = BLE_HCI_EVENT_HW_ERROR_LEN;
evbuf[2] = hw_err;
ble_ll_hci_event_send(evbuf);
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_HW_ERROR;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->hw_code = hw_err;
ble_ll_hci_event_send(hci_ev);
} else {
rc = -1;
}
@@ -256,15 +291,19 @@ ble_ll_hci_ev_hw_err(uint8_t hw_err)
void
ble_ll_hci_ev_databuf_overflow(void)
{
uint8_t *evbuf;
struct ble_hci_ev_data_buf_overflow *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DATA_BUF_OVERFLOW)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_DATA_BUF_OVERFLOW;
evbuf[1] = BLE_HCI_EVENT_DATABUF_OVERFLOW_LEN;
evbuf[2] = BLE_HCI_EVENT_ACL_BUF_OVERFLOW;
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_DATA_BUF_OVERFLOW;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->link_type = BLE_HCI_EVENT_ACL_BUF_OVERFLOW;
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -278,17 +317,21 @@ ble_ll_hci_ev_databuf_overflow(void)
void
ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_chan_sel_alg *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CHAN_SEL_ALG)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG;
put_le16(evbuf + 3, connsm->conn_handle);
evbuf[5] = connsm->csmflags.cfbit.csa2_supp ? 0x01 : 0x00;
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG;
ev->conn_handle = htole16(connsm->conn_handle);
ev->csa = connsm->csmflags.cfbit.csa2_supp ? 0x01 : 0x00;
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -303,18 +346,22 @@ void
ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer,
uint8_t peer_addr_type)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_scan_req_rcvd *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD;
evbuf[3] = adv_handle;
evbuf[4] = peer_addr_type;
memcpy(&evbuf[5], peer, BLE_DEV_ADDR_LEN);
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD;
ev->adv_handle = adv_handle;
ev->peer_addr_type = peer_addr_type;
memcpy(ev->peer_addr, peer, BLE_DEV_ADDR_LEN);
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -328,15 +375,19 @@ ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer,
void
ble_ll_hci_ev_send_scan_timeout(void)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_scan_timeout *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_TIMEOUT)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_SUBEV_SCAN_TIMEOUT_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_SCAN_TIMEOUT;
ble_ll_hci_event_send(evbuf);
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_TIMEOUT;
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -351,19 +402,23 @@ void
ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle,
uint16_t conn_handle, uint8_t events)
{
uint8_t *evbuf;
struct ble_hci_ev_le_subev_adv_set_terminated *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED;
evbuf[3] = status;
evbuf[4] = adv_handle;
put_le16(evbuf + 5, conn_handle);
evbuf[7] = events;
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED;
ev->status = status;
ev->adv_handle = adv_handle;
ev->conn_handle = htole16(conn_handle);
ev->num_events = events;
ble_ll_hci_event_send(hci_ev);
}
}
}
@@ -379,21 +434,25 @@ ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle,
int
ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
{
struct ble_hci_ev_le_subev_phy_update_complete *ev;
struct ble_hci_ev *hci_ev;
int rc;
uint8_t *evbuf;
rc = 0;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_PHY_UPD_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE;
evbuf[3] = status;
put_le16(evbuf + 4, connsm->conn_handle);
evbuf[6] = connsm->phy_data.cur_tx_phy;
evbuf[7] = connsm->phy_data.cur_rx_phy;
ble_ll_hci_event_send(evbuf);
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE;
ev->status = status;
ev->conn_handle = htole16(connsm->conn_handle);
ev->tx_phy = connsm->phy_data.cur_tx_phy;
ev->rx_phy = connsm->phy_data.cur_rx_phy;
ble_ll_hci_event_send(hci_ev);
} else {
rc = BLE_ERR_MEM_CAPACITY;
}
@@ -403,21 +462,61 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
#endif
void
ble_ll_hci_ev_send_vendor_err(char *file, uint32_t line)
ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line)
{
uint8_t *evbuf;
uint8_t file_len = strlen(file);
struct ble_hci_ev_vendor_debug *ev;
struct ble_hci_ev *hci_ev;
unsigned int str_len;
bool skip = true;
uint8_t digit;
int max_len;
int i;
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (!evbuf) {
return;
/* 6 is for line number ":00000" , we assume files have no more than 64k of
* lines
*/
max_len = BLE_HCI_MAX_DATA_LEN - sizeof(*ev) - 6;
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
/* Debug id for future use */
ev->id = 0x00;
/* snprintf would be nicer but this is heavy on flash
* len = snprintf((char *) ev->data, max_len, "%s:%u", file, line);
* if (len < 0) {
* len = 0;
* } else if (len > max_len) {
* len = max_len;
* }
*
* hci_ev->length += len;
*/
str_len = strlen(file);
if (str_len > max_len) {
str_len = max_len;
}
memcpy(ev->data, file, str_len);
ev->data[str_len++] = ':';
for (i = 100000; i >= 10; i /= 10) {
digit = (line % i) / (i/10);
if (!digit && skip) {
continue;
}
skip = false;
ev->data[str_len++] = '0' + digit;
}
hci_ev->length += str_len;
ble_ll_hci_event_send(hci_ev);
}
evbuf[0] = BLE_HCI_EVCODE_VENDOR_DEBUG;
evbuf[1] = file_len + sizeof(line) + 1;
/* Debug id for future use */
evbuf[2] = 0x00;
memcpy(&evbuf[3], file, file_len);
put_le32(&evbuf[3] + file_len, line);
ble_ll_hci_event_send(evbuf);
}
+101 -82
View File
@@ -200,8 +200,11 @@ ble_ll_resolv_list_clr(void)
int
ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen)
{
rspbuf[0] = g_ble_ll_resolv_data.rl_size;
*rsplen = 1;
struct ble_hci_le_rd_resolv_list_size_rp *rsp = (void *) rspbuf;
rsp->size = g_ble_ll_resolv_data.rl_size;
*rsplen = sizeof(*rsp);
return BLE_ERR_SUCCESS;
}
@@ -216,7 +219,7 @@ ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen)
* element plus 1).
*/
static int
ble_ll_is_on_resolv_list(uint8_t *addr, uint8_t addr_type)
ble_ll_is_on_resolv_list(const uint8_t *addr, uint8_t addr_type)
{
int i;
struct ble_ll_resolv_entry *rl;
@@ -242,7 +245,7 @@ ble_ll_is_on_resolv_list(uint8_t *addr, uint8_t addr_type)
* @return Pointer to resolving list entry or NULL if no entry found.
*/
struct ble_ll_resolv_entry *
ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type)
ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type)
{
int i;
struct ble_ll_resolv_entry *rl;
@@ -265,13 +268,16 @@ ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type)
* @return int
*/
int
ble_ll_resolv_list_add(uint8_t *cmdbuf)
ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_add_resolv_list_cp *cmd = (const void *) cmdbuf;
int rc;
uint8_t addr_type;
uint8_t *ident_addr;
struct ble_ll_resolv_entry *rl;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* Must be in proper state */
if (!ble_ll_resolv_list_chg_allowed()) {
return BLE_ERR_CMD_DISALLOWED;
@@ -282,23 +288,20 @@ ble_ll_resolv_list_add(uint8_t *cmdbuf)
return BLE_ERR_MEM_CAPACITY;
}
addr_type = cmdbuf[0];
ident_addr = cmdbuf + 1;
/* spec is not clear on how to handle this but make sure host is aware
* that new keys are not used in that case
*/
if (ble_ll_is_on_resolv_list(ident_addr, addr_type)) {
if (ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt];
memset (rl, 0, sizeof(*rl));
rl->rl_addr_type = addr_type;
memcpy(&rl->rl_identity_addr[0], ident_addr, BLE_DEV_ADDR_LEN);
swap_buf(rl->rl_peer_irk, cmdbuf + 7, 16);
swap_buf(rl->rl_local_irk, cmdbuf + 23, 16);
rl->rl_addr_type = cmd->peer_addr_type;
memcpy(rl->rl_identity_addr, cmd->peer_id_addr, BLE_DEV_ADDR_LEN);
swap_buf(rl->rl_peer_irk, cmd->peer_irk, 16);
swap_buf(rl->rl_local_irk, cmd->local_irk, 16);
/* By default use privacy network mode */
rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK;
@@ -327,22 +330,22 @@ ble_ll_resolv_list_add(uint8_t *cmdbuf)
* @return int 0: success, BLE error code otherwise
*/
int
ble_ll_resolv_list_rmv(uint8_t *cmdbuf)
ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_rmv_resolve_list_cp *cmd = (const void *) cmdbuf;
int position;
uint8_t addr_type;
uint8_t *ident_addr;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* Must be in proper state */
if (!ble_ll_resolv_list_chg_allowed()) {
return BLE_ERR_CMD_DISALLOWED;
}
addr_type = cmdbuf[0];
ident_addr = cmdbuf + 1;
/* Remove from IRK records */
position = ble_ll_is_on_resolv_list(ident_addr, addr_type);
position = ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type);
if (position) {
BLE_LL_ASSERT(position <= g_ble_ll_resolv_data.rl_cnt);
@@ -368,81 +371,87 @@ ble_ll_resolv_list_rmv(uint8_t *cmdbuf)
* @return int
*/
int
ble_ll_resolv_enable_cmd(uint8_t *cmdbuf)
ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len)
{
int rc;
const struct ble_hci_le_set_addr_res_en_cp *cmd = (const void *) cmdbuf;
int32_t tmo;
uint8_t enabled;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (ble_ll_is_controller_busy()) {
rc = BLE_ERR_CMD_DISALLOWED;
} else {
enabled = cmdbuf[0];
if (enabled <= 1) {
/* If we change state, we need to disable/enable the RPA timer */
if ((enabled ^ g_ble_ll_resolv_data.addr_res_enabled) != 0) {
if (enabled) {
tmo = (int32_t)g_ble_ll_resolv_data.rpa_tmo;
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, tmo);
} else {
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
}
g_ble_ll_resolv_data.addr_res_enabled = enabled;
}
rc = BLE_ERR_SUCCESS;
return BLE_ERR_CMD_DISALLOWED;
}
if (cmd->enable > 1) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* If we change state, we need to disable/enable the RPA timer */
if ((cmd->enable ^ g_ble_ll_resolv_data.addr_res_enabled) != 0) {
if (cmd->enable) {
tmo = (int32_t)g_ble_ll_resolv_data.rpa_tmo;
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, tmo);
} else {
rc = BLE_ERR_INV_HCI_CMD_PARMS;
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
}
g_ble_ll_resolv_data.addr_res_enabled = cmd->enable;
}
return BLE_ERR_SUCCESS;
}
int
ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
const struct ble_hci_le_rd_peer_recolv_addr_cp *cmd = (const void *) cmdbuf;
struct ble_hci_le_rd_peer_recolv_addr_rp *rsp = (void *) rspbuf;
struct ble_ll_resolv_entry *rl;
int rc;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type);
if (rl) {
memcpy(rsp->rpa, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
rc = BLE_ERR_SUCCESS;
} else {
memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN);
rc = BLE_ERR_UNK_CONN_ID;
}
*rsplen = sizeof(*rsp);
return rc;
}
int
ble_ll_resolv_peer_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
const struct ble_hci_le_rd_local_recolv_addr_cp *cmd = (const void *) cmdbuf;
struct ble_hci_le_rd_local_recolv_addr_rp *rsp = (void *) rspbuf;
struct ble_ll_resolv_entry *rl;
uint8_t addr_type;
uint8_t *ident_addr;
int rc;
addr_type = cmdbuf[0];
ident_addr = cmdbuf + 1;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rl = ble_ll_resolv_list_find(ident_addr, addr_type);
rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type);
if (rl) {
memcpy(rspbuf, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
memcpy(rsp->rpa, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
rc = BLE_ERR_SUCCESS;
} else {
memset(rspbuf, 0, BLE_DEV_ADDR_LEN);
memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN);
rc = BLE_ERR_UNK_CONN_ID;
}
*rsplen = BLE_DEV_ADDR_LEN;
return rc;
}
int
ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
{
struct ble_ll_resolv_entry *rl;
uint8_t addr_type;
uint8_t *ident_addr;
int rc;
addr_type = cmdbuf[0];
ident_addr = cmdbuf + 1;
rl = ble_ll_resolv_list_find(ident_addr, addr_type);
if (rl) {
memcpy(rspbuf, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
rc = BLE_ERR_SUCCESS;
} else {
memset(rspbuf, 0, BLE_DEV_ADDR_LEN);
rc = BLE_ERR_UNK_CONN_ID;
}
*rsplen = BLE_DEV_ADDR_LEN;
*rsplen = sizeof(*rsp);
return rc;
}
@@ -454,11 +463,16 @@ ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
* @return int
*/
int
ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_rpa_tmo_cp *cmd = (const void *)cmdbuf;
uint16_t tmo_secs;
tmo_secs = get_le16(cmdbuf);
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
tmo_secs = le16toh(cmd->rpa_timeout);
if (!((tmo_secs > 0) && (tmo_secs <= 0xA1B8))) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -478,26 +492,31 @@ ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
}
int
ble_ll_resolve_set_priv_mode(uint8_t *cmdbuf)
ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_set_privacy_mode_cp *cmd = (const void *) cmdbuf;
struct ble_ll_resolv_entry *rl;
if (ble_ll_is_controller_busy()) {
return BLE_ERR_CMD_DISALLOWED;
}
/* cmdbuf = addr_type(0) | addr(6) | priv_mode(1) */
rl = ble_ll_resolv_list_find(&cmdbuf[1], cmdbuf[0]);
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_id_addr_type);
if (!rl) {
return BLE_ERR_UNK_CONN_ID;
}
if (cmdbuf[7] > BLE_HCI_PRIVACY_DEVICE) {
if (cmd->mode > BLE_HCI_PRIVACY_DEVICE) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rl->rl_priv_mode = cmdbuf[7];
return 0;
rl->rl_priv_mode = cmd->mode;
return BLE_ERR_SUCCESS;
}
/**
File diff suppressed because it is too large Load Diff
+128 -130
View File
@@ -156,29 +156,29 @@ ble_ll_sync_phy_mode_to_hci(int8_t phy_mode)
static void
ble_ll_sync_est_event_success(struct ble_ll_sync_sm *sm)
{
struct hci_le_subev_periodic_adv_sync_estab *evt;
uint8_t *evbuf;
struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev;
struct ble_hci_ev *hci_ev;
BLE_LL_ASSERT(g_ble_ll_sync_comp_ev);
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB)) {
evbuf = g_ble_ll_sync_comp_ev;
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_PERIODIC_ADV_SYNC_ESTAB_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB;
hci_ev = (void *) g_ble_ll_sync_comp_ev;
evt = (void *) evbuf + 3;
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
evt->status = BLE_ERR_SUCCESS;
evt->sync_handle = htole16(ble_ll_sync_get_handle(sm));
evt->sid = sm->adv_sid;
evt->adv_addr_type = sm->adv_addr_type;
memcpy(evt->adv_addr, sm->adv_addr, BLE_DEV_ADDR_LEN);
evt->adv_phy = ble_ll_sync_phy_mode_to_hci(sm->phy_mode);
evt->per_adv_ival = htole16(sm->itvl);
evt->adv_clk_accuracy = sm->sca;
ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB;
ev->status = BLE_ERR_SUCCESS;
ev->sync_handle = htole16(ble_ll_sync_get_handle(sm));
ev->sid = sm->adv_sid;
ev->peer_addr_type = sm->adv_addr_type;
memcpy(ev->peer_addr, sm->adv_addr, BLE_DEV_ADDR_LEN);
ev->phy = ble_ll_sync_phy_mode_to_hci(sm->phy_mode);
ev->interval = htole16(sm->itvl);
ev->aca = sm->sca;
ble_ll_hci_event_send(evbuf);
ble_ll_hci_event_send(hci_ev);
} else {
ble_hci_trans_buf_free(g_ble_ll_sync_comp_ev);
}
@@ -189,23 +189,24 @@ ble_ll_sync_est_event_success(struct ble_ll_sync_sm *sm)
static void
ble_ll_sync_est_event_failed(uint8_t status)
{
struct hci_le_subev_periodic_adv_sync_estab *evt;
uint8_t *evbuf;
struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev;
struct ble_hci_ev *hci_ev;
BLE_LL_ASSERT(g_ble_ll_sync_comp_ev);
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB)) {
evbuf = g_ble_ll_sync_comp_ev;
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_PERIODIC_ADV_SYNC_ESTAB_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB;
hci_ev = (void *) g_ble_ll_sync_comp_ev;
evt = (void *) evbuf + 3;
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
memset(evt, 0, sizeof(*evt));
evt->status = status;
memset(ev, 0, sizeof(*ev));
ble_ll_hci_event_send(evbuf);
ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB;
ev->status = status;
ble_ll_hci_event_send(hci_ev);
} else {
ble_hci_trans_buf_free(g_ble_ll_sync_comp_ev);
}
@@ -216,20 +217,20 @@ ble_ll_sync_est_event_failed(uint8_t status)
static void
ble_ll_sync_lost_event(struct ble_ll_sync_sm *sm)
{
struct hci_le_subev_periodic_adv_sync_lost *evt;
uint8_t *evbuf;
struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev;
struct ble_hci_ev *hci_ev;
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST)) {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (evbuf) {
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_PERIODIC_ADV_SYNC_LOST_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST;
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (hci_ev) {
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
evt = (void *) evbuf + 3;
evt->sync_handle = htole16(ble_ll_sync_get_handle(sm));
ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST;
ev->sync_handle = htole16(ble_ll_sync_get_handle(sm));
ble_ll_hci_event_send(evbuf);
ble_ll_hci_event_send(hci_ev);
}
}
@@ -489,36 +490,40 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power)
static void
ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf)
{
struct hci_le_subev_periodic_adv_rpt *evt;
struct ble_hci_ev_le_subev_periodic_adv_rpt *ev;
struct ble_hci_ev *hci_ev;
if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT)) {
ble_hci_trans_buf_free(evbuf);
return;
}
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_PERIODIC_ADV_RPT_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT;
hci_ev = (void *) evbuf;
evt = (void *) evbuf + 3;
evt->sync_handle = htole16(ble_ll_sync_get_handle(sm));
evt->tx_power = 127; /* not available */
evt->rssi = 127; /* not available */
evt->unused = 0xff;
evt->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED;
evt->data_length = 0;
ble_ll_hci_event_send(evbuf);
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT;
ev->sync_handle = htole16(ble_ll_sync_get_handle(sm));
ev->tx_power = 127; /* not available */
ev->rssi = 127; /* not available */
ev->cte_type = 0xff;
ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED;
ev->data_len = 0;
ble_ll_hci_event_send(hci_ev);
}
static int
ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu,
struct ble_mbuf_hdr *hdr, uint8_t **aux)
{
struct hci_le_subev_periodic_adv_rpt *evt;
uint8_t *evbuf_next = NULL;
uint16_t max_event_len;
struct ble_hci_ev_le_subev_periodic_adv_rpt *ev;
struct ble_hci_ev *hci_ev;
struct ble_hci_ev *hci_ev_next = NULL;
uint8_t max_data_len;
int8_t tx_power;
uint8_t *evbuf;
int datalen;
int offset;
int rc;
@@ -539,64 +544,62 @@ ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu,
/* use next report buffer if present, this means we are chaining */
if (sm->next_report) {
evbuf = sm->next_report;
hci_ev = (void *) sm->next_report;
sm->next_report = NULL;
} else {
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
if (!evbuf) {
hci_ev = (void * )ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
if (!hci_ev) {
return -1;
}
}
/* Max_event_len contains advertising data and BLE_HCI_EVENT_HDR_LEN as this
* is related to the buffer available for the event. The maximum is 255 + 2
*/
max_data_len = BLE_LL_MAX_EVT_LEN - sizeof(*hci_ev) - sizeof(*ev);
offset = 0;
max_event_len = min(UINT8_MAX + BLE_HCI_EVENT_HDR_LEN, BLE_LL_MAX_EVT_LEN);
do {
if (evbuf_next) {
evbuf = evbuf_next;
evbuf_next = NULL;
if (hci_ev_next) {
hci_ev = hci_ev_next;
hci_ev_next = NULL;
}
evbuf[0] = BLE_HCI_EVCODE_LE_META;
evbuf[1] = BLE_HCI_LE_PERIODIC_ADV_RPT_LEN;
evbuf[2] = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT;
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
evt = (void *) evbuf + 3;
evt->sync_handle = htole16(ble_ll_sync_get_handle(sm));
evt->tx_power = tx_power;
evt->rssi = hdr->rxinfo.rssi;
evt->unused = 0xff;
ev = (void *) hci_ev->data;
evt->data_length = min(max_event_len - sizeof(*evt) - 3, datalen - offset);
ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT;
ev->sync_handle = htole16(ble_ll_sync_get_handle(sm));
ev->tx_power = tx_power;
ev->rssi = hdr->rxinfo.rssi;
ev->cte_type = 0xff;
ev->data_len = min(max_data_len, datalen - offset);
/* adjust event length */
evbuf[1] += evt->data_length;
hci_ev->length += ev->data_len;
os_mbuf_copydata(rxpdu, offset, evt->data_length, evt->data);
offset += evt->data_length;
os_mbuf_copydata(rxpdu, offset, ev->data_len, ev->data);
offset += ev->data_len;
/* Need another event for next fragment of this PDU */
if ((offset < datalen) || *aux) {
evbuf_next = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
if (evbuf_next) {
evt->data_status = BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE;
hci_ev_next = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
if (hci_ev_next) {
ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE;
rc = 0;
} else {
evt->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED;
ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED;
rc = -1;
}
} else {
evt->data_status = BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE;
ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE;
rc = 0;
}
ble_ll_hci_event_send(evbuf);
} while ((offset < datalen) && evbuf_next);
ble_ll_hci_event_send(hci_ev);
} while ((offset < datalen) && hci_ev_next);
/* store for chain */
sm->next_report = evbuf_next;
sm->next_report = (void *) hci_ev_next;
return rc;
}
@@ -1216,15 +1219,11 @@ ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, uint8_t sid,
}
int
ble_ll_sync_create(uint8_t *cmdbuf)
ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_periodic_adv_create_sync_cp *cmd = (const void *) cmdbuf;
struct ble_ll_sync_sm *sm;
uint8_t filter_policy;
uint8_t addr_type;
uint16_t timeout;
uint8_t *addr;
uint16_t skip;
uint8_t sid;
os_sr_t sr;
int cnt;
int i;
@@ -1233,23 +1232,25 @@ ble_ll_sync_create(uint8_t *cmdbuf)
return BLE_ERR_CMD_DISALLOWED;
}
filter_policy = cmdbuf[0];
if (filter_policy > 0x01) {
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
skip = get_le16(cmdbuf + 9);
if (skip > 0x01f3) {
if (cmd->options > BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
timeout = get_le16(cmdbuf + 11);
if (cmd->skip > 0x01f3) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
timeout = le16toh(cmd->sync_timeout);
if (timeout < 0x000a && timeout > 0x4000) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* check if list is sane */
if (filter_policy) {
if (cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) {
cnt = 0;
OS_ENTER_CRITICAL(sr);
@@ -1270,7 +1271,7 @@ ble_ll_sync_create(uint8_t *cmdbuf)
/* mark as pending */
sm->flags |= BLE_LL_SYNC_SM_FLAG_PENDING;
sm->skip = skip;
sm->skip = cmd->skip;
sm->timeout = timeout * 10000; /* 10ms units, store in us */
cnt++;
}
@@ -1284,19 +1285,15 @@ ble_ll_sync_create(uint8_t *cmdbuf)
return BLE_ERR_CMD_DISALLOWED;
}
} else {
sid = cmdbuf[1];
if (sid > 0x0f) {
if (cmd->sid > 0x0f) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
addr_type = cmdbuf[2];
if (addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) {
if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
addr = &cmdbuf[3];
sm = ble_ll_sync_get(addr, addr_type, sid);
sm = ble_ll_sync_get(cmd->peer_addr, cmd->peer_addr_type, cmd->sid);
if (!sm) {
return BLE_ERR_MEM_CAPACITY;
}
@@ -1312,7 +1309,7 @@ ble_ll_sync_create(uint8_t *cmdbuf)
/* mark as pending */
sm->flags |= BLE_LL_SYNC_SM_FLAG_PENDING;
sm->timeout = timeout * 10000; /* 10ms units, store in us */
sm->skip = skip;
sm->skip = cmd->skip;
OS_EXIT_CRITICAL(sr);
}
@@ -1379,8 +1376,9 @@ ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
}
int
ble_ll_sync_terminate(uint8_t *cmdbuf)
ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_periodic_adv_term_sync_cp *cmd = (const void *) cmdbuf;
struct ble_ll_sync_sm *sm;
uint16_t handle;
os_sr_t sr;
@@ -1389,7 +1387,11 @@ ble_ll_sync_terminate(uint8_t *cmdbuf)
return BLE_ERR_CMD_DISALLOWED;
}
handle = get_le16(cmdbuf);
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
handle = le16toh(cmd->sync_handle);
if (handle > 0xeff) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -1415,33 +1417,30 @@ ble_ll_sync_terminate(uint8_t *cmdbuf)
}
int
ble_ll_sync_list_add(uint8_t *cmdbuf)
ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_add_dev_to_periodic_adv_list_cp *cmd = (const void *)cmdbuf;
struct ble_ll_sync_sm *sm;
uint8_t addr_type;
uint8_t *addr;
uint8_t sid;
os_sr_t sr;
if (g_ble_ll_sync_pending) {
return BLE_ERR_CMD_DISALLOWED;
}
addr_type = cmdbuf[0];
if (addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) {
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
addr = &cmdbuf[1];
sid = cmdbuf[7];
if (sid > 0x0f) {
if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (cmd->sid > 0x0f) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
OS_ENTER_CRITICAL(sr);
sm = ble_ll_sync_get(addr, addr_type, sid);
sm = ble_ll_sync_get(cmd->peer_addr, cmd->peer_addr_type, cmd->sid);
if (!sm) {
OS_EXIT_CRITICAL(sr);
return BLE_ERR_MEM_CAPACITY;
@@ -1455,33 +1454,31 @@ ble_ll_sync_list_add(uint8_t *cmdbuf)
}
int
ble_ll_sync_list_remove(uint8_t *cmdbuf)
ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_rem_dev_from_periodic_adv_list_cp *cmd = (const void *)cmdbuf;
struct ble_ll_sync_sm *sm;
uint8_t addr_type;
uint8_t *addr;
uint8_t sid;
os_sr_t sr;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (g_ble_ll_sync_pending) {
return BLE_ERR_CMD_DISALLOWED;
}
addr_type = cmdbuf[0];
if (addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) {
if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
addr = &cmdbuf[1];
sid = cmdbuf[7];
if (sid > 0x0f) {
if (cmd->sid > 0x0f) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
OS_ENTER_CRITICAL(sr);
sm = ble_ll_sync_find(addr, addr_type, sid);
sm = ble_ll_sync_find(cmd->peer_addr, cmd->peer_addr_type, cmd->sid);
if (!sm) {
OS_EXIT_CRITICAL(sr);
return BLE_ERR_UNK_ADV_INDENT;
@@ -1532,10 +1529,11 @@ ble_ll_sync_list_clear(void)
int
ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen)
{
struct ble_hci_le_rd_periodic_adv_list_size_rp *rsp = (void *) rspbuf;
os_sr_t sr;
int i;
rspbuf[0] = 0;
rsp->list_size = 0;
OS_ENTER_CRITICAL(sr);
@@ -1546,12 +1544,12 @@ ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen)
continue;
}
rspbuf[0]++;
rsp->list_size++;
}
OS_EXIT_CRITICAL(sr);
*rsplen = 1;
*rsplen = sizeof(*rsp);
return BLE_ERR_SUCCESS;
}
+27 -13
View File
@@ -105,8 +105,12 @@ ble_ll_whitelist_clear(void)
int
ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen)
{
rspbuf[0] = BLE_LL_WHITELIST_SIZE;
*rsplen = 1;
struct ble_hci_le_rd_white_list_rp *rsp = (void *) rspbuf;
rsp->size = BLE_LL_WHITELIST_SIZE;
*rsplen = sizeof(*rsp);
return BLE_ERR_SUCCESS;
}
@@ -123,7 +127,7 @@ ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen)
* plus 1).
*/
static int
ble_ll_whitelist_search(uint8_t *addr, uint8_t addr_type)
ble_ll_whitelist_search(const uint8_t *addr, uint8_t addr_type)
{
int i;
struct ble_ll_whitelist_entry *wl;
@@ -180,11 +184,16 @@ ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident)
* @return int
*/
int
ble_ll_whitelist_add(uint8_t *addr, uint8_t addr_type)
ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len)
{
int i;
int rc;
const struct ble_hci_le_add_whte_list_cp *cmd = (const void *) cmdbuf;
struct ble_ll_whitelist_entry *wl;
int rc;
int i;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* Must be in proper state */
if (!ble_ll_whitelist_chg_allowed()) {
@@ -193,12 +202,12 @@ ble_ll_whitelist_add(uint8_t *addr, uint8_t addr_type)
/* Check if we have any open entries */
rc = BLE_ERR_SUCCESS;
if (!ble_ll_whitelist_search(addr, addr_type)) {
if (!ble_ll_whitelist_search(cmd->addr, cmd->addr_type)) {
wl = &g_ble_ll_whitelist[0];
for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) {
if (wl->wl_valid == 0) {
memcpy(&wl->wl_dev_addr[0], addr, BLE_DEV_ADDR_LEN);
wl->wl_addr_type = addr_type;
memcpy(&wl->wl_dev_addr[0], cmd->addr, BLE_DEV_ADDR_LEN);
wl->wl_addr_type = cmd->addr_type;
wl->wl_valid = 1;
break;
}
@@ -209,7 +218,7 @@ ble_ll_whitelist_add(uint8_t *addr, uint8_t addr_type)
rc = BLE_ERR_MEM_CAPACITY;
} else {
#if (BLE_USES_HW_WHITELIST == 1)
rc = ble_hw_whitelist_add(addr, addr_type);
rc = ble_hw_whitelist_add(cmd->addr, cmd->addr_type);
#endif
}
}
@@ -225,22 +234,27 @@ ble_ll_whitelist_add(uint8_t *addr, uint8_t addr_type)
* @return int 0: success, BLE error code otherwise
*/
int
ble_ll_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_le_rmv_white_list_cp *cmd = (const void *) cmdbuf;
int position;
if (len != sizeof(*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* Must be in proper state */
if (!ble_ll_whitelist_chg_allowed()) {
return BLE_ERR_CMD_DISALLOWED;
}
position = ble_ll_whitelist_search(addr, addr_type);
position = ble_ll_whitelist_search(cmd->addr, cmd->addr_type);
if (position) {
g_ble_ll_whitelist[position - 1].wl_valid = 0;
}
#if (BLE_USES_HW_WHITELIST == 1)
ble_hw_whitelist_rmv(addr, addr_type);
ble_hw_whitelist_rmv(cmd->addr, cmd->addr_type);
#endif
return BLE_ERR_SUCCESS;
+2 -2
View File
@@ -66,7 +66,7 @@ ble_hw_whitelist_clear(void)
* @return int 0: success, BLE error code otherwise
*/
int
ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
{
return BLE_ERR_MEM_CAPACITY;
}
@@ -79,7 +79,7 @@ ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
*
*/
void
ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
{
return;
}
+2 -2
View File
@@ -124,7 +124,7 @@ ble_hw_whitelist_clear(void)
* @return int 0: success, BLE error code otherwise
*/
int
ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
{
int i;
uint32_t mask;
@@ -155,7 +155,7 @@ ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
*
*/
void
ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
{
int i;
uint8_t cfg_addr;
+2 -2
View File
@@ -124,7 +124,7 @@ ble_hw_whitelist_clear(void)
* @return int 0: success, BLE error code otherwise
*/
int
ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
{
int i;
uint32_t mask;
@@ -155,7 +155,7 @@ ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
*
*/
void
ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
{
int i;
uint8_t cfg_addr;
+3 -3
View File
@@ -390,7 +390,7 @@ struct ble_gap_ext_disc_desc {
uint8_t length_data;
/** Advertising data */
uint8_t *data;
const uint8_t *data;
/** Directed advertising address. Valid if BLE_HCI_ADV_DIRECT_MASK props is
* set (BLE_ADDR_ANY otherwise).
@@ -420,7 +420,7 @@ struct ble_gap_disc_desc {
int8_t rssi;
/** Advertising data */
uint8_t *data;
const uint8_t *data;
/** Directed advertising address. Valid for BLE_HCI_ADV_RPT_EVTYPE_DIR_IND
* event type (BLE_ADDR_ANY otherwise).
@@ -890,7 +890,7 @@ struct ble_gap_event {
uint8_t data_length;
/** Advertising data */
uint8_t *data;
const uint8_t *data;
} periodic_report;
/**
+14 -14
View File
@@ -35,7 +35,7 @@ extern "C" {
struct ble_hs_adv_field {
uint8_t length;
uint8_t type;
uint8_t value[];
uint8_t value[0];
};
typedef int (* ble_hs_adv_parse_func_t) (const struct ble_hs_adv_field *,
@@ -46,22 +46,22 @@ struct ble_hs_adv_fields {
uint8_t flags;
/*** 0x02,0x03 - 16-bit service class UUIDs. */
ble_uuid16_t *uuids16;
const ble_uuid16_t *uuids16;
uint8_t num_uuids16;
unsigned uuids16_is_complete:1;
/*** 0x04,0x05 - 32-bit service class UUIDs. */
ble_uuid32_t *uuids32;
const ble_uuid32_t *uuids32;
uint8_t num_uuids32;
unsigned uuids32_is_complete:1;
/*** 0x06,0x07 - 128-bit service class UUIDs. */
ble_uuid128_t *uuids128;
const ble_uuid128_t *uuids128;
uint8_t num_uuids128;
unsigned uuids128_is_complete:1;
/*** 0x08,0x09 - Local name. */
uint8_t *name;
const uint8_t *name;
uint8_t name_len;
unsigned name_is_complete:1;
@@ -70,14 +70,14 @@ struct ble_hs_adv_fields {
unsigned tx_pwr_lvl_is_present:1;
/*** 0x0d - Slave connection interval range. */
uint8_t *slave_itvl_range;
const uint8_t *slave_itvl_range;
/*** 0x16 - Service data - 16-bit UUID. */
uint8_t *svc_data_uuid16;
const uint8_t *svc_data_uuid16;
uint8_t svc_data_uuid16_len;
/*** 0x17 - Public target address. */
uint8_t *public_tgt_addr;
const uint8_t *public_tgt_addr;
uint8_t num_public_tgt_addrs;
/*** 0x19 - Appearance. */
@@ -89,19 +89,19 @@ struct ble_hs_adv_fields {
unsigned adv_itvl_is_present:1;
/*** 0x20 - Service data - 32-bit UUID. */
uint8_t *svc_data_uuid32;
const uint8_t *svc_data_uuid32;
uint8_t svc_data_uuid32_len;
/*** 0x21 - Service data - 128-bit UUID. */
uint8_t *svc_data_uuid128;
const uint8_t *svc_data_uuid128;
uint8_t svc_data_uuid128_len;
/*** 0x24 - URI. */
uint8_t *uri;
const uint8_t *uri;
uint8_t uri_len;
/*** 0xff - Manufacturer specific data. */
uint8_t *mfg_data;
const uint8_t *mfg_data;
uint8_t mfg_data_len;
};
@@ -164,8 +164,8 @@ int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields,
int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
uint8_t *dst, uint8_t *dst_len, uint8_t max_len);
int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src,
uint8_t src_len);
int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields,
const uint8_t *src, uint8_t src_len);
int ble_hs_adv_parse(const uint8_t *data, uint8_t length,
ble_hs_adv_parse_func_t func, void *user_data);
+703 -726
View File
File diff suppressed because it is too large Load Diff
+27 -11
View File
@@ -81,23 +81,39 @@ 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);
void ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev);
#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);
void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev);
void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev);
void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev);
#endif
void ble_gap_rx_scan_req_rcvd(struct hci_le_scan_req_rcvd *evt);
void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev);
#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);
int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt, uint8_t instance);
void ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt);
void ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt);
void ble_gap_rx_param_req(struct hci_le_conn_param_req *evt);
void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev);
struct ble_gap_conn_complete
{
uint8_t status;
uint16_t connection_handle;
uint8_t role;
uint8_t peer_addr_type;
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
uint16_t conn_itvl;
uint16_t conn_latency;
uint16_t supervision_timeout;
uint8_t master_clk_acc;
uint8_t local_rpa[BLE_DEV_ADDR_LEN];
uint8_t peer_rpa[BLE_DEV_ADDR_LEN];
};
int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance);
void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev);
void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev);
void ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev);
int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
struct ble_gap_upd_params *params);
void ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt);
void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev);
void ble_gap_enc_event(uint16_t conn_handle, int status,
int security_restored);
void ble_gap_passkey_event(uint16_t conn_handle,
+5 -5
View File
@@ -500,20 +500,20 @@ ble_hs_sched_start(void)
static void
ble_hs_event_rx_hci_ev(struct ble_npl_event *ev)
{
uint8_t *hci_evt;
const struct ble_hci_ev *hci_ev;
int rc;
hci_evt = ble_npl_event_get_arg(ev);
hci_ev = ble_npl_event_get_arg(ev);
rc = os_memblock_put(&ble_hs_hci_ev_pool, ev);
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
#if BLE_MONITOR
ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, hci_evt,
hci_evt[1] + BLE_HCI_EVENT_HDR_LEN);
ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, hci_ev,
hci_ev->length + sizeof(*hci_ev));
#endif
ble_hs_hci_evt_process(hci_evt);
ble_hs_hci_evt_process(hci_ev);
}
static void
+10 -9
View File
@@ -63,8 +63,8 @@ ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len,
static int
ble_hs_adv_set_flat_mbuf(uint8_t type, int data_len, const void *data,
uint8_t *dst, uint8_t *dst_len, uint8_t max_len,
struct os_mbuf *om)
uint8_t *dst, uint8_t *dst_len, uint8_t max_len,
struct os_mbuf *om)
{
int rc;
@@ -489,7 +489,7 @@ ble_hs_adv_parse_uuids16(struct ble_hs_adv_fields *adv_fields,
for (i = 0; i < adv_fields->num_uuids16; i++) {
ble_uuid_init_from_buf(&uuid, data + i * 2, 2);
adv_fields->uuids16[i] = uuid.u16;
ble_hs_adv_uuids16[i] = uuid.u16;
}
return 0;
@@ -511,7 +511,7 @@ ble_hs_adv_parse_uuids32(struct ble_hs_adv_fields *adv_fields,
for (i = 0; i < adv_fields->num_uuids32; i++) {
ble_uuid_init_from_buf(&uuid, data + i * 4, 4);
adv_fields->uuids32[i] = uuid.u32;
ble_hs_adv_uuids32[i] = uuid.u32;
}
return 0;
@@ -533,7 +533,7 @@ ble_hs_adv_parse_uuids128(struct ble_hs_adv_fields *adv_fields,
for (i = 0; i < adv_fields->num_uuids128; i++) {
ble_uuid_init_from_buf(&uuid, data + i * 16, 16);
adv_fields->uuids128[i] = uuid.u128;
ble_hs_adv_uuids128[i] = uuid.u128;
}
return 0;
@@ -541,11 +541,12 @@ ble_hs_adv_parse_uuids128(struct ble_hs_adv_fields *adv_fields,
static int
ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
uint8_t *total_len, uint8_t *src, uint8_t src_len)
uint8_t *total_len, const uint8_t *src,
uint8_t src_len)
{
uint8_t data_len;
uint8_t type;
uint8_t *data;
const uint8_t *data;
int rc;
if (src_len < 1) {
@@ -715,8 +716,8 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
}
int
ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src,
uint8_t src_len)
ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields,
const uint8_t *src, uint8_t src_len)
{
uint8_t field_len;
int rc;
+58 -78
View File
@@ -32,10 +32,13 @@
static struct ble_npl_mutex ble_hs_hci_mutex;
static struct ble_npl_sem ble_hs_hci_sem;
static uint8_t *ble_hs_hci_ack;
static struct ble_hci_ev *ble_hs_hci_ack;
static uint16_t ble_hs_hci_buf_sz;
static uint8_t ble_hs_hci_max_pkts;
/* For now 32-bits of features is enough */
static uint32_t ble_hs_hci_sup_feat;
static uint8_t ble_hs_hci_version;
#define BLE_HS_HCI_FRAG_DATABUF_SIZE \
@@ -127,71 +130,66 @@ ble_hs_hci_add_avail_pkts(uint16_t delta)
}
static int
ble_hs_hci_rx_cmd_complete(uint8_t event_code, uint8_t *data, int len,
ble_hs_hci_rx_cmd_complete(const void *data, int len,
struct ble_hs_hci_ack *out_ack)
{
const struct ble_hci_ev_command_complete *ev = data;
const struct ble_hci_ev_command_complete_nop *nop = data;
uint16_t opcode;
uint8_t *params;
uint8_t params_len;
uint8_t num_pkts;
if (len < BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN) {
return BLE_HS_ECONTROLLER;
if (len < sizeof(*ev)) {
if (len < sizeof(*nop)) {
return BLE_HS_ECONTROLLER;
}
/* nop is special as it doesn't have status and response */
opcode = le16toh(nop->opcode);
if (opcode != BLE_HCI_OPCODE_NOP) {
return BLE_HS_ECONTROLLER;
}
/* TODO Process num_pkts field. */
out_ack->bha_status = 0;
out_ack->bha_params = NULL;
out_ack->bha_params_len = 0;
return 0;
}
num_pkts = data[2];
opcode = get_le16(data + 3);
params = data + 5;
opcode = le16toh(ev->opcode);
/* XXX: Process num_pkts field. */
(void)num_pkts;
/* TODO Process num_pkts field. */
out_ack->bha_opcode = opcode;
params_len = len - BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN;
if (params_len > 0) {
out_ack->bha_status = BLE_HS_HCI_ERR(params[0]);
} else if (opcode == BLE_HCI_OPCODE_NOP) {
out_ack->bha_status = 0;
} else {
out_ack->bha_status = BLE_HS_ECONTROLLER;
}
/* Don't include the status byte in the parameters blob. */
if (params_len > 1) {
out_ack->bha_params = params + 1;
out_ack->bha_params_len = params_len - 1;
out_ack->bha_status = BLE_HS_HCI_ERR(ev->status);
out_ack->bha_params_len = len - sizeof(*ev);
if (out_ack->bha_params_len) {
out_ack->bha_params = ev->return_params;
} else {
out_ack->bha_params = NULL;
out_ack->bha_params_len = 0;
}
return 0;
}
static int
ble_hs_hci_rx_cmd_status(uint8_t event_code, uint8_t *data, int len,
ble_hs_hci_rx_cmd_status(const void *data, int len,
struct ble_hs_hci_ack *out_ack)
{
uint16_t opcode;
uint8_t num_pkts;
uint8_t status;
const struct ble_hci_ev_command_status *ev = data;
if (len < BLE_HCI_EVENT_CMD_STATUS_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
status = data[2];
num_pkts = data[3];
opcode = get_le16(data + 4);
/* XXX: Process num_pkts field. */
(void)num_pkts;
out_ack->bha_opcode = opcode;
out_ack->bha_opcode = le16toh(ev->opcode);
out_ack->bha_params = NULL;
out_ack->bha_params_len = 0;
out_ack->bha_status = BLE_HS_HCI_ERR(status);
out_ack->bha_status = BLE_HS_HCI_ERR(ev->status);
return 0;
}
@@ -201,9 +199,6 @@ ble_hs_hci_process_ack(uint16_t expected_opcode,
uint8_t *params_buf, uint8_t params_buf_len,
struct ble_hs_hci_ack *out_ack)
{
uint8_t event_code;
uint8_t param_len;
uint8_t event_len;
int rc;
BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
@@ -211,22 +206,19 @@ ble_hs_hci_process_ack(uint16_t expected_opcode,
/* Count events received */
STATS_INC(ble_hs_stats, hci_event);
event_code = ble_hs_hci_ack[0];
param_len = ble_hs_hci_ack[1];
event_len = param_len + 2;
/* Clear ack fields up front to silence spurious gcc warnings. */
memset(out_ack, 0, sizeof *out_ack);
switch (event_code) {
switch (ble_hs_hci_ack->opcode) {
case BLE_HCI_EVCODE_COMMAND_COMPLETE:
rc = ble_hs_hci_rx_cmd_complete(event_code, ble_hs_hci_ack,
event_len, out_ack);
rc = ble_hs_hci_rx_cmd_complete(ble_hs_hci_ack->data,
ble_hs_hci_ack->length, out_ack);
break;
case BLE_HCI_EVCODE_COMMAND_STATUS:
rc = ble_hs_hci_rx_cmd_status(event_code, ble_hs_hci_ack,
event_len, out_ack);
rc = ble_hs_hci_rx_cmd_status(ble_hs_hci_ack->data,
ble_hs_hci_ack->length, out_ack);
break;
default:
@@ -269,20 +261,20 @@ ble_hs_hci_wait_for_ack(void)
rc = BLE_HS_ETIMEOUT_HCI;
} else {
ble_hs_hci_ack =
ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
(void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
rc = ble_hs_hci_phony_ack_cb(ble_hs_hci_ack, 260);
rc = ble_hs_hci_phony_ack_cb((void *)ble_hs_hci_ack, 260);
}
#else
rc = ble_npl_sem_pend(&ble_hs_hci_sem,
ble_npl_time_ms_to_ticks32(BLE_HCI_CMD_TIMEOUT_MS));
ble_npl_time_ms_to_ticks32(BLE_HCI_CMD_TIMEOUT_MS));
switch (rc) {
case 0:
BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
#if BLE_MONITOR
ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, ble_hs_hci_ack,
ble_hs_hci_ack[1] + BLE_HCI_EVENT_HDR_LEN);
ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, (void *) ble_hs_hci_ack,
sizeof(*ble_hs_hci_ack) + ble_hs_hci_ack->length);
#endif
break;
@@ -300,9 +292,8 @@ ble_hs_hci_wait_for_ack(void)
}
int
ble_hs_hci_cmd_tx(uint16_t opcode, void *cmd, uint8_t cmd_len,
void *evt_buf, uint8_t evt_buf_len,
uint8_t *out_evt_buf_len)
ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len,
void *rsp, uint8_t rsp_len)
{
struct ble_hs_hci_ack ack;
int rc;
@@ -321,21 +312,23 @@ ble_hs_hci_cmd_tx(uint16_t opcode, void *cmd, uint8_t cmd_len,
goto done;
}
rc = ble_hs_hci_process_ack(opcode, evt_buf, evt_buf_len, &ack);
rc = ble_hs_hci_process_ack(opcode, rsp, rsp_len, &ack);
if (rc != 0) {
ble_hs_sched_reset(rc);
goto done;
}
if (out_evt_buf_len != NULL) {
*out_evt_buf_len = ack.bha_params_len;
}
rc = ack.bha_status;
/* on success we should always get full response */
if (!rc && (ack.bha_params_len != rsp_len)) {
ble_hs_sched_reset(rc);
goto done;
}
done:
if (ble_hs_hci_ack != NULL) {
ble_hci_trans_buf_free(ble_hs_hci_ack);
ble_hci_trans_buf_free((uint8_t *) ble_hs_hci_ack);
ble_hs_hci_ack = NULL;
}
@@ -343,20 +336,7 @@ done:
return rc;
}
int
ble_hs_hci_cmd_tx_empty_ack(uint16_t opcode, void *cmd, uint8_t cmd_len)
{
int rc;
rc = ble_hs_hci_cmd_tx(opcode, cmd, cmd_len, NULL, 0, NULL);
if (rc != 0) {
return rc;
}
return 0;
}
void
static void
ble_hs_hci_rx_ack(uint8_t *ack_ev)
{
if (ble_npl_sem_get_count(&ble_hs_hci_sem) > 0) {
@@ -369,7 +349,7 @@ ble_hs_hci_rx_ack(uint8_t *ack_ev)
/* Unblock the application now that the HCI command buffer is populated
* with the acknowledgement.
*/
ble_hs_hci_ack = ack_ev;
ble_hs_hci_ack = (struct ble_hci_ev *) ack_ev;
ble_npl_sem_release(&ble_hs_hci_sem);
}
File diff suppressed because it is too large Load Diff
+252 -343
View File
@@ -30,7 +30,8 @@
_Static_assert(sizeof (struct hci_data_hdr) == BLE_HCI_DATA_HDR_SZ,
"struct hci_data_hdr must be 4 bytes");
typedef int ble_hs_hci_evt_fn(uint8_t event_code, uint8_t *data, int len);
typedef int ble_hs_hci_evt_fn(uint8_t event_code, const void *data,
unsigned int len);
static ble_hs_hci_evt_fn ble_hs_hci_evt_disconn_complete;
static ble_hs_hci_evt_fn ble_hs_hci_evt_encrypt_change;
static ble_hs_hci_evt_fn ble_hs_hci_evt_hw_error;
@@ -38,7 +39,8 @@ static ble_hs_hci_evt_fn ble_hs_hci_evt_num_completed_pkts;
static ble_hs_hci_evt_fn ble_hs_hci_evt_enc_key_refresh;
static ble_hs_hci_evt_fn ble_hs_hci_evt_le_meta;
typedef int ble_hs_hci_evt_le_fn(uint8_t subevent, uint8_t *data, int len);
typedef int ble_hs_hci_evt_le_fn(uint8_t subevent, const void *data,
unsigned int len);
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_upd_complete;
@@ -54,6 +56,7 @@ 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;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_req_rcvd;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_enh_conn_complete;
/* Statistics */
struct host_hci_stats
{
@@ -89,7 +92,7 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
[BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE] = ble_hs_hci_evt_le_conn_upd_complete,
[BLE_HCI_LE_SUBEV_LT_KEY_REQ] = ble_hs_hci_evt_le_lt_key_req,
[BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ] = ble_hs_hci_evt_le_conn_parm_req,
[BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE] = ble_hs_hci_evt_le_conn_complete,
[BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE] = ble_hs_hci_evt_le_enh_conn_complete,
[BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT] = ble_hs_hci_evt_le_dir_adv_rpt,
[BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE] = ble_hs_hci_evt_le_phy_update_complete,
[BLE_HCI_LE_SUBEV_EXT_ADV_RPT] = ble_hs_hci_evt_le_ext_adv_rpt,
@@ -132,27 +135,24 @@ ble_hs_hci_evt_le_dispatch_find(uint8_t event_code)
}
static int
ble_hs_hci_evt_disconn_complete(uint8_t event_code, uint8_t *data, int len)
ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data,
unsigned int len)
{
struct hci_disconn_complete evt;
const struct ble_hci_ev_disconn_cmp *ev = data;
const struct ble_hs_conn *conn;
if (len < BLE_HCI_EVENT_DISCONN_COMPLETE_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.status = data[2];
evt.connection_handle = get_le16(data + 3);
evt.reason = data[5];
ble_hs_lock();
conn = ble_hs_conn_find(evt.connection_handle);
conn = ble_hs_conn_find(le16toh(ev->conn_handle));
if (conn != NULL) {
ble_hs_hci_add_avail_pkts(conn->bhc_outstanding_pkts);
}
ble_hs_unlock();
ble_gap_rx_disconn_complete(&evt);
ble_gap_rx_disconn_complete(ev);
/* The connection termination may have freed up some capacity in the
* controller for additional ACL data packets. Wake up any stalled
@@ -164,86 +164,68 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, uint8_t *data, int len)
}
static int
ble_hs_hci_evt_encrypt_change(uint8_t event_code, uint8_t *data, int len)
ble_hs_hci_evt_encrypt_change(uint8_t event_code, const void *data,
unsigned int len)
{
struct hci_encrypt_change evt;
const struct ble_hci_ev_enrypt_chg *ev = data;
if (len < BLE_HCI_EVENT_ENCRYPT_CHG_LEN) {
if (len != sizeof (*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.status = data[2];
evt.connection_handle = get_le16(data + 3);
evt.encryption_enabled = data[5];
ble_sm_enc_change_rx(&evt);
ble_sm_enc_change_rx(ev);
return 0;
}
static int
ble_hs_hci_evt_hw_error(uint8_t event_code, uint8_t *data, int len)
ble_hs_hci_evt_hw_error(uint8_t event_code, const void *data, unsigned int len)
{
uint8_t hw_code;
const struct ble_hci_ev_hw_error *ev = data;
if (len < BLE_HCI_EVENT_HW_ERROR_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
hw_code = data[0];
ble_hs_hw_error(hw_code);
ble_hs_hw_error(ev->hw_code);
return 0;
}
static int
ble_hs_hci_evt_enc_key_refresh(uint8_t event_code, uint8_t *data, int len)
ble_hs_hci_evt_enc_key_refresh(uint8_t event_code, const void *data,
unsigned int len)
{
struct hci_encrypt_key_refresh evt;
const struct ble_hci_ev_enc_key_refresh *ev = data;
if (len < BLE_HCI_EVENT_ENC_KEY_REFRESH_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.status = data[2];
evt.connection_handle = get_le16(data + 3);
ble_sm_enc_key_refresh_rx(&evt);
ble_sm_enc_key_refresh_rx(ev);
return 0;
}
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, const void *data,
unsigned int len)
{
const struct ble_hci_ev_num_comp_pkts *ev = data;
struct ble_hs_conn *conn;
uint16_t num_pkts;
uint16_t handle;
uint8_t num_handles;
int off;
int i;
if (len < BLE_HCI_EVENT_HDR_LEN + BLE_HCI_EVENT_NUM_COMP_PKTS_HDR_LEN) {
if (len != sizeof(*ev) + (ev->count * sizeof(ev->completed[0]))) {
return BLE_HS_ECONTROLLER;
}
off = BLE_HCI_EVENT_HDR_LEN;
num_handles = data[off];
if (len < BLE_HCI_EVENT_NUM_COMP_PKTS_HDR_LEN +
num_handles * BLE_HCI_EVENT_NUM_COMP_PKTS_ENT_LEN) {
return BLE_HS_ECONTROLLER;
}
off++;
for (i = 0; i < num_handles; i++) {
handle = get_le16(data + off);
num_pkts = get_le16(data + off + 2);
off += (2 * sizeof(uint16_t));
for (i = 0; i < ev->count; i++) {
num_pkts = le16toh(ev->completed[i].packets);
if (num_pkts > 0) {
ble_hs_lock();
conn = ble_hs_conn_find(handle);
conn = ble_hs_conn_find(le16toh(ev->completed[i].handle));
if (conn != NULL) {
if (conn->bhc_outstanding_pkts < num_pkts) {
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
@@ -264,75 +246,96 @@ ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, uint8_t *data,
}
static int
ble_hs_hci_evt_le_meta(uint8_t event_code, uint8_t *data, int len)
ble_hs_hci_evt_le_meta(uint8_t event_code, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_meta *ev = data;
ble_hs_hci_evt_le_fn *fn;
uint8_t subevent;
int rc;
if (len < BLE_HCI_EVENT_HDR_LEN + BLE_HCI_LE_MIN_LEN) {
if (len < sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
subevent = data[2];
fn = ble_hs_hci_evt_le_dispatch_find(subevent);
fn = ble_hs_hci_evt_le_dispatch_find(ev->subevent);
if (fn) {
rc = fn(subevent, data + BLE_HCI_EVENT_HDR_LEN,
len - BLE_HCI_EVENT_HDR_LEN);
if (rc != 0) {
return rc;
}
return fn(ev->subevent, data, len);
}
return 0;
}
#if MYNEWT_VAL(BLE_EXT_ADV)
static struct hci_le_conn_complete pend_conn_complete;
static struct ble_gap_conn_complete pend_conn_complete;
#endif
static int
ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data,
unsigned int len)
{
struct hci_le_conn_complete evt;
int extended_offset = 0;
const struct ble_hci_ev_le_subev_enh_conn_complete *ev = data;
struct ble_gap_conn_complete evt;
if (len < BLE_HCI_LE_CONN_COMPLETE_LEN) {
return BLE_HS_ECONTROLLER;
}
/* this code processes two different events that are really similar */
if ((subevent == BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE) &&
( len < BLE_HCI_LE_ENH_CONN_COMPLETE_LEN)) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
memset(&evt, 0, sizeof(evt));
evt.subevent_code = data[0];
evt.status = data[1];
evt.status = ev->status;
if (evt.status == BLE_ERR_SUCCESS) {
evt.connection_handle = get_le16(data + 2);
evt.role = data[4];
evt.peer_addr_type = data[5];
memcpy(evt.peer_addr, data + 6, BLE_DEV_ADDR_LEN);
evt.connection_handle = le16toh(ev->conn_handle);
evt.role = ev->role;
evt.peer_addr_type = ev->peer_addr_type;
memcpy(evt.peer_addr, ev->peer_addr, BLE_DEV_ADDR_LEN);
memcpy(evt.local_rpa, ev->local_rpa, BLE_DEV_ADDR_LEN);
memcpy(evt.peer_rpa,ev->peer_rpa, BLE_DEV_ADDR_LEN);
evt.conn_itvl = le16toh(ev->conn_itvl);
evt.conn_latency = le16toh(ev->conn_latency);
evt.supervision_timeout = le16toh(ev->supervision_timeout);
evt.master_clk_acc = ev->mca;
} else {
#if MYNEWT_VAL(BLE_HS_DEBUG)
evt.connection_handle = BLE_HS_CONN_HANDLE_NONE;
#endif
}
/* enhanced connection event has the same information with these
* extra fields stuffed into the middle */
if (subevent == BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE) {
memcpy(evt.local_rpa, data + 12, BLE_DEV_ADDR_LEN);
memcpy(evt.peer_rpa, data + 18, BLE_DEV_ADDR_LEN);
extended_offset = 12;
} else {
memset(evt.local_rpa, 0, BLE_DEV_ADDR_LEN);
memset(evt.peer_rpa, 0, BLE_DEV_ADDR_LEN);
}
#if MYNEWT_VAL(BLE_EXT_ADV)
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 */
memcpy(&pend_conn_complete, &evt, sizeof(evt));
return 0;
}
#endif
return ble_gap_rx_conn_complete(&evt, 0);
evt.conn_itvl = get_le16(data + 12 + extended_offset);
evt.conn_latency = get_le16(data + 14 + extended_offset);
evt.supervision_timeout = get_le16(data + 16 + extended_offset);
evt.master_clk_acc = data[18 + extended_offset];
}
static int
ble_hs_hci_evt_le_conn_complete(uint8_t subevent, const void *data,
unsigned int len)
{
const struct ble_hci_ev_le_subev_conn_complete *ev = data;
struct ble_gap_conn_complete evt;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
memset(&evt, 0, sizeof(evt));
evt.status = ev->status;
if (evt.status == BLE_ERR_SUCCESS) {
evt.connection_handle = le16toh(ev->conn_handle);
evt.role = ev->role;
evt.peer_addr_type = ev->peer_addr_type;
memcpy(evt.peer_addr, ev->peer_addr, BLE_DEV_ADDR_LEN);
evt.conn_itvl = le16toh(ev->conn_itvl);
evt.conn_latency = le16toh(ev->conn_latency);
evt.supervision_timeout = le16toh(ev->supervision_timeout);
evt.master_clk_acc = ev->mca;
} else {
#if MYNEWT_VAL(BLE_HS_DEBUG)
evt.connection_handle = BLE_HS_CONN_HANDLE_NONE;
@@ -351,39 +354,45 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
}
static int
ble_hs_hci_evt_le_adv_rpt_first_pass(uint8_t *data, int len)
ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len)
{
uint8_t num_reports;
int off;
const struct ble_hci_ev_le_subev_adv_rpt *ev = data;
const struct adv_report *rpt;
int i;
if (len < BLE_HCI_LE_ADV_RPT_MIN_LEN) {
if (len < sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
num_reports = data[1];
if (num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
len -= sizeof(*ev);
data += sizeof(*ev);
if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
return BLE_HS_EBADDATA;
}
off = 2; /* Subevent code and num reports. */
for (i = 0; i < num_reports; i++) {
/* Move past event type (1), address type (1) and address (6) */
off += 8;
/* Add advertising data length (N), length (1) and rssi (1) */
off += data[off];
off += 2;
/* Make sure we are not past length */
if (off > len) {
for (i = 0; i < ev->num_reports; i++) {
/* extra byte for RSSI after adv data */
if (len < sizeof(*rpt) + 1) {
return BLE_HS_ECONTROLLER;
}
rpt = data;
len -= sizeof(*rpt) + 1;
data += sizeof(rpt) + 1;
if (rpt->data_len > len) {
return BLE_HS_ECONTROLLER;
}
len -= rpt->data_len;
data += rpt->data_len;
}
/* Make sure length was correct */
if (off != len) {
if (len) {
return BLE_HS_ECONTROLLER;
}
@@ -391,11 +400,11 @@ ble_hs_hci_evt_le_adv_rpt_first_pass(uint8_t *data, int len)
}
static int
ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_adv_rpt *ev = data;
struct ble_gap_disc_desc desc = {0};
uint8_t num_reports;
int off;
const struct adv_report *rpt;
int rc;
int i;
@@ -405,28 +414,21 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
return rc;
}
data += sizeof(*ev);
desc.direct_addr = *BLE_ADDR_ANY;
off = 2; /* skip sub-event and num reports */
num_reports = data[1];
for (i = 0; i < num_reports; i++) {
desc.event_type = data[off];
++off;
for (i = 0; i < ev->num_reports; i++) {
rpt = data;
desc.addr.type = data[off];
++off;
data += sizeof(rpt) + rpt->data_len + 1;
memcpy(desc.addr.val, data + off, 6);
off += 6;
desc.length_data = data[off];
++off;
desc.data = data + off;
off += desc.length_data;
desc.rssi = data[off];
++off;
desc.event_type = rpt->type;
desc.addr.type = rpt->addr_type;
memcpy(desc.addr.val, rpt->addr, BLE_DEV_ADDR_LEN);
desc.length_data = rpt->data_len;
desc.data = rpt->data;
desc.rssi = rpt->data[rpt->data_len];
ble_gap_rx_adv_report(&desc);
}
@@ -435,20 +437,13 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
}
static int
ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_direct_adv_rpt *ev = data;
struct ble_gap_disc_desc desc = {0};
uint8_t num_reports;
int suboff;
int off;
int i;
if (len < BLE_HCI_LE_ADV_DIRECT_RPT_LEN) {
return BLE_HS_ECONTROLLER;
}
num_reports = data[1];
if (len != 2 + num_reports * BLE_HCI_LE_ADV_DIRECT_RPT_SUB_LEN) {
if (len < sizeof(*ev) || len != ev->num_reports * sizeof(ev->reports[0])) {
return BLE_HS_ECONTROLLER;
}
@@ -456,32 +451,13 @@ ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
desc.data = NULL;
desc.length_data = 0;
for (i = 0; i < num_reports; i++) {
suboff = 0;
off = 2 + suboff * num_reports + i;
desc.event_type = data[off];
suboff++;
off = 2 + suboff * num_reports + i;
desc.addr.type = data[off];
suboff++;
off = 2 + suboff * num_reports + i * 6;
memcpy(desc.addr.val, data + off, 6);
suboff += 6;
off = 2 + suboff * num_reports + i;
desc.direct_addr.type = data[off];
suboff++;
off = 2 + suboff * num_reports + i * 6;
memcpy(desc.direct_addr.val, data + off, 6);
suboff += 6;
off = 2 + suboff * num_reports + i;
desc.rssi = data[off];
suboff++;
for (i = 0; i < ev->num_reports; i++) {
desc.event_type = ev->reports[i].type;
desc.addr.type = ev->reports[i].addr_type;
memcpy(desc.addr.val, ev->reports[i].addr, BLE_DEV_ADDR_LEN);
desc.direct_addr.type = ev->reports[i].dir_addr_type;
memcpy(desc.direct_addr.val, ev->reports[i].dir_addr, BLE_DEV_ADDR_LEN);
desc.rssi = ev->reports[i].rssi;
ble_gap_rx_adv_report(&desc);
}
@@ -490,22 +466,16 @@ 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, const void *data,
unsigned int len)
{
struct hci_le_rd_rem_supp_feat_complete evt;
const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev = data;
if (len < BLE_HCI_LE_RD_REM_USED_FEAT_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.status = data[1];
evt.connection_handle = get_le16(data + 2);
memcpy(evt.features, data + 4, 8);
ble_gap_rx_rd_rem_sup_feat_complete(&evt);
ble_gap_rx_rd_rem_sup_feat_complete(ev);
return 0;
}
@@ -532,47 +502,42 @@ ble_hs_hci_decode_legacy_type(uint16_t evt_type)
#endif
static int
ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV)
const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data;
const struct ext_adv_report *report;
struct ble_gap_ext_disc_desc desc;
struct hci_ext_adv_report *ext_adv;
struct hci_ext_adv_report_param *params;
int num_reports;
int i;
int legacy_event_type;
if (len < sizeof(*ext_adv)) {
if (len < sizeof(*ev)) {
return BLE_HS_EBADDATA;
}
ext_adv = (struct hci_ext_adv_report *) data;
num_reports = ext_adv->num_reports;
if (num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
return BLE_HS_EBADDATA;
}
if (len < (sizeof(*ext_adv) + ext_adv->num_reports * sizeof(*params))) {
return BLE_HS_ECONTROLLER;
}
/* TODO properly validate len of the event */
params = &ext_adv->params[0];
for (i = 0; i < num_reports; i++) {
report = &ev->reports[0];
for (i = 0; i < ev->num_reports; i++) {
memset(&desc, 0, sizeof(desc));
desc.props = (params->evt_type) & 0x1F;
desc.props = (report->evt_type) & 0x1F;
if (desc.props & BLE_HCI_ADV_LEGACY_MASK) {
legacy_event_type = ble_hs_hci_decode_legacy_type(params->evt_type);
legacy_event_type = ble_hs_hci_decode_legacy_type(report->evt_type);
if (legacy_event_type < 0) {
params += 1;
report = (const void *) &report->data[report->data_len];
continue;
}
desc.legacy_event_type = legacy_event_type;
desc.data_status = BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE;
} else {
switch(params->evt_type & BLE_HCI_ADV_DATA_STATUS_MASK) {
switch(report->evt_type & BLE_HCI_ADV_DATA_STATUS_MASK) {
case BLE_HCI_ADV_DATA_STATUS_COMPLETE:
desc.data_status = BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE;
break;
@@ -586,82 +551,73 @@ ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, uint8_t *data, int len)
assert(false);
}
}
desc.addr.type = params->addr_type;
memcpy(desc.addr.val, params->addr, 6);
desc.length_data = params->adv_data_len;
desc.data = params->adv_data;
desc.rssi = params->rssi;
desc.tx_power = params->tx_power;
memcpy(desc.direct_addr.val, params->dir_addr, 6);
desc.direct_addr.type = params->dir_addr_type;
desc.sid = params->sid;
desc.prim_phy = params->prim_phy;
desc.sec_phy = params->sec_phy;
desc.periodic_adv_itvl = params->per_adv_itvl;
desc.addr.type = report->addr_type;
memcpy(desc.addr.val, report->addr, 6);
desc.length_data = report->data_len;
desc.data = report->data;
desc.rssi = report->rssi;
desc.tx_power = report->tx_power;
memcpy(desc.direct_addr.val, report->dir_addr, 6);
desc.direct_addr.type = report->dir_addr_type;
desc.sid = report->sid;
desc.prim_phy = report->pri_phy;
desc.sec_phy = report->sec_phy;
desc.periodic_adv_itvl = report->periodic_itvl;
ble_gap_rx_ext_adv_report(&desc);
params += 1;
report = (const void *) &report->data[report->data_len];
}
#endif
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_sync_estab(uint8_t subevent, uint8_t *data,
int len)
ble_hs_hci_evt_le_periodic_adv_sync_estab(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
struct hci_le_subev_periodic_adv_sync_estab evt;
const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev = data;
if (len < BLE_HCI_LE_PERIODIC_ADV_SYNC_ESTAB_LEN) {
if (len != sizeof(*ev)) {
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);
ble_gap_rx_peroidic_adv_sync_estab(ev);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_rpt(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_periodic_adv_rpt(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
struct hci_le_subev_periodic_adv_rpt* evt;
const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev = data;
if (len < BLE_HCI_LE_PERIODIC_ADV_RPT_LEN) {
if (len < sizeof(*ev) || len != (sizeof(*ev) + ev->data_len)) {
return BLE_HS_EBADDATA;
}
evt = (struct hci_le_subev_periodic_adv_rpt *)(data + 1);
ble_gap_rx_periodic_adv_rpt(evt);
ble_gap_rx_periodic_adv_rpt(ev);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_periodic_adv_sync_lost(uint8_t subevent, uint8_t *data,
int len)
ble_hs_hci_evt_le_periodic_adv_sync_lost(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
struct hci_le_subev_periodic_adv_sync_lost evt;
const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev = data;
if (len < BLE_HCI_LE_PERIODIC_ADV_SYNC_LOST_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_EBADDATA;
}
evt.sync_handle = get_le16(data + 1);
ble_gap_rx_periodic_adv_sync_lost(&evt);
ble_gap_rx_periodic_adv_sync_lost(ev);
#endif
return 0;
@@ -669,204 +625,157 @@ ble_hs_hci_evt_le_periodic_adv_sync_lost(uint8_t subevent, uint8_t *data,
static int
ble_hs_hci_evt_le_scan_timeout(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_scan_timeout(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
ble_gap_rx_le_scan_timeout();
const struct ble_hci_ev_le_subev_scan_timeout *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_EBADDATA;
}
ble_gap_rx_le_scan_timeout();
#endif
return 0;
return 0;
}
static int
ble_hs_hci_evt_le_adv_set_terminated(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_adv_set_terminated(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV)
struct hci_le_adv_set_terminated evt;
const struct ble_hci_ev_le_subev_adv_set_terminated *ev = data;
if (len < BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.status = data[1];
evt.adv_handle = data[2];
evt.conn_handle = get_le16(data + 3);
evt.completed_events = data[5];
if (evt.status == 0) {
if (ev->status == 0) {
/* ignore return code as we need to terminate advertising set anyway */
ble_gap_rx_conn_complete(&pend_conn_complete, evt.adv_handle);
ble_gap_rx_conn_complete(&pend_conn_complete, ev->adv_handle);
}
ble_gap_rx_adv_set_terminated(&evt);
ble_gap_rx_adv_set_terminated(ev);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_scan_req_rcvd(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_scan_req_rcvd(uint8_t subevent, const void *data,
unsigned int len)
{
#if MYNEWT_VAL(BLE_EXT_ADV)
struct hci_le_scan_req_rcvd evt;
const struct ble_hci_ev_le_subev_scan_req_rcvd *ev = data;
if (len != BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.adv_handle = data[1];
evt.scan_addr_type = data[2];
memcpy(evt.scan_addr, data + 3, 6);
ble_gap_rx_scan_req_rcvd(&evt);
ble_gap_rx_scan_req_rcvd(ev);
#endif
return 0;
}
static int
ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, const void *data,
unsigned int len)
{
struct hci_le_conn_upd_complete evt;
const struct ble_hci_ev_le_subev_conn_upd_complete *ev = data;
if (len < BLE_HCI_LE_CONN_UPD_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.status = data[1];
evt.connection_handle = get_le16(data + 2);
evt.conn_itvl = get_le16(data + 4);
evt.conn_latency = get_le16(data + 6);
evt.supervision_timeout = get_le16(data + 8);
if (ev->status == 0) {
BLE_HS_DBG_ASSERT(le16toh(ev->conn_itvl) > BLE_HCI_CONN_ITVL_MIN);
BLE_HS_DBG_ASSERT(le16toh(ev->conn_itvl) < BLE_HCI_CONN_ITVL_MAX);
if (evt.status == 0) {
if (evt.conn_itvl < BLE_HCI_CONN_ITVL_MIN ||
evt.conn_itvl > BLE_HCI_CONN_ITVL_MAX) {
BLE_HS_DBG_ASSERT(le16toh(ev->conn_latency) > BLE_HCI_CONN_LATENCY_MIN);
BLE_HS_DBG_ASSERT(le16toh(ev->conn_latency) < BLE_HCI_CONN_LATENCY_MAX);
return BLE_HS_EBADDATA;
}
if (evt.conn_latency < BLE_HCI_CONN_LATENCY_MIN ||
evt.conn_latency > BLE_HCI_CONN_LATENCY_MAX) {
return BLE_HS_EBADDATA;
}
if (evt.supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN ||
evt.supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX) {
return BLE_HS_EBADDATA;
}
BLE_HS_DBG_ASSERT(le16toh(ev->supervision_timeout) > BLE_HCI_CONN_SPVN_TIMEOUT_MIN);
BLE_HS_DBG_ASSERT(le16toh(ev->supervision_timeout) < BLE_HCI_CONN_SPVN_TIMEOUT_MAX);
}
ble_gap_rx_update_complete(&evt);
ble_gap_rx_update_complete(ev);
return 0;
}
static int
ble_hs_hci_evt_le_lt_key_req(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_lt_key_req(uint8_t subevent, const void *data, unsigned int len)
{
struct hci_le_lt_key_req evt;
const struct ble_hci_ev_le_subev_lt_key_req *ev = data;
if (len < BLE_HCI_LE_LT_KEY_REQ_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.connection_handle = get_le16(data + 1);
evt.random_number = get_le64(data + 3);
evt.encrypted_diversifier = get_le16(data + 11);
ble_sm_ltk_req_rx(&evt);
ble_sm_ltk_req_rx(ev);
return 0;
}
static int
ble_hs_hci_evt_le_conn_parm_req(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_conn_parm_req(uint8_t subevent, const void *data, unsigned int len)
{
struct hci_le_conn_param_req evt;
const struct ble_hci_ev_le_subev_rem_conn_param_req *ev = data;
if (len < BLE_HCI_LE_REM_CONN_PARM_REQ_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.connection_handle = get_le16(data + 1);
evt.itvl_min = get_le16(data + 3);
evt.itvl_max = get_le16(data + 5);
evt.latency = get_le16(data + 7);
evt.timeout = get_le16(data + 9);
BLE_HS_DBG_ASSERT(le16toh(ev->min_interval) > BLE_HCI_CONN_ITVL_MIN);
BLE_HS_DBG_ASSERT(le16toh(ev->max_interval) < BLE_HCI_CONN_ITVL_MAX);
BLE_HS_DBG_ASSERT(le16toh(ev->max_interval) >= le16toh(ev->min_interval));
if (evt.itvl_min < BLE_HCI_CONN_ITVL_MIN ||
evt.itvl_max > BLE_HCI_CONN_ITVL_MAX ||
evt.itvl_min > evt.itvl_max) {
BLE_HS_DBG_ASSERT(le16toh(ev->latency) > BLE_HCI_CONN_LATENCY_MIN);
BLE_HS_DBG_ASSERT(le16toh(ev->latency) < BLE_HCI_CONN_LATENCY_MAX);
return BLE_HS_EBADDATA;
}
if (evt.latency < BLE_HCI_CONN_LATENCY_MIN ||
evt.latency > BLE_HCI_CONN_LATENCY_MAX) {
BLE_HS_DBG_ASSERT(le16toh(ev->timeout) > BLE_HCI_CONN_SPVN_TIMEOUT_MIN);
BLE_HS_DBG_ASSERT(le16toh(ev->timeout) < BLE_HCI_CONN_SPVN_TIMEOUT_MAX);
return BLE_HS_EBADDATA;
}
if (evt.timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN ||
evt.timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX) {
return BLE_HS_EBADDATA;
}
ble_gap_rx_param_req(&evt);
ble_gap_rx_param_req(ev);
return 0;
}
static int
ble_hs_hci_evt_le_phy_update_complete(uint8_t subevent, uint8_t *data, int len)
ble_hs_hci_evt_le_phy_update_complete(uint8_t subevent, const void *data,
unsigned int len)
{
struct hci_le_phy_upd_complete evt;
const struct ble_hci_ev_le_subev_phy_update_complete *ev = data;
if (len < BLE_HCI_LE_PHY_UPD_LEN) {
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
evt.subevent_code = data[0];
evt.status = data[1];
evt.connection_handle = get_le16(data + 2);
evt.tx_phy = data[4];
evt.rx_phy = data[5];
ble_gap_rx_phy_update_complete(&evt);
ble_gap_rx_phy_update_complete(ev);
return 0;
}
int
ble_hs_hci_evt_process(uint8_t *data)
ble_hs_hci_evt_process(const struct ble_hci_ev *ev)
{
const struct ble_hs_hci_evt_dispatch_entry *entry;
uint8_t event_code;
uint8_t param_len;
int event_len;
int rc;
/* Count events received */
STATS_INC(ble_hs_stats, hci_event);
/* Process the event */
event_code = data[0];
param_len = data[1];
event_len = param_len + 2;
entry = ble_hs_hci_evt_dispatch_find(event_code);
entry = ble_hs_hci_evt_dispatch_find(ev->opcode);
if (entry == NULL) {
STATS_INC(ble_hs_stats, hci_unknown_event);
rc = BLE_HS_ENOTSUP;
} else {
rc = entry->cb(event_code, data, event_len);
rc = entry->cb(ev->opcode, ev->data, ev->length);
}
ble_hci_trans_buf_free(data);
ble_hci_trans_buf_free((uint8_t *) ev);
return rc;
}
+5 -209
View File
@@ -48,7 +48,7 @@ struct os_mbuf;
struct ble_hs_hci_ack {
int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */
uint8_t *bha_params;
const uint8_t *bha_params;
int bha_params_len;
uint16_t bha_opcode;
uint8_t bha_hci_handle;
@@ -81,11 +81,8 @@ struct hci_periodic_adv_params
extern uint16_t ble_hs_hci_avail_pkts;
int ble_hs_hci_cmd_tx(uint16_t opcode, void *cmd, uint8_t cmd_len,
void *evt_buf, uint8_t evt_buf_len,
uint8_t *out_evt_buf_len);
int ble_hs_hci_cmd_tx_empty_ack(uint16_t opcode, void *cmd, uint8_t cmd_len);
void ble_hs_hci_rx_ack(uint8_t *ack_ev);
int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len,
void *rsp, uint8_t rsp_len);
void ble_hs_hci_init(void);
void ble_hs_hci_set_le_supported_feat(uint32_t feat);
@@ -106,74 +103,9 @@ int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
uint16_t tx_time);
int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
struct hci_data_hdr *out_hdr);
int ble_hs_hci_evt_process(uint8_t *data);
int ble_hs_hci_evt_process(const struct ble_hci_ev *ev);
void ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint16_t ocf, uint8_t len,
void *buf);
int ble_hs_hci_cmd_send_buf(uint16_t opcode, void *buf, uint8_t buf_len);
void ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask,
uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask, uint8_t *dst,
int dst_len);
void ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst,
int dst_len);
void ble_hs_hci_cmd_build_le_set_host_chan_class(const uint8_t *chan_map,
uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_le_read_chan_map(uint16_t conn_handle,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t *data, uint8_t len,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params *adv,
uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_le_read_buffer_size(void);
void ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst,
int dst_len);
int ble_hs_hci_cmd_le_set_adv_enable(uint8_t enable);
int ble_hs_hci_cmd_build_le_set_scan_params(uint8_t scan_type,
uint16_t scan_itvl,
uint16_t scan_window,
uint8_t own_addr_type,
uint8_t filter_policy,
uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable,
uint8_t filter_dups,
uint8_t *dst, uint8_t dst_len);
int ble_hs_hci_cmd_le_set_scan_enable(uint8_t enable, uint8_t filter_dups);
int ble_hs_hci_cmd_build_le_create_connection(
const struct hci_create_conn *hcc, uint8_t *cmd, int cmd_len);
int ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t *addr,
uint8_t addr_type,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_reset(void);
int ble_hs_hci_cmd_tx_set_ctlr_to_host_fc(uint8_t fc_enable);
int ble_hs_hci_cmd_tx_host_buf_size(const struct hci_host_buf_size *cmd);
int ble_hs_hci_cmd_build_host_num_comp_pkts_entry(
const struct hci_host_num_comp_pkts_entry *entry,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_read_adv_pwr(void);
int ble_hs_hci_cmd_le_create_conn_cancel(void);
int ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update *hcu,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update *hcu);
void ble_hs_hci_cmd_build_le_lt_key_req_reply(
const struct hci_lt_key_req_reply *hkr, uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,
uint8_t *dst, int dst_len);
void ble_hs_hci_cmd_build_le_conn_param_reply(
const struct hci_conn_param_reply *hcr, uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply *hcr);
void ble_hs_hci_cmd_build_le_conn_param_neg_reply(
const struct hci_conn_param_neg_reply *hcn, uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_le_conn_param_neg_reply(
const struct hci_conn_param_neg_reply *hcn);
void ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt *cmd,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len);
int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts);
void ble_hs_hci_add_avail_pkts(uint16_t delta);
@@ -183,145 +115,9 @@ uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb,
int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om);
int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om);
int ble_hs_hci_cmd_build_set_data_len(uint16_t connection_handle,
uint16_t tx_octets, uint16_t tx_time,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_add_to_resolv_list(
const struct hci_add_dev_to_resolving_list *padd,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_remove_from_resolv_list(
uint8_t addr_type, const uint8_t *addr, uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_read_peer_resolv_addr(
uint8_t peer_identity_addr_type, const uint8_t *peer_identity_addr,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_read_lcl_resolv_addr(
uint8_t local_identity_addr_type, const uint8_t *local_identity_addr,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_set_addr_res_en(
uint8_t enable, uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(
uint16_t timeout, uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr,
uint8_t *dst, int dst_len);
#if MYNEWT_VAL(BLE_EXT_ADV)
int ble_hs_hci_cmd_build_le_set_ext_scan_params(uint8_t own_addr_type,
uint8_t filter_policy,
uint8_t phy_mask,
uint8_t phy_count,
struct ble_hs_hci_ext_scan_param *params[],
uint8_t *dst, uint16_t dst_len);
int ble_hs_hci_cmd_build_le_set_ext_scan_enable(uint8_t enable,
uint8_t filter_dups,
uint16_t duration,
uint16_t period,
uint8_t *dst, uint16_t dst_len);
int ble_hs_hci_cmd_build_le_ext_create_conn(const struct hci_ext_create_conn *hcc,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle,
const uint8_t *addr,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation,
uint8_t frag_pref, struct os_mbuf *data,
uint8_t data_len,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_ext_adv_enable(uint8_t enable, uint8_t sets_num,
const struct hci_ext_adv_set *sets,
uint8_t *cmd, int cmd_len);
int
ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,
const struct hci_ext_adv_params *params,
uint8_t *cmd, int cmd_len);
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,
uint8_t mod_idx,
uint8_t *dst, uint16_t dst_len);
int ble_hs_hci_cmd_build_le_enh_trans_test(uint8_t tx_chan,
uint8_t test_data_len,
uint8_t packet_payload_idx,
uint8_t phy,
uint8_t *dst, uint16_t dst_len);
int ble_hs_hci_cmd_build_le_set_priv_mode(const uint8_t *addr, uint8_t addr_type,
uint8_t priv_mode, uint8_t *dst,
uint16_t dst_len);
int ble_hs_hci_cmd_build_le_read_phy(uint16_t conn_handle, uint8_t *dst,
int dst_len);
int ble_hs_hci_cmd_build_le_set_default_phy(uint8_t tx_phys_mask,
uint8_t rx_phys_mask,
uint8_t *dst, int dst_len);
int ble_hs_hci_cmd_build_le_set_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
uint8_t rx_phys_mask, uint16_t phy_opts,
uint8_t *dst, int dst_len);
int ble_hs_hci_frag_num_mbufs(void);
int ble_hs_hci_frag_num_mbufs_free(void);
#if MYNEWT_VAL(BLE_EXT_ADV)
#endif
int ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle, uint8_t *dst,
int dst_len);
#ifdef __cplusplus
}
#endif
+51 -83
View File
@@ -37,18 +37,19 @@ ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc)
int
ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
{
uint8_t params_len;
struct ble_hci_le_rd_adv_chan_txpwr_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
NULL, 0,out_tx_pwr, 1, &params_len);
NULL, 0, &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (params_len != 1 ||
*out_tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
*out_tx_pwr = rsp.power_level;
if (*out_tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
*out_tx_pwr > BLE_HCI_ADV_CHAN_TXPWR_MAX) {
BLE_HS_LOG(WARN, "advertiser txpwr out of range\n");
}
@@ -59,8 +60,7 @@ ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
int
ble_hs_hci_util_rand(void *dst, int len)
{
uint8_t rsp_buf[BLE_HCI_LE_RAND_LEN];
uint8_t params_len;
struct ble_hci_le_rand_rp rsp;
uint8_t *u8ptr;
int chunk_sz;
int rc;
@@ -68,16 +68,13 @@ ble_hs_hci_util_rand(void *dst, int len)
u8ptr = dst;
while (len > 0) {
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND),
NULL, 0, rsp_buf, sizeof rsp_buf, &params_len);
NULL, 0, &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (params_len != sizeof rsp_buf) {
return BLE_HS_ECONTROLLER;
}
chunk_sz = min(len, sizeof rsp_buf);
memcpy(u8ptr, rsp_buf, chunk_sz);
chunk_sz = min(len, sizeof(rsp));
memcpy(u8ptr, &rsp.random_number, chunk_sz);
len -= chunk_sz;
u8ptr += chunk_sz;
@@ -89,30 +86,25 @@ ble_hs_hci_util_rand(void *dst, int len)
int
ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
{
uint8_t buf[BLE_HCI_READ_RSSI_LEN];
uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN];
uint16_t params_conn_handle;
uint8_t params_len;
struct ble_hci_rd_rssi_cp cmd;
struct ble_hci_rd_rssi_rp rsp;
int rc;
ble_hs_hci_cmd_build_read_rssi(conn_handle, buf, sizeof buf);
cmd.handle = htole16(conn_handle);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_STATUS_PARAMS,
BLE_HCI_OCF_RD_RSSI), buf, sizeof(buf),
params, sizeof(params), &params_len);
BLE_HCI_OCF_RD_RSSI), &cmd, sizeof(cmd),
&rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (params_len != BLE_HCI_READ_RSSI_ACK_PARAM_LEN) {
if (le16toh(rsp.handle) != conn_handle) {
return BLE_HS_ECONTROLLER;
}
params_conn_handle = get_le16(params + 0);
if (params_conn_handle != conn_handle) {
return BLE_HS_ECONTROLLER;
}
*out_rssi = params[2];
*out_rssi = rsp.rssi;
return 0;
}
@@ -120,57 +112,45 @@ ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
int
ble_hs_hci_util_set_random_addr(const uint8_t *addr)
{
uint8_t buf[BLE_HCI_SET_RAND_ADDR_LEN];
int rc;
struct ble_hci_le_set_rand_addr_cp cmd;
/* set the address in the controller */
memcpy(cmd.addr, addr, BLE_DEV_ADDR_LEN);
rc = ble_hs_hci_cmd_build_set_random_addr(addr, 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_RAND_ADDR),
buf, BLE_HCI_SET_RAND_ADDR_LEN);
if (rc != 0) {
return rc;
}
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_RAND_ADDR),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
uint16_t tx_time)
{
uint8_t buf[BLE_HCI_SET_DATALEN_LEN];
uint8_t params[BLE_HCI_SET_DATALEN_ACK_PARAM_LEN];
uint16_t params_conn_handle;
uint8_t params_len;
struct ble_hci_le_set_data_len_cp cmd;
struct ble_hci_le_set_data_len_rp rsp;
int rc;
rc = ble_hs_hci_cmd_build_set_data_len(conn_handle, tx_octets, tx_time,
buf, sizeof buf);
if (rc != 0) {
return BLE_HS_HCI_ERR(rc);
if (tx_octets < BLE_HCI_SET_DATALEN_TX_OCTETS_MIN ||
tx_octets > BLE_HCI_SET_DATALEN_TX_OCTETS_MAX) {
return BLE_HS_EINVAL;
}
if (tx_time < BLE_HCI_SET_DATALEN_TX_TIME_MIN ||
tx_time > BLE_HCI_SET_DATALEN_TX_TIME_MAX) {
return BLE_HS_EINVAL;
}
cmd.conn_handle = htole16(conn_handle);
cmd.tx_octets = htole16(tx_octets);
cmd.tx_time = htole16(tx_time);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_DATA_LEN),
buf, sizeof(buf), params,
BLE_HCI_SET_DATALEN_ACK_PARAM_LEN, &params_len);
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (params_len != BLE_HCI_SET_DATALEN_ACK_PARAM_LEN) {
return BLE_HS_ECONTROLLER;
}
params_conn_handle = get_le16(params + 0);
if (params_conn_handle != conn_handle) {
if (le16toh(rsp.conn_handle) != conn_handle) {
return BLE_HS_ECONTROLLER;
}
@@ -200,31 +180,24 @@ ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
int
ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map)
{
uint8_t buf[BLE_HCI_RD_CHANMAP_LEN];
uint8_t params[BLE_HCI_RD_CHANMAP_RSP_LEN];
uint16_t params_conn_handle;
uint8_t params_len;
struct ble_hci_le_rd_chan_map_cp cmd;
struct ble_hci_le_rd_chan_map_rp rsp;
int rc;
ble_hs_hci_cmd_build_le_read_chan_map(conn_handle, buf, sizeof buf);
cmd.conn_handle = htole16(conn_handle);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_CHAN_MAP),
buf, sizeof(buf), params, BLE_HCI_RD_CHANMAP_RSP_LEN,
&params_len);
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (params_len != BLE_HCI_RD_CHANMAP_RSP_LEN) {
if (le16toh(rsp.conn_handle) != conn_handle) {
return BLE_HS_ECONTROLLER;
}
params_conn_handle = get_le16(params + 0);
if (params_conn_handle != conn_handle) {
return BLE_HS_ECONTROLLER;
}
memcpy(out_chan_map, params + 2, 5);
memcpy(out_chan_map, rsp.chan_map, 5);
return 0;
}
@@ -232,16 +205,11 @@ ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map)
int
ble_hs_hci_set_chan_class(const uint8_t *chan_map)
{
uint8_t buf[BLE_HCI_SET_HOST_CHAN_CLASS_LEN];
int rc;
struct ble_hci_le_set_host_chan_class_cp cmd;
ble_hs_hci_cmd_build_le_set_host_chan_class(chan_map, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
buf, sizeof(buf));
if (rc != 0) {
return rc;
}
memcpy(cmd.chan_map, chan_map, sizeof(cmd.chan_map));
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
&cmd, sizeof(cmd), NULL, 0);
}
+39 -63
View File
@@ -34,105 +34,80 @@ const uint8_t ble_hs_pvcy_default_irk[16] = {
static int
ble_hs_pvcy_set_addr_timeout(uint16_t timeout)
{
uint8_t buf[BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN];
int rc;
struct ble_hci_le_set_rpa_tmo_cp cmd;
rc = ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(timeout, buf,
sizeof(buf));
if (rc != 0) {
return rc;
if (timeout == 0 || timeout > 0xA1B8) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.rpa_timeout = htole16(timeout);
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_RPA_TMO),
buf, sizeof(buf), NULL, 0, NULL);
&cmd, sizeof(cmd), NULL, 0);
}
static int
ble_hs_pvcy_set_resolve_enabled(int enable)
{
uint8_t buf[BLE_HCI_SET_ADDR_RESOL_ENA_LEN];
int rc;
struct ble_hci_le_set_addr_res_en_cp cmd;
rc = ble_hs_hci_cmd_build_set_addr_res_en(enable, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
cmd.enable = enable;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
buf, sizeof(buf), NULL, 0, NULL);
if (rc != 0) {
return rc;
}
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_pvcy_remove_entry(uint8_t addr_type, const uint8_t *addr)
{
uint8_t buf[BLE_HCI_RMV_FROM_RESOLV_LIST_LEN];
int rc;
struct ble_hci_le_rmv_resolve_list_cp cmd;
rc = ble_hs_hci_cmd_build_remove_from_resolv_list(addr_type, addr,
buf, sizeof(buf));
if (rc != 0) {
return rc;
if (addr_type > BLE_ADDR_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RMV_RESOLV_LIST),
buf, sizeof(buf), NULL, 0, NULL);
if (rc != 0) {
return rc;
}
cmd.peer_addr_type = addr_type;
memcpy(cmd.peer_id_addr, addr, BLE_DEV_ADDR_LEN);
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RMV_RESOLV_LIST),
&cmd, sizeof(cmd), NULL, 0);
}
static int
ble_hs_pvcy_clear_entries(void)
{
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
NULL, 0, NULL, 0, NULL);
if (rc != 0) {
return rc;
}
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
NULL, 0, NULL, 0);
}
static int
ble_hs_pvcy_add_entry_hci(const uint8_t *addr, uint8_t addr_type,
const uint8_t *irk)
{
struct hci_add_dev_to_resolving_list add;
uint8_t buf[BLE_HCI_ADD_TO_RESOLV_LIST_LEN];
struct ble_hci_le_add_resolv_list_cp cmd;
ble_addr_t peer_addr;
int rc;
add.addr_type = addr_type;
memcpy(add.addr, addr, 6);
memcpy(add.local_irk, ble_hs_pvcy_irk, 16);
memcpy(add.peer_irk, irk, 16);
rc = ble_hs_hci_cmd_build_add_to_resolv_list(&add, buf, sizeof(buf));
if (rc != 0) {
return rc;
if (addr_type > BLE_ADDR_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.peer_addr_type = addr_type;
memcpy(cmd.peer_id_addr, addr, 6);
memcpy(cmd.local_irk, ble_hs_pvcy_irk, 16);
memcpy(cmd.peer_irk, irk, 16);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
buf, sizeof(buf), NULL, 0, NULL);
&cmd, sizeof(cmd), NULL, 0);
if (rc != 0) {
return rc;
}
/* FIXME Controller is BT5.0 and default privacy mode is network which
* can cause problems for apps which are not aware of it. We need to
* sort it out somehow. For now we set device mode for all of the peer
@@ -257,16 +232,17 @@ ble_hs_pvcy_our_irk(const uint8_t **out_irk)
int
ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode)
{
uint8_t buf[BLE_HCI_LE_SET_PRIVACY_MODE_LEN];
int rc;
struct ble_hci_le_set_privacy_mode_cp cmd;
rc = ble_hs_hci_cmd_build_le_set_priv_mode(addr->val, addr->type, priv_mode,
buf, sizeof(buf));
if (rc != 0) {
return rc;
if (addr->type > BLE_ADDR_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.mode = priv_mode;
cmd.peer_id_addr_type = addr->type;
memcpy(cmd.peer_id_addr, addr->val, BLE_DEV_ADDR_LEN);
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_PRIVACY_MODE),
buf, sizeof(buf), NULL, 0, NULL);
&cmd, sizeof(cmd), NULL, 0);
}
+40 -83
View File
@@ -27,26 +27,20 @@
static int
ble_hs_startup_read_sup_f_tx(void)
{
uint8_t ack_params[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN];
uint8_t ack_params_len;
struct ble_hci_ip_rd_loc_supp_feat_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
NULL,0, ack_params, sizeof ack_params,
&ack_params_len);
NULL, 0, &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
/* for now we don't use it outside of init sequence so check this here
* LE Supported (Controller) byte 4, bit 6
*/
if (!(ack_params[4] & 0x60)) {
if (!(rsp.features & 0x0000006000000000)) {
BLE_HS_LOG(ERROR, "Controller doesn't support LE\n");
return BLE_HS_ECONTROLLER;
}
@@ -58,26 +52,18 @@ ble_hs_startup_read_sup_f_tx(void)
static int
ble_hs_startup_read_local_ver_tx(void)
{
uint8_t ack_params[BLE_HCI_RD_LOC_VER_INFO_RSPLEN];
uint8_t ack_params_len;
uint8_t hci_version;
struct ble_hci_ip_rd_local_ver_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_LOCAL_VER),
NULL,0, ack_params, sizeof ack_params,
&ack_params_len);
NULL, 0, &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_RD_LOC_VER_INFO_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
/* For now we are interested only in HCI Version */
hci_version = ack_params[0];
ble_hs_hci_set_hci_version(hci_version);
ble_hs_hci_set_hci_version(rsp.hci_ver);
return 0;
}
@@ -85,26 +71,17 @@ ble_hs_startup_read_local_ver_tx(void)
static int
ble_hs_startup_le_read_sup_f_tx(void)
{
uint8_t ack_params[BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN];
uint8_t ack_params_len;
uint32_t feat;
struct ble_hci_le_rd_loc_supp_feat_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
NULL,0, ack_params, sizeof ack_params,
&ack_params_len);
NULL,0, &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
/* For now 32-bits of features is enough */
feat = get_le32(ack_params);
ble_hs_hci_set_le_supported_feat(feat);
ble_hs_hci_set_le_supported_feat(le64toh(rsp.features));
return 0;
}
@@ -112,23 +89,18 @@ ble_hs_startup_le_read_sup_f_tx(void)
static int
ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
{
uint8_t ack_params[BLE_HCI_RD_BUF_SIZE_RSPLEN];
uint8_t ack_params_len;
struct ble_hci_le_rd_buf_size_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_BUF_SIZE), NULL, 0,
ack_params, sizeof ack_params, &ack_params_len);
&rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_RD_BUF_SIZE_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
*out_pktlen = get_le16(ack_params + 0);
*out_max_pkts = ack_params[2];
*out_pktlen = le16toh(rsp.data_len);
*out_max_pkts = rsp.data_packets;
return 0;
}
@@ -136,23 +108,18 @@ ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
static int
ble_hs_startup_read_buf_sz_tx(uint16_t *out_pktlen, uint16_t *out_max_pkts)
{
uint8_t ack_params[BLE_HCI_IP_RD_BUF_SIZE_RSPLEN];
uint8_t ack_params_len;
struct ble_hci_ip_rd_buf_size_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_BUF_SIZE), NULL, 0,
ack_params, sizeof ack_params, &ack_params_len);
&rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_IP_RD_BUF_SIZE_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
*out_pktlen = get_le16(ack_params + 0);
*out_max_pkts = get_le16(ack_params + 3);
*out_pktlen = le16toh(rsp.acl_data_len);
*out_max_pkts = le16toh(rsp.acl_num);
return 0;
}
@@ -192,30 +159,24 @@ ble_hs_startup_read_buf_sz(void)
static int
ble_hs_startup_read_bd_addr(void)
{
uint8_t ack_params[BLE_HCI_IP_RD_BD_ADDR_ACK_PARAM_LEN];
uint8_t ack_params_len;
struct ble_hci_ip_rd_bd_addr_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_BD_ADDR),
NULL, 0, ack_params, sizeof ack_params,
&ack_params_len);
NULL, 0, &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != sizeof ack_params) {
return BLE_HS_ECONTROLLER;
}
ble_hs_id_set_pub(ack_params);
ble_hs_id_set_pub(rsp.addr);
return 0;
}
static int
ble_hs_startup_le_set_evmask_tx(void)
{
uint8_t buf[BLE_HCI_SET_LE_EVENT_MASK_LEN];
struct ble_hci_le_set_event_mask_cp cmd;
uint8_t version;
uint64_t mask;
int rc;
@@ -267,10 +228,11 @@ ble_hs_startup_le_set_evmask_tx(void)
mask |= 0x00000000000ff800;
}
ble_hs_hci_cmd_build_le_set_event_mask(mask, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_EVENT_MASK),
buf, sizeof(buf));
cmd.event_mask = htole64(mask);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_EVENT_MASK),
&cmd, sizeof(cmd), NULL, 0);
if (rc != 0) {
return rc;
}
@@ -281,7 +243,8 @@ ble_hs_startup_le_set_evmask_tx(void)
static int
ble_hs_startup_set_evmask_tx(void)
{
uint8_t buf[BLE_HCI_SET_EVENT_MASK_LEN];
struct ble_hci_cb_set_event_mask_cp cmd;
struct ble_hci_cb_set_event_mask2_cp cmd2;
uint8_t version;
int rc;
@@ -296,10 +259,11 @@ ble_hs_startup_set_evmask_tx(void)
* 0x0000800000000000 Encryption Key Refresh Complete Event
* 0x2000000000000000 LE Meta-Event
*/
ble_hs_hci_cmd_build_set_event_mask(0x2000800002008090, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_SET_EVENT_MASK),
buf, sizeof(buf));
cmd.event_mask = htole64(0x2000800002008090);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_SET_EVENT_MASK),
&cmd, sizeof(cmd), NULL, 0);
if (rc != 0) {
return rc;
}
@@ -309,10 +273,10 @@ ble_hs_startup_set_evmask_tx(void)
* Enable the following events:
* 0x0000000000800000 Authenticated Payload Timeout Event
*/
ble_hs_hci_cmd_build_set_event_mask2(0x0000000000800000, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_SET_EVENT_MASK2),
buf, sizeof(buf));
cmd2.event_mask2 = htole64(0x0000000000800000);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_SET_EVENT_MASK2),
&cmd2, sizeof(cmd2), NULL, 0);
if (rc != 0) {
return rc;
}
@@ -324,16 +288,9 @@ ble_hs_startup_set_evmask_tx(void)
static int
ble_hs_startup_reset_tx(void)
{
int rc;
rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_RESET),
NULL, 0);
if (rc != 0) {
return rc;
}
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_RESET),
NULL, 0, NULL, 0);
}
int
+47 -51
View File
@@ -93,6 +93,14 @@ static ble_sm_rx_fn * const ble_sm_dispatch[] = {
#endif
};
struct hci_start_encrypt
{
uint16_t connection_handle;
uint16_t encrypted_diversifier;
uint64_t random_number;
uint8_t long_term_key[16];
};
typedef void ble_sm_state_fn(struct ble_sm_proc *proc,
struct ble_sm_result *res, void *arg);
@@ -1033,20 +1041,18 @@ ble_sm_chk_store_overflow(uint16_t conn_handle)
*****************************************************************************/
static int
ble_sm_start_encrypt_tx(struct hci_start_encrypt *cmd)
ble_sm_start_encrypt_tx(struct hci_start_encrypt *params)
{
uint8_t buf[BLE_HCI_LE_START_ENCRYPT_LEN];
int rc;
struct ble_hci_le_start_encrypt_cp cmd;
ble_hs_hci_cmd_build_le_start_encrypt(cmd, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_START_ENCRYPT),
buf, sizeof(buf));
if (rc != 0) {
return rc;
}
cmd.conn_handle = htole16(params->connection_handle);
cmd.div = htole16(params->encrypted_diversifier);
cmd.rand = htole64(params->random_number);
memcpy(cmd.ltk, params->long_term_key, sizeof(cmd.ltk));
return 0;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_START_ENCRYPT),
&cmd, sizeof(cmd), NULL, 0);
}
static void
@@ -1181,19 +1187,19 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
}
void
ble_sm_enc_change_rx(struct hci_encrypt_change *evt)
ble_sm_enc_change_rx(const struct ble_hci_ev_enrypt_chg *ev)
{
/* For encrypted state: read LE-encryption bit; ignore BR/EDR and reserved
* bits.
*/
ble_sm_enc_event_rx(evt->connection_handle, evt->status,
evt->encryption_enabled & 0x01);
ble_sm_enc_event_rx(le16toh(ev->connection_handle), ev->status,
ev->enabled & 0x01);
}
void
ble_sm_enc_key_refresh_rx(struct hci_encrypt_key_refresh *evt)
ble_sm_enc_key_refresh_rx(const struct ble_hci_ev_enc_key_refresh *ev)
{
ble_sm_enc_event_rx(evt->connection_handle, evt->status, 1);
ble_sm_enc_event_rx(le16toh(ev->conn_handle), ev->status, 1);
}
/*****************************************************************************
@@ -1201,7 +1207,7 @@ ble_sm_enc_key_refresh_rx(struct hci_encrypt_key_refresh *evt)
*****************************************************************************/
static int
ble_sm_retrieve_ltk(struct hci_le_lt_key_req *evt, uint8_t peer_addr_type,
ble_sm_retrieve_ltk(uint16_t ediv, uint64_t rand, uint8_t peer_addr_type,
uint8_t *peer_addr, struct ble_store_value_sec *value_sec)
{
struct ble_store_key_sec key_sec;
@@ -1211,8 +1217,8 @@ ble_sm_retrieve_ltk(struct hci_le_lt_key_req *evt, uint8_t peer_addr_type,
memset(&key_sec, 0, sizeof key_sec);
key_sec.peer_addr.type = peer_addr_type;
memcpy(key_sec.peer_addr.val, peer_addr, 6);
key_sec.ediv = evt->encrypted_diversifier;
key_sec.rand_num = evt->random_number;
key_sec.ediv = ediv;
key_sec.rand_num = rand;
key_sec.ediv_rand_present = 1;
rc = ble_store_read_our_sec(&key_sec, value_sec);
@@ -1220,30 +1226,23 @@ ble_sm_retrieve_ltk(struct hci_le_lt_key_req *evt, uint8_t peer_addr_type,
}
static int
ble_sm_ltk_req_reply_tx(uint16_t conn_handle, uint8_t *ltk)
ble_sm_ltk_req_reply_tx(uint16_t conn_handle, const uint8_t *ltk)
{
struct hci_lt_key_req_reply cmd;
uint16_t ack_conn_handle;
uint8_t buf[BLE_HCI_LT_KEY_REQ_REPLY_LEN];
uint8_t ack_params_len;
struct ble_hci_le_lt_key_req_reply_cp cmd;
struct ble_hci_le_lt_key_req_reply_rp rsp;
int rc;
cmd.conn_handle = conn_handle;
memcpy(cmd.long_term_key, ltk, 16);
cmd.conn_handle = htole16(conn_handle);
memcpy(cmd.ltk, ltk, 16);
ble_hs_hci_cmd_build_le_lt_key_req_reply(&cmd, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY),
buf, sizeof(buf), &ack_conn_handle,
sizeof(ack_conn_handle), &ack_params_len);
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN) {
return BLE_HS_ECONTROLLER;
}
if (le16toh(ack_conn_handle) != conn_handle) {
if (le16toh(rsp.conn_handle) != conn_handle) {
return BLE_HS_ECONTROLLER;
}
@@ -1253,24 +1252,19 @@ ble_sm_ltk_req_reply_tx(uint16_t conn_handle, uint8_t *ltk)
static int
ble_sm_ltk_req_neg_reply_tx(uint16_t conn_handle)
{
uint16_t ack_conn_handle;
uint8_t buf[BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN];
uint8_t ack_params_len;
struct ble_hci_le_lt_key_req_neg_reply_cp cmd;
struct ble_hci_le_lt_key_req_neg_reply_cp rsp;
int rc;
ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(conn_handle, buf, sizeof buf);
cmd.conn_handle = htole16(conn_handle);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY),
buf, sizeof(buf), &ack_conn_handle,
sizeof(ack_conn_handle), &ack_params_len);
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_LT_KEY_REQ_NEG_REPLY_ACK_PARAM_LEN) {
return BLE_HS_ECONTROLLER;
}
if (le16toh(ack_conn_handle) != conn_handle) {
if (le16toh(rsp.conn_handle) != conn_handle) {
return BLE_HS_ECONTROLLER;
}
@@ -1329,7 +1323,7 @@ ble_sm_ltk_restore_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
}
int
ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev)
{
struct ble_store_value_sec value_sec;
struct ble_hs_conn_addrs addrs;
@@ -1340,11 +1334,12 @@ ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
int store_rc;
int restore;
uint16_t conn_handle = le16toh(ev->conn_handle);
memset(&res, 0, sizeof res);
ble_hs_lock();
proc = ble_sm_proc_find(evt->connection_handle, BLE_SM_PROC_STATE_NONE,
0, NULL);
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, 0, NULL);
if (proc == NULL) {
/* The peer is attempting to restore a encrypted connection via the
* encryption procedure. Create a proc entry to indicate that security
@@ -1356,7 +1351,7 @@ ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
if (proc == NULL) {
res.app_status = BLE_HS_ENOMEM;
} else {
proc->conn_handle = evt->connection_handle;
proc->conn_handle = conn_handle;
proc->state = BLE_SM_PROC_STATE_LTK_RESTORE;
ble_sm_insert(proc);
@@ -1378,12 +1373,12 @@ ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
} else {
/* The request is unexpected; nack and forget. */
restore = 0;
ble_sm_ltk_req_neg_reply_tx(evt->connection_handle);
ble_sm_ltk_req_neg_reply_tx(conn_handle);
proc = NULL;
}
if (restore) {
conn = ble_hs_conn_find_assert(evt->connection_handle);
conn = ble_hs_conn_find_assert(conn_handle);
ble_hs_conn_addrs(conn, &addrs);
memcpy(peer_id_addr, addrs.peer_id_addr.val, 6);
}
@@ -1396,7 +1391,8 @@ ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
if (res.app_status == 0) {
if (restore) {
store_rc = ble_sm_retrieve_ltk(evt, addrs.peer_id_addr.type,
store_rc = ble_sm_retrieve_ltk(le16toh(ev->div), le64toh(ev->rand),
addrs.peer_id_addr.type,
peer_id_addr, &value_sec);
if (store_rc == 0) {
/* Send the key to the controller. */
@@ -1408,7 +1404,7 @@ ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
}
}
ble_sm_process_result(evt->connection_handle, &res);
ble_sm_process_result(conn_handle, &res);
return 0;
}
+3 -3
View File
@@ -316,9 +316,9 @@ int ble_sm_alg_gen_dhkey(uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y,
int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv);
void ble_sm_alg_ecc_init(void);
void ble_sm_enc_change_rx(struct hci_encrypt_change *evt);
void ble_sm_enc_key_refresh_rx(struct hci_encrypt_key_refresh *evt);
int ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt);
void ble_sm_enc_change_rx(const struct ble_hci_ev_enrypt_chg *ev);
void ble_sm_enc_key_refresh_rx(const struct ble_hci_ev_enc_key_refresh *ev);
int ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev);
#if MYNEWT_VAL(BLE_SM_LEGACY)
int ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action);
+65 -54
View File
@@ -26,6 +26,15 @@
#include "ble_hs_test.h"
#include "ble_hs_test_util.h"
#define BLE_HCI_SET_SCAN_PARAM_LEN (7)
#define BLE_HCI_SET_SCAN_ENABLE_LEN (2)
#define BLE_HCI_DISCONNECT_CMD_LEN (3)
#define BLE_HCI_SET_ADV_PARAM_LEN (15)
#define BLE_HCI_SET_ADV_ENABLE_LEN (1)
#define BLE_HCI_CONN_UPDATE_LEN (14)
#define BLE_HCI_CONN_PARAM_REPLY_LEN (14)
#define BLE_HCI_CONN_PARAM_NEG_REPLY_LEN (3)
static struct ble_gap_event ble_gap_test_event;
static int ble_gap_test_conn_status;
static struct ble_gap_conn_desc ble_gap_test_conn_desc;
@@ -350,14 +359,14 @@ ble_gap_test_util_rx_update_complete(
uint8_t status,
const struct ble_gap_upd_params *params)
{
struct hci_le_conn_upd_complete evt;
struct ble_hci_ev_le_subev_conn_upd_complete evt;
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
evt.subev_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
evt.status = status;
evt.connection_handle = 2;
evt.conn_itvl = params->itvl_max;
evt.conn_latency = params->latency;
evt.supervision_timeout = params->supervision_timeout;
evt.conn_handle = htole16(2);
evt.conn_itvl = htole16(params->itvl_max);
evt.conn_latency = htole16(params->latency);
evt.supervision_timeout = htole16(params->supervision_timeout);
ble_gap_rx_update_complete(&evt);
}
@@ -367,15 +376,15 @@ ble_gap_test_util_rx_param_req(struct ble_gap_upd_params *params, int pos,
int *cmd_idx, int cmd_fail_idx,
uint8_t fail_status)
{
struct hci_le_conn_param_req evt;
struct ble_hci_ev_le_subev_rem_conn_param_req evt;
uint16_t opcode;
uint8_t hci_status;
evt.subevent_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
evt.connection_handle = 2;
evt.itvl_min = params->itvl_min;
evt.itvl_max = params->itvl_max;
evt.latency = params->latency;
evt.subev_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
evt.conn_handle = htole16(2);
evt.min_interval = htole16(params->itvl_min);
evt.max_interval = htole16(params->itvl_max);
evt.latency = htole16(params->latency);
evt.timeout = params->supervision_timeout;
if (pos) {
@@ -612,7 +621,7 @@ TEST_CASE_SELF(ble_gap_test_case_disc_good)
flags = BLE_HS_ADV_F_DISC_LTD;
rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_FLAGS, 1, &flags,
desc.data, &desc.length_data,
adv_data, &desc.length_data,
sizeof adv_data);
TEST_ASSERT_FATAL(rc == 0);
@@ -645,7 +654,7 @@ TEST_CASE_SELF(ble_gap_test_case_disc_good)
TEST_CASE_SELF(ble_gap_test_case_disc_ltd_mismatch)
{
int rc;
struct ble_gap_disc_desc desc = {
struct ble_gap_disc_desc desc_gen = {
.event_type = BLE_HCI_ADV_TYPE_ADV_IND,
.length_data = 3,
.rssi = 0,
@@ -656,6 +665,19 @@ TEST_CASE_SELF(ble_gap_test_case_disc_ltd_mismatch)
BLE_HS_ADV_F_DISC_GEN,
},
};
struct ble_gap_disc_desc desc_lim = {
.event_type = BLE_HCI_ADV_TYPE_ADV_IND,
.length_data = 3,
.rssi = 0,
.addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
.data = (uint8_t[BLE_HS_ADV_MAX_SZ]){
2,
BLE_HS_ADV_TYPE_FLAGS,
BLE_HS_ADV_F_DISC_LTD,
},
};
struct ble_gap_disc_params disc_params = {
.itvl = BLE_GAP_SCAN_SLOW_INTERVAL1,
.window = BLE_GAP_SCAN_SLOW_WINDOW1,
@@ -665,7 +687,7 @@ TEST_CASE_SELF(ble_gap_test_case_disc_ltd_mismatch)
.filter_duplicates = 0,
};
rc = ble_gap_test_util_disc(BLE_OWN_ADDR_PUBLIC, &disc_params, &desc,
rc = ble_gap_test_util_disc(BLE_OWN_ADDR_PUBLIC, &disc_params, &desc_gen,
-1, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(ble_gap_master_in_progress());
@@ -677,9 +699,8 @@ TEST_CASE_SELF(ble_gap_test_case_disc_ltd_mismatch)
rc = ble_hs_test_util_disc_cancel(0);
TEST_ASSERT(rc == 0);
desc.data[2] = BLE_HS_ADV_F_DISC_LTD;
disc_params.limited = 0;
rc = ble_gap_test_util_disc(BLE_OWN_ADDR_PUBLIC, &disc_params, &desc,
rc = ble_gap_test_util_disc(BLE_OWN_ADDR_PUBLIC, &disc_params, &desc_lim,
-1, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(ble_gap_master_in_progress());
@@ -831,7 +852,7 @@ TEST_SUITE(ble_gap_test_suite_disc)
TEST_CASE_SELF(ble_gap_test_case_conn_gen_good)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
struct ble_gap_conn_params params;
int rc;
@@ -869,7 +890,6 @@ TEST_CASE_SELF(ble_gap_test_case_conn_gen_good)
/* Receive connection complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 2;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
@@ -1018,8 +1038,8 @@ TEST_CASE_SELF(ble_gap_test_case_conn_gen_busy)
TEST_CASE_SELF(ble_gap_test_case_conn_gen_fail_evt)
{
static const ble_addr_t peer_addr = {BLE_ADDR_PUBLIC, {1, 2, 3, 4, 5, 6}};
struct hci_le_conn_complete evt;
struct hci_disconn_complete disc_evt;
struct ble_gap_conn_complete evt;
struct ble_hci_ev_disconn_cmp disc_evt;
int rc;
ble_gap_test_util_init();
@@ -1031,7 +1051,6 @@ TEST_CASE_SELF(ble_gap_test_case_conn_gen_fail_evt)
/* Controller indicates failure via connect complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 6;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
@@ -1047,7 +1066,7 @@ TEST_CASE_SELF(ble_gap_test_case_conn_gen_fail_evt)
BLE_HS_HCI_ERR(BLE_ERR_SUCCESS));
memset(&disc_evt, 0, sizeof disc_evt);
disc_evt.connection_handle = 6;
disc_evt.conn_handle = htole16(6);
disc_evt.status = BLE_ERR_SUCCESS;
disc_evt.reason = BLE_ERR_CONN_ESTABLISHMENT;
@@ -1079,7 +1098,7 @@ TEST_SUITE(ble_gap_test_suite_conn_gen)
static void
ble_gap_test_util_conn_cancel(uint8_t hci_status)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
int rc;
/* Initiate cancel procedure. */
@@ -1095,7 +1114,6 @@ ble_gap_test_util_conn_cancel(uint8_t hci_status)
/* Receive connection complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_UNK_CONN_ID;
/* test if host correctly ignores other fields if status is error */
evt.connection_handle = 0x0fff;
@@ -1158,7 +1176,7 @@ TEST_CASE_SELF(ble_gap_test_case_conn_cancel_good)
TEST_CASE_SELF(ble_gap_test_case_conn_cancel_ctlr_fail)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
int rc;
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
@@ -1178,7 +1196,6 @@ TEST_CASE_SELF(ble_gap_test_case_conn_cancel_ctlr_fail)
/* Allow connection complete to succeed. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 2;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
@@ -1212,7 +1229,7 @@ TEST_SUITE(ble_gap_test_suite_conn_cancel)
static void
ble_gap_test_util_terminate(uint8_t *peer_addr, uint8_t hci_status)
{
struct hci_disconn_complete evt;
struct ble_hci_ev_disconn_cmp evt;
int rc;
ble_gap_test_util_init();
@@ -1236,7 +1253,7 @@ ble_gap_test_util_terminate(uint8_t *peer_addr, uint8_t hci_status)
if (hci_status == 0) {
/* Receive disconnection complete event. */
evt.connection_handle = 2;
evt.conn_handle = htole16(2);
evt.status = 0;
evt.reason = BLE_ERR_CONN_TERM_LOCAL;
ble_gap_rx_disconn_complete(&evt);
@@ -1280,7 +1297,7 @@ TEST_CASE_SELF(ble_gap_test_case_conn_terminate_good)
TEST_CASE_SELF(ble_gap_test_case_conn_terminate_ctlr_fail)
{
struct hci_disconn_complete evt;
struct ble_hci_ev_disconn_cmp evt;
int rc;
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
@@ -1300,7 +1317,7 @@ TEST_CASE_SELF(ble_gap_test_case_conn_terminate_ctlr_fail)
ble_gap_test_util_verify_tx_disconnect();
/* Receive failed disconnection complete event. */
evt.connection_handle = 2;
evt.conn_handle = htole16(2);
evt.status = BLE_ERR_UNSUPPORTED;
evt.reason = 0;
ble_gap_rx_disconn_complete(&evt);
@@ -1469,7 +1486,7 @@ ble_gap_test_util_adv(uint8_t own_addr_type,
uint8_t disc_mode, int connect_status,
int cmd_fail_idx, uint8_t fail_status)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields adv_fields;
uint8_t hci_status;
@@ -1545,7 +1562,6 @@ ble_gap_test_util_adv(uint8_t own_addr_type,
}
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = connect_status;
if (connect_status == BLE_ERR_SUCCESS) {
@@ -1635,8 +1651,8 @@ ble_gap_test_util_adv_verify_dflt_params(uint8_t own_addr_type,
uint8_t conn_mode,
uint8_t disc_mode)
{
struct ble_hci_le_set_adv_params_cp hci_cmd;
struct ble_gap_adv_params adv_params;
struct hci_adv_params hci_cmd;
uint8_t *hci_buf;
uint8_t hci_param_len;
int rc;
@@ -1668,33 +1684,33 @@ ble_gap_test_util_adv_verify_dflt_params(uint8_t own_addr_type,
TEST_ASSERT_FATAL(hci_buf != NULL);
TEST_ASSERT_FATAL(hci_param_len == BLE_HCI_SET_ADV_PARAM_LEN);
hci_cmd.adv_itvl_min = get_le16(hci_buf + 0);
hci_cmd.adv_itvl_max = get_le16(hci_buf + 2);
hci_cmd.adv_type = hci_buf[4];
hci_cmd.min_interval = get_le16(hci_buf + 0);
hci_cmd.max_interval = get_le16(hci_buf + 2);
hci_cmd.type = hci_buf[4];
hci_cmd.own_addr_type = hci_buf[5];
hci_cmd.peer_addr_type = hci_buf[6];
memcpy(hci_cmd.peer_addr, hci_buf + 7, 6);
hci_cmd.adv_channel_map = hci_buf[13];
hci_cmd.adv_filter_policy = hci_buf[14];
hci_cmd.chan_map = hci_buf[13];
hci_cmd.filter_policy = hci_buf[14];
if (conn_mode == BLE_GAP_CONN_MODE_NON) {
TEST_ASSERT(hci_cmd.adv_itvl_min == BLE_GAP_ADV_FAST_INTERVAL2_MIN);
TEST_ASSERT(hci_cmd.adv_itvl_max == BLE_GAP_ADV_FAST_INTERVAL2_MAX);
TEST_ASSERT(hci_cmd.min_interval == BLE_GAP_ADV_FAST_INTERVAL2_MIN);
TEST_ASSERT(hci_cmd.max_interval == BLE_GAP_ADV_FAST_INTERVAL2_MAX);
} else {
TEST_ASSERT(hci_cmd.adv_itvl_min == BLE_GAP_ADV_FAST_INTERVAL1_MIN);
TEST_ASSERT(hci_cmd.adv_itvl_max == BLE_GAP_ADV_FAST_INTERVAL1_MAX);
TEST_ASSERT(hci_cmd.min_interval == BLE_GAP_ADV_FAST_INTERVAL1_MIN);
TEST_ASSERT(hci_cmd.max_interval == BLE_GAP_ADV_FAST_INTERVAL1_MAX);
}
if (conn_mode == BLE_GAP_CONN_MODE_NON) {
if (disc_mode == BLE_GAP_DISC_MODE_NON) {
TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND);
TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND);
} else {
TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
}
} else if (conn_mode == BLE_GAP_CONN_MODE_UND) {
TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_IND);
TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_IND);
} else {
TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD);
TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD);
}
}
@@ -2834,7 +2850,7 @@ ble_gap_test_util_conn_forever(void)
static void
ble_gap_test_util_conn_timeout(int32_t duration_ms)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
uint32_t duration_ticks;
int32_t ticks_from_now;
int rc;
@@ -2879,7 +2895,6 @@ ble_gap_test_util_conn_timeout(int32_t duration_ms)
/* Receive the connection complete event indicating a successful cancel. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_UNK_CONN_ID;
/* test if host correctly ignores other fields if status is error */
evt.connection_handle = 0x0fff;
@@ -3174,7 +3189,6 @@ ble_gap_test_util_set_cb_event(struct ble_gap_event *event, void *arg)
TEST_CASE_SELF(ble_gap_test_case_set_cb_good)
{
const uint8_t peer_addr[6] = { 1,2,3,4,5,6 };
struct hci_disconn_complete disconn_evt;
struct ble_gap_event event;
int rc;
@@ -3191,10 +3205,7 @@ TEST_CASE_SELF(ble_gap_test_case_set_cb_good)
rc = ble_hs_test_util_conn_terminate(2, 0);
TEST_ASSERT_FATAL(rc == 0);
disconn_evt.connection_handle = 2;
disconn_evt.status = 0;
disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
ble_hs_test_util_hci_rx_disconn_complete_event(2, 0, BLE_ERR_REM_USER_CONN_TERM);
TEST_ASSERT(event.type == BLE_GAP_EVENT_DISCONNECT);
TEST_ASSERT(event.disconnect.reason ==
+2 -5
View File
@@ -558,7 +558,6 @@ static void
ble_gatt_conn_test_util_timeout(uint16_t conn_handle,
struct ble_gatt_conn_test_arg *arg)
{
struct hci_disconn_complete evt;
int32_t ticks_from_now;
ticks_from_now = ble_gattc_timer();
@@ -574,10 +573,8 @@ ble_gatt_conn_test_util_timeout(uint16_t conn_handle,
TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
/* Ensure connection was terminated due to proecedure timeout. */
evt.connection_handle = conn_handle;
evt.status = 0;
evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_hs_test_util_hci_rx_disconn_complete_event(&evt);
ble_hs_test_util_hci_rx_disconn_complete_event(conn_handle, 0,
BLE_ERR_REM_USER_CONN_TERM);
/* Ensure GATT callback was called with timeout status. */
if (arg != NULL) {
+3
View File
@@ -28,6 +28,9 @@
#define BLE_ADV_TEST_DATA_OFF 4
#define BLE_HCI_SET_ADV_DATA_LEN (32)
#define BLE_HCI_SET_SCAN_RSP_DATA_LEN (32)
static void
ble_hs_adv_test_misc_verify_tx_adv_data_hdr(uint8_t *cmd, int data_len)
{
+4 -6
View File
@@ -25,6 +25,7 @@
#include "host/ble_hs_adv.h"
#include "ble_hs_test.h"
#include "ble_hs_test_util.h"
#include "../src/ble_gap_priv.h"
static int
ble_hs_conn_test_util_any(void)
@@ -40,7 +41,7 @@ ble_hs_conn_test_util_any(void)
TEST_CASE_SELF(ble_hs_conn_test_direct_connect_success)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
ble_addr_t addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
@@ -65,7 +66,6 @@ TEST_CASE_SELF(ble_hs_conn_test_direct_connect_success)
/* Receive successful connection complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 2;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
@@ -93,7 +93,7 @@ TEST_CASE_SELF(ble_hs_conn_test_direct_connect_success)
TEST_CASE_SELF(ble_hs_conn_test_direct_connectable_success)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
struct ble_gap_adv_params adv_params;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
@@ -124,7 +124,6 @@ TEST_CASE_SELF(ble_hs_conn_test_direct_connectable_success)
/* Receive successful connection complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 2;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
@@ -154,7 +153,7 @@ TEST_CASE_SELF(ble_hs_conn_test_direct_connectable_success)
TEST_CASE_SELF(ble_hs_conn_test_undirect_connectable_success)
{
struct ble_hs_adv_fields adv_fields;
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
struct ble_gap_adv_params adv_params;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
@@ -191,7 +190,6 @@ TEST_CASE_SELF(ble_hs_conn_test_undirect_connectable_success)
/* Receive successful connection complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 2;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
+4 -6
View File
@@ -26,6 +26,8 @@
#include "testutil/testutil.h"
#include "ble_hs_test_util.h"
#define BLE_HCI_READ_RSSI_ACK_PARAM_LEN (3) /* No status byte. */
TEST_CASE_SELF(ble_hs_hci_test_event_bad)
{
uint8_t *buf;
@@ -37,7 +39,7 @@ TEST_CASE_SELF(ble_hs_hci_test_event_bad)
buf[0] = 0xff;
buf[1] = 0;
rc = ble_hs_hci_evt_process(buf);
rc = ble_hs_hci_evt_process((void*)buf);
TEST_ASSERT(rc == BLE_HS_ENOTSUP);
ble_hs_test_util_assert_mbufs_freed(NULL);
@@ -90,7 +92,6 @@ TEST_CASE_SELF(ble_hs_hci_test_rssi)
TEST_CASE_SELF(ble_hs_hci_acl_one_conn)
{
struct ble_hs_test_util_hci_num_completed_pkts_entry ncpe[2];
struct hci_disconn_complete evt;
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
uint8_t data[256];
int rc;
@@ -164,10 +165,7 @@ TEST_CASE_SELF(ble_hs_hci_acl_one_conn)
/* Receive a disconnection-complete event. Ensure available buffer count
* increases.
*/
evt.connection_handle = 1;
evt.status = 0;
evt.reason = BLE_ERR_CONN_TERM_LOCAL;
ble_hs_test_util_hci_rx_disconn_complete_event(&evt);
ble_hs_test_util_hci_rx_disconn_complete_event(1, 0, BLE_ERR_CONN_TERM_LOCAL);
TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 5);
ble_hs_test_util_assert_mbufs_freed(NULL);
+7 -10
View File
@@ -216,8 +216,8 @@ ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
ble_gap_event_fn *cb, void *cb_arg)
{
ble_addr_t addr;
struct hci_le_conn_complete evt;
struct hci_le_rd_rem_supp_feat_complete evt2;
struct ble_gap_conn_complete evt;
struct ble_hci_ev_le_subev_rd_rem_used_feat evt2;
int rc;
addr.type = peer_addr_type;
@@ -232,7 +232,6 @@ ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = handle;
evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
@@ -247,9 +246,9 @@ ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
rc = ble_gap_rx_conn_complete(&evt, 0);
TEST_ASSERT(rc == 0);
evt2.subevent_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
evt2.subev_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
evt2.status = BLE_ERR_SUCCESS;
evt2.connection_handle = handle;
evt2.conn_handle = htole16(handle);
memcpy(evt2.features, ((uint8_t[]){ conn_features, 0, 0, 0, 0, 0, 0, 0 }),
8);
@@ -365,17 +364,14 @@ ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status)
void
ble_hs_test_util_conn_disconnect(uint16_t conn_handle)
{
struct hci_disconn_complete evt;
int rc;
rc = ble_hs_test_util_conn_terminate(conn_handle, 0);
TEST_ASSERT_FATAL(rc == 0);
/* Receive disconnection complete event. */
evt.connection_handle = conn_handle;
evt.status = 0;
evt.reason = BLE_ERR_CONN_TERM_LOCAL;
ble_hs_test_util_hci_rx_disconn_complete_event(&evt);
ble_hs_test_util_hci_rx_disconn_complete_event(conn_handle, 0,
BLE_ERR_CONN_TERM_LOCAL);
}
int
@@ -1590,6 +1586,7 @@ ble_hs_test_util_set_static_rnd_addr(const uint8_t *addr)
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_RAND_ADDR), 0);
rc = ble_hs_id_set_rnd(addr);
TEST_ASSERT_FATAL(rc == 0);
ble_hs_test_util_hci_out_first();
+20
View File
@@ -28,6 +28,26 @@
extern "C" {
#endif
/* TODO this is currently copied from ble_ll_conn_priv.h and eventually
* should not be needed...
*/
struct hci_create_conn
{
uint16_t scan_itvl;
uint16_t scan_window;
uint8_t filter_policy;
uint8_t peer_addr_type;
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
uint8_t own_addr_type;
uint16_t conn_itvl_min;
uint16_t conn_itvl_max;
uint16_t conn_latency;
uint16_t supervision_timeout;
uint16_t min_ce_len;
uint16_t max_ce_len;
};
struct ble_hs_conn;
struct ble_l2cap_chan;
struct hci_disconn_complete;
+15 -8
View File
@@ -23,6 +23,14 @@
#include "transport/ram/ble_hci_ram.h"
#include "ble_hs_test_util.h"
#define BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN (5)
#define BLE_HCI_EVENT_CMD_STATUS_LEN (6)
#define BLE_HCI_ADD_TO_RESOLV_LIST_LEN (39)
#define BLE_HCI_LE_SET_PRIVACY_MODE_LEN (8)
#define BLE_HCI_DISCONNECT_CMD_LEN (3)
#define BLE_HCI_EVENT_HDR_LEN (2)
#define BLE_HCI_EVENT_DISCONN_COMPLETE_LEN (4)
#define BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT 64
static uint8_t
@@ -517,7 +525,7 @@ ble_hs_test_util_hci_rx_evt(uint8_t *evt)
if (os_started()) {
rc = ble_hci_trans_ll_evt_tx(evbuf);
} else {
rc = ble_hs_hci_evt_process(evbuf);
rc = ble_hs_hci_evt_process((void *)evbuf);
}
TEST_ASSERT_FATAL(rc == 0);
@@ -557,16 +565,16 @@ ble_hs_test_util_hci_rx_num_completed_pkts_event(
}
void
ble_hs_test_util_hci_rx_disconn_complete_event(
struct hci_disconn_complete *evt)
ble_hs_test_util_hci_rx_disconn_complete_event(uint16_t conn_handle,
uint8_t status, uint8_t reason)
{
uint8_t buf[BLE_HCI_EVENT_HDR_LEN + BLE_HCI_EVENT_DISCONN_COMPLETE_LEN];
buf[0] = BLE_HCI_EVCODE_DISCONN_CMP;
buf[1] = BLE_HCI_EVENT_DISCONN_COMPLETE_LEN;
buf[2] = evt->status;
put_le16(buf + 3, evt->connection_handle);
buf[5] = evt->reason;
buf[2] = status;
put_le16(buf + 3, conn_handle);
buf[5] = reason;
ble_hs_test_util_hci_rx_evt(buf);
}
@@ -574,11 +582,10 @@ ble_hs_test_util_hci_rx_disconn_complete_event(
void
ble_hs_test_util_hci_rx_conn_cancel_evt(void)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
int rc;
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_UNK_CONN_ID;
/* test if host correctly ignores other fields if status is error */
evt.connection_handle = 0x0fff;
+2 -2
View File
@@ -89,8 +89,8 @@ uint8_t *ble_hs_test_util_hci_verify_tx(uint8_t ogf, uint16_t ocf,
/* $rx */
void ble_hs_test_util_hci_rx_num_completed_pkts_event(
struct ble_hs_test_util_hci_num_completed_pkts_entry *entries);
void ble_hs_test_util_hci_rx_disconn_complete_event(
struct hci_disconn_complete *evt);
void ble_hs_test_util_hci_rx_disconn_complete_event(uint16_t conn_handle,
uint8_t status, uint8_t reason);
void ble_hs_test_util_hci_rx_conn_cancel_evt(void);
/* $misc */
+2
View File
@@ -24,6 +24,8 @@
#include "ble_hs_test.h"
#include "ble_hs_test_util.h"
#define BLE_HCI_CONN_UPDATE_LEN (14)
#define BLE_L2CAP_TEST_PSM (90)
#define BLE_L2CAP_TEST_CID (99)
#define BLE_L2CAP_TEST_COC_MTU (256)
+4 -14
View File
@@ -122,7 +122,7 @@ ble_gap_direct_connect_test_connect_cb(struct ble_gap_event *event, void *arg)
static void
ble_gap_direct_connect_test_task_handler(void *arg)
{
struct hci_le_conn_complete evt;
struct ble_gap_conn_complete evt;
ble_addr_t addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
int cb_called;
int rc;
@@ -150,7 +150,6 @@ ble_gap_direct_connect_test_task_handler(void *arg)
/* Receive an HCI connection-complete event. */
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_SUCCESS;
evt.connection_handle = 2;
memcpy(evt.peer_addr, addr.val, 6);
@@ -285,8 +284,7 @@ ble_gap_terminate_cb(struct ble_gap_event *event, void *arg)
static void
ble_gap_terminate_test_task_handler(void *arg)
{
struct hci_disconn_complete disconn_evt;
struct hci_le_conn_complete conn_evt;
struct ble_gap_conn_complete conn_evt;
ble_addr_t addr1 = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
ble_addr_t addr2 = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 }};
int disconn_handle;
@@ -316,7 +314,6 @@ ble_gap_terminate_test_task_handler(void *arg)
ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
memset(&conn_evt, 0, sizeof conn_evt);
conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
conn_evt.status = BLE_ERR_SUCCESS;
conn_evt.connection_handle = 1;
memcpy(conn_evt.peer_addr, addr1.val, 6);
@@ -330,7 +327,6 @@ ble_gap_terminate_test_task_handler(void *arg)
ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
memset(&conn_evt, 0, sizeof conn_evt);
conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
conn_evt.status = BLE_ERR_SUCCESS;
conn_evt.connection_handle = 2;
memcpy(conn_evt.peer_addr, addr2.val, 6);
@@ -343,10 +339,7 @@ ble_gap_terminate_test_task_handler(void *arg)
/* Terminate the first one. */
rc = ble_hs_test_util_conn_terminate(1, 0);
TEST_ASSERT(rc == 0);
disconn_evt.connection_handle = 1;
disconn_evt.status = 0;
disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
ble_hs_test_util_hci_rx_disconn_complete_event(1, 0, BLE_ERR_REM_USER_CONN_TERM);
TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
TEST_ASSERT(disconn_handle == 1);
TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
@@ -355,10 +348,7 @@ ble_gap_terminate_test_task_handler(void *arg)
/* Terminate the second one. */
rc = ble_hs_test_util_conn_terminate(2, 0);
TEST_ASSERT(rc == 0);
disconn_evt.connection_handle = 2;
disconn_evt.status = 0;
disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
ble_hs_test_util_hci_rx_disconn_complete_event(2, 0, BLE_ERR_REM_USER_CONN_TERM);
TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
TEST_ASSERT(disconn_handle == 2);
TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
+2 -2
View File
@@ -144,7 +144,7 @@ TEST_CASE_SELF(ble_sm_test_case_g2)
TEST_CASE_SELF(ble_sm_test_case_conn_broken)
{
struct hci_disconn_complete disconn_evt;
struct ble_hci_ev_disconn_cmp disconn_evt;
int rc;
ble_sm_test_util_init();
@@ -161,7 +161,7 @@ TEST_CASE_SELF(ble_sm_test_case_conn_broken)
ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
/* Terminate the connection. */
disconn_evt.connection_handle = 2;
disconn_evt.conn_handle = htole16(2);
disconn_evt.status = 0;
disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_gap_rx_disconn_complete(&disconn_evt);
+15 -8
View File
@@ -29,6 +29,13 @@
#include "ble_hs_test_util.h"
#include "ble_sm_test_util.h"
#define BLE_HCI_LT_KEY_REQ_REPLY_LEN (18)
#define BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN (2)
#define BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN (2) /* No status byte. */
#define BLE_HCI_LT_KEY_REQ_NEG_REPLY_ACK_PARAM_LEN (2)
#define BLE_HCI_LE_START_ENCRYPT_LEN (28)
#define BLE_HCI_ADD_TO_RESOLV_LIST_LEN (39)
int ble_sm_test_gap_event_type;
int ble_sm_test_gap_status;
struct ble_gap_sec_state ble_sm_test_sec_state;
@@ -1239,13 +1246,13 @@ ble_sm_test_util_verify_tx_pair_fail(
static void
ble_sm_test_util_rx_lt_key_req(uint16_t conn_handle, uint64_t r, uint16_t ediv)
{
struct hci_le_lt_key_req evt;
struct ble_hci_ev_le_subev_lt_key_req evt;
int rc;
evt.subevent_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ;
evt.connection_handle = conn_handle;
evt.random_number = r;
evt.encrypted_diversifier = ediv;
evt.subev_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ;
evt.conn_handle = htole16(conn_handle);
evt.rand = htole64(r);
evt.div = htole16(ediv);
rc = ble_sm_ltk_req_rx(&evt);
TEST_ASSERT_FATAL(rc == 0);
@@ -1307,11 +1314,11 @@ static void
ble_sm_test_util_rx_enc_change(uint16_t conn_handle, uint8_t status,
uint8_t encryption_enabled)
{
struct hci_encrypt_change evt;
struct ble_hci_ev_enrypt_chg evt;
evt.status = status;
evt.encryption_enabled = encryption_enabled;
evt.connection_handle = conn_handle;
evt.enabled = encryption_enabled;
evt.connection_handle = htole16(conn_handle);
ble_sm_enc_change_rx(&evt);
}
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -394,7 +394,7 @@ ble_hci_emspi_tx_cmd(const uint8_t *data)
return rc;
}
len = data[2] + BLE_HCI_CMD_HDR_LEN;
len = data[2] + sizeof(struct ble_hci_cmd);
rc = ble_hci_emspi_tx_flat(data, len);
if (rc != 0) {
return rc;
@@ -488,14 +488,14 @@ ble_hci_emspi_rx_evt(void)
data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
assert(data != NULL);
rc = ble_hci_emspi_rx(data, BLE_HCI_EVENT_HDR_LEN);
rc = ble_hci_emspi_rx(data, sizeof(struct ble_hci_ev));
if (rc != 0) {
goto err;
}
len = data[1];
if (len > 0) {
rc = ble_hci_emspi_rx(data + BLE_HCI_EVENT_HDR_LEN, len);
rc = ble_hci_emspi_rx(data + sizeof(struct ble_hci_ev), len);
if (rc != 0) {
goto err;
}
+6 -6
View File
@@ -289,10 +289,10 @@ ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
iov[0].iov_base = &ch;
iov[1].iov_base = hci_ev;
if (h4_type == BLE_HCI_UART_H4_CMD) {
len = BLE_HCI_CMD_HDR_LEN + hci_ev[2];
len = sizeof(struct ble_hci_cmd) + hci_ev[2];
STATS_INC(hci_sock_stats, ocmd);
} else if (h4_type == BLE_HCI_UART_H4_EVT) {
len = BLE_HCI_EVENT_HDR_LEN + hci_ev[1];
len = sizeof(struct ble_hci_ev) + hci_ev[1];
STATS_INC(hci_sock_stats, oevt);
} else {
assert(0);
@@ -346,10 +346,10 @@ ble_hci_sock_rx_msg(void)
switch (bhss->rx_data[0]) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case BLE_HCI_UART_H4_CMD:
if (bhss->rx_off < BLE_HCI_CMD_HDR_LEN) {
if (bhss->rx_off < sizeof(struct ble_hci_cmd)) {
return -1;
}
len = 1 + BLE_HCI_CMD_HDR_LEN + bhss->rx_data[3];
len = 1 + sizeof(struct ble_hci_cmd) + bhss->rx_data[3];
if (bhss->rx_off < len) {
return -1;
}
@@ -373,10 +373,10 @@ ble_hci_sock_rx_msg(void)
#endif
#if MYNEWT_VAL(BLE_HOST)
case BLE_HCI_UART_H4_EVT:
if (bhss->rx_off < BLE_HCI_EVENT_HDR_LEN) {
if (bhss->rx_off < sizeof(struct ble_hci_ev)) {
return -1;
}
len = 1 + BLE_HCI_EVENT_HDR_LEN + bhss->rx_data[2];
len = 1 + sizeof(struct ble_hci_ev) + bhss->rx_data[2];
if (bhss->rx_off < len) {
return -1;
}
+14 -14
View File
@@ -290,7 +290,7 @@ ble_hci_uart_tx_pkt_type(void)
ble_hci_uart_state.tx_cmd.data = pkt->data;
ble_hci_uart_state.tx_cmd.cur = 0;
ble_hci_uart_state.tx_cmd.len = ble_hci_uart_state.tx_cmd.data[2] +
BLE_HCI_CMD_HDR_LEN;
sizeof(struct ble_hci_cmd);
break;
case BLE_HCI_UART_H4_EVT:
@@ -298,7 +298,7 @@ ble_hci_uart_tx_pkt_type(void)
ble_hci_uart_state.tx_cmd.data = pkt->data;
ble_hci_uart_state.tx_cmd.cur = 0;
ble_hci_uart_state.tx_cmd.len = ble_hci_uart_state.tx_cmd.data[1] +
BLE_HCI_EVENT_HDR_LEN;
sizeof(struct ble_hci_ev);
break;
case BLE_HCI_UART_H4_ACL:
@@ -543,13 +543,13 @@ ble_hci_uart_rx_cmd(uint8_t data)
ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur++] = data;
if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_CMD_HDR_LEN) {
if (ble_hci_uart_state.rx_cmd.cur < sizeof(struct ble_hci_cmd)) {
return;
}
if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_CMD_HDR_LEN) {
if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_cmd)) {
ble_hci_uart_state.rx_cmd.len = ble_hci_uart_state.rx_cmd.data[2] +
BLE_HCI_CMD_HDR_LEN;
sizeof(struct ble_hci_cmd);
}
if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
@@ -568,12 +568,12 @@ ble_hci_uart_rx_skip_cmd(uint8_t data)
{
ble_hci_uart_state.rx_cmd.cur++;
if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_CMD_HDR_LEN) {
if (ble_hci_uart_state.rx_cmd.cur < sizeof(struct ble_hci_cmd)) {
return;
}
if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_CMD_HDR_LEN) {
ble_hci_uart_state.rx_cmd.len = data + BLE_HCI_CMD_HDR_LEN;
if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_cmd)) {
ble_hci_uart_state.rx_cmd.len = data + sizeof(struct ble_hci_cmd);
}
if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
@@ -625,13 +625,13 @@ ble_hci_uart_rx_evt(uint8_t data)
ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur++] = data;
if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_EVENT_HDR_LEN) {
if (ble_hci_uart_state.rx_cmd.cur < sizeof(struct ble_hci_ev)) {
return;
}
if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_EVENT_HDR_LEN) {
if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_ev)) {
ble_hci_uart_state.rx_cmd.len = ble_hci_uart_state.rx_cmd.data[1] +
BLE_HCI_EVENT_HDR_LEN;
sizeof(struct ble_hci_ev);
}
ble_hci_uart_rx_evt_cb();
@@ -642,10 +642,10 @@ ble_hci_uart_rx_le_evt(uint8_t data)
{
ble_hci_uart_state.rx_cmd.cur++;
if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_EVENT_HDR_LEN) {
if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_ev)) {
/* LE Meta Event parameter length is never 0 */
assert(data != 0);
ble_hci_uart_state.rx_cmd.len = data + BLE_HCI_EVENT_HDR_LEN;
ble_hci_uart_state.rx_cmd.len = data + sizeof(struct ble_hci_ev);
return;
}
@@ -668,7 +668,7 @@ ble_hci_uart_rx_le_evt(uint8_t data)
ble_hci_uart_state.rx_cmd.data[0] = BLE_HCI_EVCODE_LE_META;
ble_hci_uart_state.rx_cmd.data[1] =
ble_hci_uart_state.rx_cmd.len - BLE_HCI_EVENT_HDR_LEN;
ble_hci_uart_state.rx_cmd.len - sizeof(struct ble_hci_ev);
}
ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur - 1] = data;