diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c index a3fac102d..275e3da2f 100644 --- a/apps/btshell/src/main.c +++ b/apps/btshell/src/main.c @@ -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; diff --git a/apps/bttester/src/gap.c b/apps/bttester/src/gap.c index 169169eff..0856a68e5 100644 --- a/apps/bttester/src/gap.c +++ b/apps/bttester/src/gap.c @@ -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; diff --git a/nimble/controller/include/controller/ble_hw.h b/nimble/controller/include/controller/ble_hw.h index 0544ca263..cf2930761 100644 --- a/nimble/controller/include/controller/ble_hw.h +++ b/nimble/controller/include/controller/ble_hw.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index a854362d5..51e719867 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index dbcf5ce5a..ef64bc064 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index 97492af57..a6a0e53e1 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -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 { diff --git a/nimble/controller/include/controller/ble_ll_ctrl.h b/nimble/controller/include/controller/ble_ll_ctrl.h index 90156d51d..00dcece42 100644 --- a/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/nimble/controller/include/controller/ble_ll_ctrl.h @@ -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 } diff --git a/nimble/controller/include/controller/ble_ll_hci.h b/nimble/controller/include/controller/ble_ll_hci.h index 2d8e93b70..d23e8d8ea 100644 --- a/nimble/controller/include/controller/ble_ll_hci.h +++ b/nimble/controller/include/controller/ble_ll_hci.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll_resolv.h b/nimble/controller/include/controller/ble_ll_resolv.h index e28e6e56f..01c655ba0 100644 --- a/nimble/controller/include/controller/ble_ll_resolv.h +++ b/nimble/controller/include/controller/ble_ll_resolv.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 5f363842b..df636ea15 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll_sync.h b/nimble/controller/include/controller/ble_ll_sync.h index af255f1f5..ca7a6d467 100644 --- a/nimble/controller/include/controller/ble_ll_sync.h +++ b/nimble/controller/include/controller/ble_ll_sync.h @@ -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); diff --git a/nimble/controller/include/controller/ble_ll_whitelist.h b/nimble/controller/include/controller/ble_ll_whitelist.h index e9549e964..2d3b6c5dd 100644 --- a/nimble/controller/include/controller/ble_ll_whitelist.h +++ b/nimble/controller/include/controller/ble_ll_whitelist.h @@ -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); diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 4afb1a00e..355485c9b 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -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; diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 6ef43693d..541f7c6bf 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -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; } diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 30bb3d916..1411a24ad 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -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; diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index 580e46c92..1a291eea3 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -133,96 +133,110 @@ void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, uint8_t *evbuf, struct ble_ll_adv_sm *advsm) { - uint8_t peer_addr_type; - uint8_t enabled; - uint8_t enh_enabled; - uint8_t *evdata; + struct ble_hci_ev_le_subev_enh_conn_complete *enh_ev; + struct ble_hci_ev_le_subev_conn_complete *ev; + struct ble_hci_ev *hci_ev = (void *) evbuf; uint8_t *rpa; - enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE); - enh_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE); + BLE_LL_ASSERT(evbuf); - if (enabled || enh_enabled) { - /* Put common elements in event */ - evbuf[0] = BLE_HCI_EVCODE_LE_META; - if (enh_enabled) { - evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN; - evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE; - } else { - evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN; - evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE; - } - evbuf[3] = status; + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE)) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*enh_ev); + enh_ev = (void *) hci_ev->data; + + memset(enh_ev, 0, sizeof(*enh_ev)); + + enh_ev->subev_code = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE; + enh_ev->status = status; if (connsm) { - put_le16(evbuf + 4, connsm->conn_handle); + enh_ev->conn_handle = htole16(connsm->conn_handle); + enh_ev->role = connsm->conn_role - 1; + enh_ev->peer_addr_type = connsm->peer_addr_type; + memcpy(enh_ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); - evbuf[6] = connsm->conn_role - 1; - peer_addr_type = connsm->peer_addr_type; - - evdata = evbuf + 14; - if (enh_enabled) { - memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN); - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - if (connsm->inita_identity_used) { - /* We used identity address in CONNECT_IND which can be just fine if - * a) it was direct advertising we replied to and remote uses its identity address - * in device privacy mode or IRK is all zeros. - * b) peer uses RPA and this is first time we connect to him - */ - rpa = NULL; - } else if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - rpa = ble_ll_scan_get_local_rpa(); - } else { - rpa = NULL; - } + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + if (connsm->inita_identity_used) { + /* We used identity address in CONNECT_IND which can be just + * fine if + * a) it was direct advertising we replied to and remote uses + * its identity address in device privacy mode or IRK is all + * zeros. + * b) peer uses RPA and this is first time we connect to him + */ + rpa = NULL; + } else if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + rpa = ble_ll_scan_get_local_rpa(); } else { - rpa = ble_ll_adv_get_local_rpa(advsm); + rpa = NULL; } - if (rpa) { - memcpy(evdata, rpa, BLE_DEV_ADDR_LEN); - } - - /* We need to adjust peer type if device connected using RPA - * and was resolved since RPA needs to be added to HCI event. - */ - if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT - && (connsm->rpa_index > -1)) { - peer_addr_type += 2; - } - - if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - rpa = ble_ll_scan_get_peer_rpa(); - } else { - rpa = ble_ll_adv_get_peer_rpa(advsm); - } - memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN); - } - evdata += 12; } else { - if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { - peer_addr_type -= 2; - } + rpa = ble_ll_adv_get_local_rpa(advsm); } - evbuf[7] = peer_addr_type; - memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN); + if (rpa) { + memcpy(enh_ev->local_rpa, rpa, BLE_DEV_ADDR_LEN); + } - put_le16(evdata, connsm->conn_itvl); - put_le16(evdata + 2, connsm->slave_latency); - put_le16(evdata + 4, connsm->supervision_tmo); - evdata[6] = connsm->master_sca; - } else { - /* zero remaining bytes of event (2 bytes used for subevent opcode - * and status) - **/ - memset(&evbuf[4], 0, evbuf[1] - 2); + /* We need to adjust peer type if device connected using RPA + * and was resolved since RPA needs to be added to HCI event. + */ + if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT + && (connsm->rpa_index > -1)) { + enh_ev->peer_addr_type += 2; + } + + if (enh_ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + rpa = ble_ll_scan_get_peer_rpa(); + } else { + rpa = ble_ll_adv_get_peer_rpa(advsm); + } + memcpy(enh_ev->peer_rpa, rpa, BLE_DEV_ADDR_LEN); + } + + enh_ev->conn_itvl = htole16(connsm->conn_itvl); + enh_ev->conn_latency = htole16(connsm->slave_latency); + enh_ev->supervision_timeout = htole16(connsm->supervision_tmo); + enh_ev->mca = connsm->master_sca; } - ble_ll_hci_event_send(evbuf); - } -} + ble_ll_hci_event_send(hci_ev); + return; + } + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE)) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + memset(ev, 0, sizeof(*ev)); + + ev->subev_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; + ev->status = status; + + if (connsm) { + ev->conn_handle = htole16(connsm->conn_handle); + ev->role = connsm->conn_role - 1; + ev->peer_addr_type = connsm->peer_addr_type; + + if (ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { + ev->peer_addr_type -= 2; + } + memcpy(ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); + ev->conn_itvl = htole16(connsm->conn_itvl); + ev->conn_latency = htole16(connsm->slave_latency); + ev->supervision_timeout = htole16(connsm->supervision_tmo); + ev->mca = connsm->master_sca; + } + + ble_ll_hci_event_send(hci_ev); + return; + } + + ble_hci_trans_buf_free(evbuf); +} /** * Called to create and send the number of completed packets event to the @@ -233,12 +247,10 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) { /** The maximum number of handles that will fit in an event buffer. */ static const int max_handles = - (BLE_LL_MAX_EVT_LEN - BLE_HCI_EVENT_HDR_LEN - 1) / 4; - + (BLE_LL_MAX_EVT_LEN - sizeof(struct ble_hci_ev_num_comp_pkts) - 1) / 4; + struct ble_hci_ev_num_comp_pkts *ev; + struct ble_hci_ev *hci_ev; int event_sent; - uint8_t *evbuf; - uint8_t *handle_ptr; - uint8_t handles; if (connsm == NULL) { goto skip_conn; @@ -259,15 +271,20 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) * entire active list every time. */ if (connsm->completed_pkts) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (evbuf) { - evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS; - evbuf[1] = (2 * sizeof(uint16_t)) + 1; - evbuf[2] = 1; - put_le16(evbuf + 3, connsm->conn_handle); - put_le16(evbuf + 5, connsm->completed_pkts); - 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_NUM_COMP_PKTS; + hci_ev->length = sizeof(*ev); + ev = (void *)hci_ev->data; + + ev->count = 1; + ev->completed[0].handle = htole16(connsm->conn_handle); + ev->completed[0].packets = htole16(connsm->completed_pkts); + hci_ev->length += sizeof(ev->completed[0]); + connsm->completed_pkts = 0; + + ble_ll_hci_event_send(hci_ev); } } return; @@ -275,9 +292,9 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) /* Iterate through all the active, created connections */ skip_conn: - evbuf = NULL; - handles = 0; - handle_ptr = NULL; + hci_ev = NULL; + ev = NULL; + event_sent = 0; SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { /* @@ -287,41 +304,39 @@ skip_conn: if ((connsm->conn_state != BLE_LL_CONN_STATE_IDLE) && (connsm->completed_pkts || !STAILQ_EMPTY(&connsm->conn_txq))) { /* If no buffer, get one, If cant get one, leave. */ - if (!evbuf) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!evbuf) { + if (!hci_ev) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!hci_ev) { break; } - handles = 0; - handle_ptr = evbuf + 3; + + hci_ev->opcode = BLE_HCI_EVCODE_NUM_COMP_PKTS; + hci_ev->length = sizeof(*ev); + ev = (void *)hci_ev->data; + + ev->count = 0; } /* Add handle and complete packets */ - put_le16(handle_ptr, connsm->conn_handle); - put_le16(handle_ptr + 2, connsm->completed_pkts); + ev->completed[ev->count].handle = htole16(connsm->conn_handle); + ev->completed[ev->count].packets = htole16(connsm->completed_pkts); + hci_ev->length += sizeof(ev->completed[ev->count]); + ev->count++; + connsm->completed_pkts = 0; - handle_ptr += (2 * sizeof(uint16_t)); - ++handles; /* Send now if the buffer is full. */ - if (handles == max_handles) { - evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS; - evbuf[1] = (handles * 2 * sizeof(uint16_t)) + 1; - evbuf[2] = handles; - ble_ll_hci_event_send(evbuf); - evbuf = NULL; - handles = 0; + if (ev->count == max_handles) { + ble_ll_hci_event_send(hci_ev); + hci_ev = NULL; event_sent = 1; } } } /* Send event if there is an event to send */ - if (evbuf) { - evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS; - evbuf[1] = (handles * 2 * sizeof(uint16_t)) + 1; - evbuf[2] = handles; - ble_ll_hci_event_send(evbuf); + if (hci_ev) { + ble_ll_hci_event_send(hci_ev); event_sent = 1; } @@ -342,15 +357,19 @@ skip_conn: void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm) { - uint8_t *evbuf; + struct ble_hci_ev_auth_pyld_tmo *ev; + struct ble_hci_ev *hci_ev; if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_AUTH_PYLD_TMO)) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (evbuf) { - evbuf[0] = BLE_HCI_EVCODE_AUTH_PYLD_TMO; - evbuf[1] = sizeof(uint16_t); - put_le16(evbuf + 2, connsm->conn_handle); - 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_AUTH_PYLD_TMO; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + ev->conn_handle = htole16(connsm->conn_handle); + + ble_ll_hci_event_send(hci_ev); } } } @@ -367,17 +386,22 @@ ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm) void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason) { - uint8_t *evbuf; + struct ble_hci_ev_disconn_cmp *ev; + struct ble_hci_ev *hci_ev; if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DISCONN_CMP)) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (evbuf) { - evbuf[0] = BLE_HCI_EVCODE_DISCONN_CMP; - evbuf[1] = BLE_HCI_EVENT_DISCONN_COMPLETE_LEN; - evbuf[2] = BLE_ERR_SUCCESS; - put_le16(evbuf + 3, connsm->conn_handle); - evbuf[5] = reason; - 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_DISCONN_CMP; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + + ev->status = BLE_ERR_SUCCESS; + ev->conn_handle = htole16(connsm->conn_handle); + ev->reason = reason; + + ble_ll_hci_event_send(hci_ev); } } } @@ -407,12 +431,16 @@ ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window) * @return int */ int -ble_ll_conn_create(uint8_t *cmdbuf) +ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) { - int rc; - struct hci_create_conn ccdata; - struct hci_create_conn *hcc; + const struct ble_hci_le_create_conn_cp *cmd = (const void *) cmdbuf; struct ble_ll_conn_sm *connsm; + struct hci_create_conn hcc = { 0 }; + int rc; + + if (len < sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } /* If we are already creating a connection we should leave */ if (g_ble_ll_conn_create_sm) { @@ -425,54 +453,53 @@ ble_ll_conn_create(uint8_t *cmdbuf) } /* Retrieve command data */ - hcc = &ccdata; - hcc->scan_itvl = get_le16(cmdbuf); - hcc->scan_window = get_le16(cmdbuf + 2); + hcc.scan_itvl = le16toh(cmd->scan_itvl); + hcc.scan_window = le16toh(cmd->scan_window); - rc = ble_ll_conn_hci_chk_scan_params(hcc->scan_itvl, hcc->scan_window); + rc = ble_ll_conn_hci_chk_scan_params(hcc.scan_itvl, hcc.scan_window); if (rc) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Check filter policy */ - hcc->filter_policy = cmdbuf[4]; - if (hcc->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { + hcc.filter_policy = cmd->filter_policy; + if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Get peer address type and address only if no whitelist used */ - if (hcc->filter_policy == 0) { - hcc->peer_addr_type = cmdbuf[5]; - if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { + if (hcc.filter_policy == 0) { + hcc.peer_addr_type = cmd->peer_addr_type; + if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - memcpy(&hcc->peer_addr, cmdbuf + 6, BLE_DEV_ADDR_LEN); + memcpy(&hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); } /* Get own address type (used in connection request) */ - hcc->own_addr_type = cmdbuf[12]; - if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + hcc.own_addr_type = cmd->own_addr_type; + if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Check connection interval, latency and supervision timeoout */ - hcc->conn_itvl_min = get_le16(cmdbuf + 13); - hcc->conn_itvl_max = get_le16(cmdbuf + 15); - hcc->conn_latency = get_le16(cmdbuf + 17); - hcc->supervision_timeout = get_le16(cmdbuf + 19); - rc = ble_ll_conn_hci_chk_conn_params(hcc->conn_itvl_min, - hcc->conn_itvl_max, - hcc->conn_latency, - hcc->supervision_timeout); + hcc.conn_itvl_min = le16toh(cmd->min_conn_itvl); + hcc.conn_itvl_max = le16toh(cmd->max_conn_itvl); + hcc.conn_latency = le16toh(cmd->conn_latency); + hcc.supervision_timeout = le16toh(cmd->tmo); + rc = ble_ll_conn_hci_chk_conn_params(hcc.conn_itvl_min, + hcc.conn_itvl_max, + hcc.conn_latency, + hcc.supervision_timeout); if (rc) { return rc; } /* Min/max connection event lengths */ - hcc->min_ce_len = get_le16(cmdbuf + 21); - hcc->max_ce_len = get_le16(cmdbuf + 23); - if (hcc->min_ce_len > hcc->max_ce_len) { + hcc.min_ce_len = le16toh(cmd->min_ce); + hcc.max_ce_len = le16toh(cmd->max_ce); + if (hcc.min_ce_len > hcc.max_ce_len) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -488,12 +515,12 @@ ble_ll_conn_create(uint8_t *cmdbuf) } /* Initialize state machine in master role and start state machine */ - ble_ll_conn_master_init(connsm, hcc); + ble_ll_conn_master_init(connsm, &hcc); ble_ll_conn_sm_new(connsm); /* CSA will be selected when advertising is received */ /* Start scanning */ - rc = ble_ll_scan_initiator_start(hcc, &connsm->scansm); + rc = ble_ll_scan_initiator_start(&hcc, &connsm->scansm); if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); @@ -507,44 +534,45 @@ ble_ll_conn_create(uint8_t *cmdbuf) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static void -ble_ll_conn_init_hcc_params(struct hci_ext_create_conn *hcc, - int valid_param_idx) +ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc, + const struct hci_ext_conn_params *fallback) { - struct hci_ext_conn_params *hcc_params = &hcc->params[valid_param_idx]; + BLE_LL_ASSERT(fallback); - if (valid_param_idx != 0 && !(hcc->init_phy_mask & BLE_PHY_MASK_1M)) { - hcc->params[0] = *hcc_params; + if (!(hcc->init_phy_mask & BLE_PHY_MASK_1M)) { + hcc->params[0] = *fallback; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if (valid_param_idx != 1 && !(hcc->init_phy_mask & BLE_PHY_MASK_2M)) { - hcc->params[1] = *hcc_params; + if (!(hcc->init_phy_mask & BLE_PHY_MASK_2M)) { + hcc->params[1] = *fallback; } #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (valid_param_idx != 2 && !(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) { - hcc->params[2] = *hcc_params; + if (!(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) { + hcc->params[2] = *fallback; } #endif } int -ble_ll_ext_conn_create(uint8_t *cmdbuf, uint8_t cmdlen) +ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) { - int rc; - struct hci_ext_create_conn ccdata; - struct hci_ext_create_conn *hcc; - struct hci_ext_conn_params *hcc_params; + const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *) cmdbuf; + const struct conn_params *params = cmd->conn_params; + const struct hci_ext_conn_params *fallback_params = NULL; + struct hci_ext_create_conn hcc = { 0 }; struct ble_ll_conn_sm *connsm; - int valid_param_idx = -1; - int iter; + int rc; /* validate length */ - if (cmdlen < 10) { + if (len < sizeof(*cmd)) { return BLE_ERR_INV_HCI_CMD_PARMS; } + len -= sizeof(*cmd); + /* If we are already creating a connection we should leave */ if (g_ble_ll_conn_create_sm) { return BLE_ERR_CMD_DISALLOWED; @@ -555,161 +583,147 @@ ble_ll_ext_conn_create(uint8_t *cmdbuf, uint8_t cmdlen) return BLE_ERR_CMD_DISALLOWED; } - /* Retrieve command data */ - hcc = &ccdata; - memset (hcc, 0, sizeof(*hcc)); - - /* Check filter policy */ - hcc->filter_policy = cmdbuf[0]; - if (hcc->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { + hcc.filter_policy = cmd->filter_policy; + if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Get own address type (used in connection request) */ - hcc->own_addr_type = cmdbuf[1]; - if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + hcc.own_addr_type = cmd->own_addr_type; + if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Get peer address type and address only if no whitelist used */ - if (hcc->filter_policy == 0) { - hcc->peer_addr_type = cmdbuf[2]; - if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { + /* Validate peer address type only if no whitelist used */ + if (hcc.filter_policy == 0) { + hcc.peer_addr_type = cmd->peer_addr_type; + + if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - memcpy(&hcc->peer_addr, cmdbuf + 3, BLE_DEV_ADDR_LEN); + memcpy(hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); } - hcc->init_phy_mask = cmdbuf[9]; - if (hcc->init_phy_mask & ~ble_ll_valid_conn_phy_mask) { + hcc.init_phy_mask = cmd->init_phy_mask; + if (hcc.init_phy_mask & ~ble_ll_valid_conn_phy_mask) { return BLE_ERR_INV_HCI_CMD_PARMS; } - if (!(hcc->init_phy_mask & ble_ll_conn_required_phy_mask)) { + if (!(hcc.init_phy_mask & ble_ll_conn_required_phy_mask)) { /* At least one of those need to be set */ return BLE_ERR_INV_HCI_CMD_PARMS; } - iter = 10; - if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { - /* validate length */ - if (cmdlen < iter + 16) { + if (hcc.init_phy_mask & BLE_PHY_MASK_1M) { + if (len < sizeof(*params)) { return BLE_ERR_INV_HCI_CMD_PARMS; } + len -= sizeof(*params); - hcc_params = &hcc->params[0]; - hcc_params->scan_itvl = get_le16(cmdbuf + iter); - hcc_params->scan_window = get_le16(cmdbuf + iter + 2); - iter += 4; + hcc.params[0].scan_itvl = le16toh(params->scan_itvl); + hcc.params[0].scan_window = le16toh(params->scan_window); - rc = ble_ll_conn_hci_chk_scan_params(hcc_params->scan_itvl, - hcc_params->scan_window); + rc = ble_ll_conn_hci_chk_scan_params(hcc.params[0].scan_itvl, + hcc.params[0].scan_window); if (rc) { return rc; } - hcc_params->conn_itvl_min = get_le16(cmdbuf + iter); - hcc_params->conn_itvl_max = get_le16(cmdbuf + iter + 2); - hcc_params->conn_latency = get_le16(cmdbuf + iter + 4); - hcc_params->supervision_timeout = get_le16(cmdbuf + iter + 6); - rc = ble_ll_conn_hci_chk_conn_params(hcc_params->conn_itvl_min, - hcc_params->conn_itvl_max, - hcc_params->conn_latency, - hcc_params->supervision_timeout); + hcc.params[0].conn_itvl_min = le16toh(params->conn_min_itvl); + hcc.params[0].conn_itvl_max = le16toh(params->conn_min_itvl); + hcc.params[0].conn_latency = le16toh(params->conn_latency); + hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout); + + rc = ble_ll_conn_hci_chk_conn_params(hcc.params[0].conn_itvl_min, + hcc.params[0].conn_itvl_max, + hcc.params[0].conn_latency, + hcc.params[0].supervision_timeout); if (rc) { return rc; } - iter += 8; /* Min/max connection event lengths */ - hcc_params->min_ce_len = get_le16(cmdbuf + iter); - hcc_params->max_ce_len = get_le16(cmdbuf + iter + 2); - if (hcc_params->min_ce_len > hcc_params->max_ce_len) { + hcc.params[0].min_ce_len = le16toh(params->min_ce); + hcc.params[0].max_ce_len = le16toh(params->max_ce); + if (hcc.params[0].min_ce_len > hcc.params[0].max_ce_len) { return BLE_ERR_INV_HCI_CMD_PARMS; } - iter += 4; - valid_param_idx = 0; + fallback_params = &hcc.params[0]; + params++; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if (hcc->init_phy_mask & BLE_PHY_MASK_2M) { - /* validate length */ - if (cmdlen < iter + 16) { + if (hcc.init_phy_mask & BLE_PHY_MASK_2M) { + if (len < sizeof(*params)) { return BLE_ERR_INV_HCI_CMD_PARMS; } + len -= sizeof(*params); - /* Move to connection parameters */ - hcc_params = &hcc->params[1]; - iter += 4; + hcc.params[1].conn_itvl_min = le16toh(params->conn_min_itvl); + hcc.params[1].conn_itvl_max = le16toh(params->conn_min_itvl); + hcc.params[1].conn_latency = le16toh(params->conn_latency); + hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout); - hcc_params->conn_itvl_min = get_le16(cmdbuf + iter); - hcc_params->conn_itvl_max = get_le16(cmdbuf + iter + 2); - hcc_params->conn_latency = get_le16(cmdbuf + iter + 4); - hcc_params->supervision_timeout = get_le16(cmdbuf + iter + 6); - rc = ble_ll_conn_hci_chk_conn_params(hcc_params->conn_itvl_min, - hcc_params->conn_itvl_max, - hcc_params->conn_latency, - hcc_params->supervision_timeout); + rc = ble_ll_conn_hci_chk_conn_params(hcc.params[1].conn_itvl_min, + hcc.params[1].conn_itvl_max, + hcc.params[1].conn_latency, + hcc.params[1].supervision_timeout); if (rc) { return rc; } - iter += 8; /* Min/max connection event lengths */ - hcc_params->min_ce_len = get_le16(cmdbuf + iter); - hcc_params->max_ce_len = get_le16(cmdbuf + iter + 2); - if (hcc_params->min_ce_len > hcc_params->max_ce_len) { + hcc.params[1].min_ce_len = le16toh(params->min_ce); + hcc.params[1].max_ce_len = le16toh(params->max_ce); + if (hcc.params[1].min_ce_len > hcc.params[1].max_ce_len) { return BLE_ERR_INV_HCI_CMD_PARMS; } - iter += 4; + params++; } #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { - /* validate length */ - if (cmdlen < iter + 16) { + if (hcc.init_phy_mask & BLE_PHY_MASK_CODED) { + if (len < sizeof(*params)) { return BLE_ERR_INV_HCI_CMD_PARMS; } + len -= sizeof(*params); - hcc_params = &hcc->params[2]; - hcc_params->scan_itvl = get_le16(cmdbuf + iter); - hcc_params->scan_window = get_le16(cmdbuf + iter + 2); - iter += 4; + hcc.params[2].scan_itvl = le16toh(params->scan_itvl); + hcc.params[2].scan_window = le16toh(params->scan_window); - rc = ble_ll_conn_hci_chk_scan_params(hcc_params->scan_itvl, - hcc_params->scan_window); + rc = ble_ll_conn_hci_chk_scan_params(hcc.params[2].scan_itvl, + hcc.params[2].scan_window); if (rc) { return rc; } - hcc_params->conn_itvl_min = get_le16(cmdbuf + iter); - hcc_params->conn_itvl_max = get_le16(cmdbuf + iter + 2); - hcc_params->conn_latency = get_le16(cmdbuf + iter + 4); - hcc_params->supervision_timeout = get_le16(cmdbuf + iter + 6); - rc = ble_ll_conn_hci_chk_conn_params(hcc_params->conn_itvl_min, - hcc_params->conn_itvl_max, - hcc_params->conn_latency, - hcc_params->supervision_timeout); + hcc.params[2].conn_itvl_min = le16toh(params->conn_min_itvl); + hcc.params[2].conn_itvl_max = le16toh(params->conn_min_itvl); + hcc.params[2].conn_latency = le16toh(params->conn_latency); + hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout); + + rc = ble_ll_conn_hci_chk_conn_params(hcc.params[2].conn_itvl_min, + hcc.params[2].conn_itvl_max, + hcc.params[2].conn_latency, + hcc.params[2].supervision_timeout); if (rc) { return rc; } - iter += 8; /* Min/max connection event lengths */ - hcc_params->min_ce_len = get_le16(cmdbuf + iter); - hcc_params->max_ce_len = get_le16(cmdbuf + iter + 2); - if (hcc_params->min_ce_len > hcc_params->max_ce_len) { + hcc.params[2].min_ce_len = le16toh(params->min_ce); + hcc.params[2].max_ce_len = le16toh(params->max_ce); + if (hcc.params[2].min_ce_len > hcc.params[2].max_ce_len) { return BLE_ERR_INV_HCI_CMD_PARMS; } - iter += 4; - if (valid_param_idx < 0) { - valid_param_idx = 2; + if (!fallback_params) { + fallback_params = &hcc.params[2]; } + params++; } #endif @@ -724,16 +738,16 @@ ble_ll_ext_conn_create(uint8_t *cmdbuf, uint8_t cmdlen) return BLE_ERR_CONN_LIMIT; } - ble_ll_conn_init_hcc_params(hcc, valid_param_idx); + ble_ll_conn_hcc_params_set_fallback(&hcc, fallback_params); /* Initialize state machine in master role and start state machine */ - ble_ll_conn_ext_master_init(connsm, hcc); + ble_ll_conn_ext_master_init(connsm, &hcc); ble_ll_conn_sm_new(connsm); /* CSA will be selected when advertising is received */ /* Start scanning */ - rc = ble_ll_scan_ext_initiator_start(hcc, &connsm->scansm); + rc = ble_ll_scan_ext_initiator_start(&hcc, &connsm->scansm); if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); @@ -747,7 +761,8 @@ ble_ll_ext_conn_create(uint8_t *cmdbuf, uint8_t cmdlen) #endif static int -ble_ll_conn_process_conn_params(uint8_t *cmdbuf, struct ble_ll_conn_sm *connsm) +ble_ll_conn_process_conn_params(const struct ble_hci_le_rem_conn_param_rr_cp *cmd, + struct ble_ll_conn_sm *connsm) { int rc; struct hci_conn_update *hcu; @@ -755,12 +770,15 @@ ble_ll_conn_process_conn_params(uint8_t *cmdbuf, struct ble_ll_conn_sm *connsm) /* Retrieve command data */ hcu = &connsm->conn_param_req; hcu->handle = connsm->conn_handle; - hcu->conn_itvl_min = get_le16(cmdbuf + 2); - hcu->conn_itvl_max = get_le16(cmdbuf + 4); - hcu->conn_latency = get_le16(cmdbuf + 6); - hcu->supervision_timeout = get_le16(cmdbuf + 8); - hcu->min_ce_len = get_le16(cmdbuf + 10); - hcu->max_ce_len = get_le16(cmdbuf + 12); + + BLE_LL_ASSERT(connsm->conn_handle == le16toh(cmd->conn_handle)); + + hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); + hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); + hcu->conn_latency = le16toh(cmd->conn_latency); + hcu->supervision_timeout = le16toh(cmd->supervision_timeout); + hcu->min_ce_len = le16toh(cmd->min_ce); + hcu->max_ce_len = le16toh(cmd->max_ce); /* Check that parameter values are in range */ rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min, @@ -770,7 +788,6 @@ ble_ll_conn_process_conn_params(uint8_t *cmdbuf, struct ble_ll_conn_sm *connsm) /* Check valid min/max ce length */ if (rc || (hcu->min_ce_len > hcu->max_ce_len)) { - hcu->handle = 0; return BLE_ERR_INV_HCI_CMD_PARMS; } return rc; @@ -784,14 +801,17 @@ ble_ll_conn_process_conn_params(uint8_t *cmdbuf, struct ble_ll_conn_sm *connsm) * @return int */ int -ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf) +ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) { - uint16_t handle; + const struct ble_hci_le_rd_rem_feat_cp *cmd = (const void *) cmdbuf; struct ble_ll_conn_sm *connsm; + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* If no connection handle exit with error */ - handle = get_le16(cmdbuf); - connsm = ble_ll_conn_find_active_conn(handle); + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); if (!connsm) { return BLE_ERR_UNK_CONN_ID; } @@ -828,8 +848,9 @@ ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf) * @return int */ int -ble_ll_conn_hci_update(uint8_t *cmdbuf) +ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) { + const struct ble_hci_le_conn_update_cp *cmd = (const void *) cmdbuf; int rc; uint8_t ctrl_proc; uint16_t handle; @@ -846,7 +867,7 @@ ble_ll_conn_hci_update(uint8_t *cmdbuf) */ /* If no connection handle exit with error */ - handle = get_le16(cmdbuf); + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { return BLE_ERR_UNK_CONN_ID; @@ -898,13 +919,12 @@ ble_ll_conn_hci_update(uint8_t *cmdbuf) /* Retrieve command data */ hcu = &connsm->conn_param_req; - hcu->handle = handle; - hcu->conn_itvl_min = get_le16(cmdbuf + 2); - hcu->conn_itvl_max = get_le16(cmdbuf + 4); - hcu->conn_latency = get_le16(cmdbuf + 6); - hcu->supervision_timeout = get_le16(cmdbuf + 8); - hcu->min_ce_len = get_le16(cmdbuf + 10); - hcu->max_ce_len = get_le16(cmdbuf + 12); + hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); + hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); + hcu->conn_latency = le16toh(cmd->conn_latency); + hcu->supervision_timeout = le16toh(cmd->supervision_timeout); + hcu->min_ce_len = le16toh(cmd->min_ce_len); + hcu->max_ce_len = le16toh(cmd->max_ce_len); if (hcu->min_ce_len > hcu->max_ce_len) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -915,6 +935,8 @@ ble_ll_conn_hci_update(uint8_t *cmdbuf) hcu->conn_latency, hcu->supervision_timeout); if (!rc) { + hcu->handle = handle; + /* Start the control procedure */ ble_ll_ctrl_proc_start(connsm, ctrl_proc); } @@ -923,19 +945,23 @@ ble_ll_conn_hci_update(uint8_t *cmdbuf) } int -ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int positive_reply, - uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { + const struct ble_hci_le_rem_conn_param_rr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rem_conn_param_rr_rp *rsp = (void *) rspbuf; int rc; - uint8_t ble_err; uint8_t *dptr; uint8_t rsp_opcode; - uint8_t len; uint16_t handle; struct os_mbuf *om; struct ble_ll_conn_sm *connsm; - handle = get_le16(cmdbuf); + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); /* See if we support this feature */ if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { @@ -950,20 +976,13 @@ ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int positive_reply, goto done; } - /* Make sure connection parameters are valid if this is a positive reply */ - rc = BLE_ERR_SUCCESS; - ble_err = cmdbuf[2]; - if (positive_reply) { - rc = ble_ll_conn_process_conn_params(cmdbuf, connsm); - if (rc) { - ble_err = BLE_ERR_CONN_PARMS; - } - } + /* Make sure connection parameters are valid */ + rc = ble_ll_conn_process_conn_params(cmd, connsm); /* The connection should be awaiting a reply. If not, just discard */ if (connsm->csmflags.cfbit.awaiting_host_reply) { /* Get a control packet buffer */ - if (positive_reply && (rc == BLE_ERR_SUCCESS)) { + if (rc == BLE_ERR_SUCCESS) { om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PAYLOAD + 1, sizeof(struct ble_mbuf_hdr)); if (om) { @@ -977,18 +996,71 @@ ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int positive_reply, } else { /* XXX: check return code and deal */ ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, - ble_err); + BLE_ERR_CONN_PARMS); } connsm->csmflags.cfbit.awaiting_host_reply = 0; /* XXX: if we cant get a buffer, what do we do? We need to remember * reason if it was a negative reply. We also would need to have - some state to tell us this happened */ + * some state to tell us this happened + */ } done: - put_le16(rspbuf, handle); - *rsplen = sizeof(uint16_t); + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +int +ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rem_conn_params_nrr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rem_conn_params_nrr_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + + /* See if we support this feature */ + if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { + rc = BLE_ERR_UNKNOWN_HCI_CMD; + goto done; + } + + /* If we dont have a handle we cant do anything */ + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto done; + } + + rc = BLE_ERR_SUCCESS; + + /* The connection should be awaiting a reply. If not, just discard */ + if (connsm->csmflags.cfbit.awaiting_host_reply) { + /* XXX: check return code and deal */ + ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, + cmd->reason); + connsm->csmflags.cfbit.awaiting_host_reply = 0; + + /* XXX: if we cant get a buffer, what do we do? We need to remember + * reason if it was a negative reply. We also would need to have + * some state to tell us this happened + */ + } + +done: + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); return rc; } @@ -1056,21 +1128,24 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) * @return int */ int -ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf) +ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len) { int rc; - uint8_t reason; uint16_t handle; struct ble_ll_conn_sm *connsm; + const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } /* Check for valid parameters */ - handle = get_le16(cmdbuf); - reason = cmdbuf[2]; + handle = le16toh(cmd->conn_handle); rc = BLE_ERR_INV_HCI_CMD_PARMS; if (handle <= BLE_LL_CONN_MAX_CONN_HANDLE) { /* Make sure reason is valid */ - switch (reason) { + switch (cmd->reason) { case BLE_ERR_AUTH_FAIL: case BLE_ERR_REM_USER_CONN_TERM: case BLE_ERR_RD_CONN_TERM_RESRCS: @@ -1088,7 +1163,7 @@ ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf) BLE_LL_ASSERT(CONN_F_TERMINATE_STARTED(connsm) == 0); /* Record the disconnect reason */ - connsm->disconnect_reason = reason; + connsm->disconnect_reason = cmd->reason; /* Start this control procedure */ ble_ll_ctrl_terminate_start(connsm); @@ -1117,14 +1192,17 @@ ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf) * @return int */ int -ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t *cmdbuf) +ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len) { - uint16_t handle; struct ble_ll_conn_sm *connsm; + const struct ble_hci_rd_rem_ver_info_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } /* Check for valid parameters */ - handle = get_le16(cmdbuf); - connsm = ble_ll_conn_find_active_conn(handle); + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); if (!connsm) { return BLE_ERR_UNK_CONN_ID; } @@ -1160,28 +1238,30 @@ ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t *cmdbuf) * @return int */ int -ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen) { - int rc; - int8_t rssi; - uint16_t handle; - struct ble_ll_conn_sm *connsm; - handle = get_le16(cmdbuf); - connsm = ble_ll_conn_find_active_conn(handle); + const struct ble_hci_rd_rssi_cp *cmd = (const void *) cmdbuf; + struct ble_hci_rd_rssi_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rsp->handle = cmd->handle; + + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->handle)); if (!connsm) { - rssi = 127; + rsp->rssi = 127; rc = BLE_ERR_UNK_CONN_ID; } else { - rssi = connsm->conn_rssi; + rsp->rssi = connsm->conn_rssi; rc = BLE_ERR_SUCCESS; } - put_le16(rspbuf, handle); - rspbuf[2] = (uint8_t)rssi; - *rsplen = 3; - - /* Place the RSSI of the connection into the response buffer */ + *rsplen = sizeof(*rsp); return rc; } @@ -1195,27 +1275,36 @@ ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) * @return int */ int -ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { - int rc; - uint16_t handle; + const struct ble_hci_le_rd_chan_map_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rd_chan_map_rp *rsp = (void *) rspbuf; struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; - handle = get_le16(cmdbuf); + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; + memset(rsp->chan_map, 0, sizeof(rsp->chan_map)); } else { if (connsm->csmflags.cfbit.chanmap_update_scheduled) { - memcpy(rspbuf + 2, &connsm->req_chanmap[0], BLE_LL_CONN_CHMAP_LEN); + memcpy(rsp->chan_map, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN); } else { - memcpy(rspbuf + 2, &connsm->chanmap[0], BLE_LL_CONN_CHMAP_LEN); + memcpy(rsp->chan_map, connsm->chanmap, BLE_LL_CONN_CHMAP_LEN); } rc = BLE_ERR_SUCCESS; } - put_le16(rspbuf, handle); - *rsplen = sizeof(uint16_t) + BLE_LL_CONN_CHMAP_LEN; + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); return rc; } @@ -1227,47 +1316,57 @@ ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) * @return int */ int -ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf) +ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len) { - int rc; + const struct ble_hci_le_set_host_chan_class_cp *cmd = (const void *) cmdbuf; uint8_t num_used_chans; + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* * The HCI command states that the host is allowed to mask in just one * channel but the Link Layer needs minimum two channels to operate. So * I will not allow this command if there are less than 2 channels masked. */ - rc = BLE_ERR_SUCCESS; - num_used_chans = ble_ll_utils_calc_num_used_chans(cmdbuf); - if ((num_used_chans < 2) || ((cmdbuf[4] & 0xe0) != 0)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; + num_used_chans = ble_ll_utils_calc_num_used_chans(cmd->chan_map); + if ((num_used_chans < 2) || ((cmd->chan_map[4] & 0xe0) != 0)) { + return BLE_ERR_INV_HCI_CMD_PARMS; } /* Set the host channel mask */ - ble_ll_conn_set_global_chanmap(num_used_chans, cmdbuf); - return rc; + ble_ll_conn_set_global_chanmap(num_used_chans, cmd->chan_map); + return BLE_ERR_SUCCESS; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) int -ble_ll_conn_hci_set_data_len(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { + const struct ble_hci_le_set_data_len_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_set_data_len_rp *rsp = (void *) rspbuf; int rc; uint16_t handle; uint16_t txoctets; uint16_t txtime; struct ble_ll_conn_sm *connsm; + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* Find connection */ - handle = get_le16(cmdbuf); + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; goto done; } - txoctets = get_le16(cmdbuf + 2); - txtime = get_le16(cmdbuf + 4); + txoctets = le16toh(cmd->tx_octets); + txtime = le16toh(cmd->tx_time); /* Make sure it is valid */ if (!ble_ll_chk_txrx_octets(txoctets) || @@ -1287,8 +1386,8 @@ ble_ll_conn_hci_set_data_len(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) } done: - put_le16(rspbuf, handle); - *rsplen = sizeof(uint16_t); + rsp->conn_handle = htole16(handle); + *rsplen = sizeof(*rsp); return rc; } #endif @@ -1302,14 +1401,17 @@ done: * @return int */ int -ble_ll_conn_hci_le_start_encrypt(uint8_t *cmdbuf) +ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len) { - int rc; - uint16_t handle; + const struct ble_hci_le_start_encrypt_cp *cmd = (const void *) cmdbuf; struct ble_ll_conn_sm *connsm; + int rc; - handle = get_le16(cmdbuf); - connsm = ble_ll_conn_find_active_conn(handle); + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; } else if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { @@ -1323,9 +1425,9 @@ ble_ll_conn_hci_le_start_encrypt(uint8_t *cmdbuf) rc = BLE_ERR_CMD_DISALLOWED; } else { /* Start the control procedure */ - connsm->enc_data.host_rand_num = get_le64(cmdbuf + 2); - connsm->enc_data.enc_div = get_le16(cmdbuf + 10); - swap_buf(connsm->enc_data.enc_block.key, cmdbuf + 12, 16); + connsm->enc_data.host_rand_num = le64toh(cmd->rand); + connsm->enc_data.enc_div = le16toh(cmd->div); + swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT); rc = BLE_ERR_SUCCESS; } @@ -1345,14 +1447,21 @@ ble_ll_conn_hci_le_start_encrypt(uint8_t *cmdbuf) * @return int */ int -ble_ll_conn_hci_le_ltk_reply(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { - int rc; - uint16_t handle; + const struct ble_hci_le_lt_key_req_reply_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_lt_key_req_reply_rp *rsp = (void *) rspbuf; struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } /* Find connection handle */ - handle = get_le16(cmdbuf); + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; @@ -1371,14 +1480,15 @@ ble_ll_conn_hci_le_ltk_reply(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) goto ltk_key_cmd_complete; } - swap_buf(connsm->enc_data.enc_block.key, cmdbuf + 2, 16); + swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); ble_ll_calc_session_key(connsm); ble_ll_ctrl_start_enc_send(connsm); rc = BLE_ERR_SUCCESS; ltk_key_cmd_complete: - put_le16(rspbuf, handle); - *rsplen = sizeof(uint16_t); + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); return rc; } @@ -1394,15 +1504,21 @@ ltk_key_cmd_complete: * @return int */ int -ble_ll_conn_hci_le_ltk_neg_reply(uint8_t *cmdbuf, uint8_t *rspbuf, - uint8_t *rsplen) +ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { - int rc; - uint16_t handle; + const struct ble_hci_le_lt_key_req_neg_reply_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_lt_key_req_neg_reply_rp *rsp = (void *) rspbuf; struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } /* Find connection handle */ - handle = get_le16(cmdbuf); + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; @@ -1429,8 +1545,9 @@ ble_ll_conn_hci_le_ltk_neg_reply(uint8_t *cmdbuf, uint8_t *rspbuf, rc = BLE_ERR_SUCCESS; ltk_key_cmd_complete: - put_le16(rspbuf, handle); - *rsplen = sizeof(uint16_t); + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); return rc; } #endif @@ -1445,23 +1562,33 @@ ltk_key_cmd_complete: * @return int */ int -ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen) +ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { - int rc; - uint16_t handle; + const struct ble_hci_cb_rd_auth_pyld_tmo_cp *cmd = (const void *) cmdbuf; + struct ble_hci_cb_rd_auth_pyld_tmo_rp *rsp = (void *) rspbuf; struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; - handle = get_le16(cmdbuf); + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; + rsp->tmo = 0; } else { - put_le16(rsp + 2, connsm->auth_pyld_tmo); rc = BLE_ERR_SUCCESS; + rsp->tmo = htole16(connsm->auth_pyld_tmo); } - put_le16(rsp, handle); - *rsplen = BLE_HCI_RD_AUTH_PYLD_TMO_LEN; + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); return rc; } @@ -1474,44 +1601,50 @@ ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen) * @return int */ int -ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen) +ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { - int rc; + const struct ble_hci_cb_wr_auth_pyld_tmo_cp *cmd = (const void *) cmdbuf; + struct ble_hci_cb_wr_auth_pyld_tmo_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint32_t min_tmo; uint16_t handle; uint16_t tmo; - uint32_t min_tmo; - struct ble_ll_conn_sm *connsm; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } rc = BLE_ERR_SUCCESS; - handle = get_le16(cmdbuf); + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; - goto wr_auth_exit; - } - - /* - * The timeout is in units of 10 msecs. We need to make sure that the - * timeout is greater than or equal to connItvl * (1 + slaveLatency) - */ - tmo = get_le16(cmdbuf + 2); - min_tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; - min_tmo *= (connsm->slave_latency + 1); - min_tmo /= 10000; - - if (tmo < min_tmo) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; } else { - connsm->auth_pyld_tmo = tmo; - if (ble_npl_callout_is_active(&connsm->auth_pyld_timer)) { - ble_ll_conn_auth_pyld_timer_start(connsm); + /* + * The timeout is in units of 10 msecs. We need to make sure that the + * timeout is greater than or equal to connItvl * (1 + slaveLatency) + */ + tmo = le16toh(cmd->tmo); + min_tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; + min_tmo *= (connsm->slave_latency + 1); + min_tmo /= 10000; + + if (tmo < min_tmo) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + } else { + connsm->auth_pyld_tmo = tmo; + if (ble_npl_callout_is_active(&connsm->auth_pyld_timer)) { + ble_ll_conn_auth_pyld_timer_start(connsm); + } } } -wr_auth_exit: - put_le16(rsp, handle); - *rsplen = BLE_HCI_WR_AUTH_PYLD_TMO_LEN; + rsp->conn_handle = htole16(handle); + *rsplen = sizeof(*rsp); return rc; } #endif @@ -1526,24 +1659,34 @@ wr_auth_exit: * @return int */ int -ble_ll_conn_hci_le_rd_phy(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen) +ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) { + const struct ble_hci_le_rd_phy_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rd_phy_rp *rsp = (void *) rspbuf; int rc; uint16_t handle; struct ble_ll_conn_sm *connsm; - handle = get_le16(cmdbuf); + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { + rsp->tx_phy = 0; + rsp->rx_phy = 0; rc = BLE_ERR_UNK_CONN_ID; } else { - rsp[2] = connsm->phy_data.cur_tx_phy; - rsp[3] = connsm->phy_data.cur_rx_phy; + rsp->tx_phy = connsm->phy_data.cur_tx_phy; + rsp->rx_phy = connsm->phy_data.cur_rx_phy; rc = BLE_ERR_SUCCESS; } - put_le16(rsp, handle); - *rsplen = BLE_HCI_LE_RD_PHY_RSPLEN; + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); return rc; } @@ -1555,8 +1698,9 @@ ble_ll_conn_hci_le_rd_phy(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen) * @return int */ int -ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf) +ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len) { + const struct ble_hci_le_set_phy_cp *cmd = (const void *) cmdbuf; int rc; uint16_t phy_options; uint8_t tx_phys; @@ -1564,7 +1708,11 @@ ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf) uint16_t handle; struct ble_ll_conn_sm *connsm; - handle = get_le16(cmdbuf); + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); connsm = ble_ll_conn_find_active_conn(handle); if (!connsm) { return BLE_ERR_UNK_CONN_ID; @@ -1578,13 +1726,14 @@ ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf) return BLE_ERR_CMD_DISALLOWED; } - phy_options = get_le16(cmdbuf + 5); + phy_options = le16toh(cmd->phy_options); if (phy_options > BLE_HCI_LE_PHY_CODED_S8_PREF) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Check valid parameters */ - rc = ble_ll_hci_chk_phy_masks(cmdbuf + 2, &tx_phys, &rx_phys); + rc = ble_ll_hci_chk_phy_masks(cmd->all_phys, cmd->tx_phys, cmd->rx_phys, + &tx_phys, &rx_phys); if (rc) { goto phy_cmd_param_err; } diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index 00b2eb550..c3e94ae64 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -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 } diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c index b0da5f9cf..3e10c78e1 100644 --- a/nimble/controller/src/ble_ll_dtm.c +++ b/nimble/controller/src/ble_ll_dtm.c @@ -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); diff --git a/nimble/controller/src/ble_ll_dtm_priv.h b/nimble/controller/src/ble_ll_dtm_priv.h index d6633f158..e04af07be 100644 --- a/nimble/controller/src/ble_ll_dtm_priv.h +++ b/nimble/controller/src/ble_ll_dtm_priv.h @@ -24,8 +24,12 @@ #include #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); diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 817d8631c..eb865b5fc 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -48,9 +48,9 @@ static void ble_ll_hci_cmd_proc(struct ble_npl_event *ev); static struct ble_npl_event g_ble_ll_hci_cmd_ev; /* LE event mask */ -static uint8_t g_ble_ll_hci_le_event_mask[BLE_HCI_SET_LE_EVENT_MASK_LEN]; -static uint8_t g_ble_ll_hci_event_mask[BLE_HCI_SET_EVENT_MASK_LEN]; -static uint8_t g_ble_ll_hci_event_mask2[BLE_HCI_SET_EVENT_MASK_LEN]; +static uint64_t g_ble_ll_hci_le_event_mask; +static uint64_t g_ble_ll_hci_event_mask; +static uint64_t g_ble_ll_hci_event_mask2; static int16_t rx_path_pwr_compensation; static int16_t tx_path_pwr_compensation; @@ -96,7 +96,7 @@ ble_ll_hci_get_num_cmd_pkts(void) * @return int 0: success; -1 otherwise. */ int -ble_ll_hci_event_send(uint8_t *evbuf) +ble_ll_hci_event_send(struct ble_hci_ev *hci_ev) { int rc; @@ -104,13 +104,13 @@ ble_ll_hci_event_send(uint8_t *evbuf) hal_gpio_write(MYNEWT_VAL(BLE_LL_DBG_HCI_EV_PIN), 1); #endif - BLE_LL_ASSERT(BLE_HCI_EVENT_HDR_LEN + evbuf[1] <= BLE_LL_MAX_EVT_LEN); + BLE_LL_ASSERT(sizeof(*hci_ev) + hci_ev->length <= BLE_LL_MAX_EVT_LEN); /* Count number of events sent */ STATS_INC(ble_ll_stats, hci_events_sent); /* Send the event to the host */ - rc = ble_hci_trans_ll_evt_tx(evbuf); + rc = ble_hci_trans_ll_evt_tx((uint8_t *)hci_ev); #if MYNEWT_VAL(BLE_LL_DBG_HCI_EV_PIN) >= 0 hal_gpio_write(MYNEWT_VAL(BLE_LL_DBG_HCI_EV_PIN), 0); @@ -122,31 +122,26 @@ ble_ll_hci_event_send(uint8_t *evbuf) /** * Created and sends a command complete event with the no-op opcode to the * host. - * - * @return int 0: ok, ble error code otherwise. */ -int +void ble_ll_hci_send_noop(void) { - int rc; - uint8_t *evbuf; - uint16_t opcode; + struct ble_hci_ev_command_complete_nop *ev; + struct ble_hci_ev *hci_ev; - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (evbuf) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { /* Create a command complete event with a NO-OP opcode */ - opcode = 0; - evbuf[0] = BLE_HCI_EVCODE_COMMAND_COMPLETE; - evbuf[1] = 3; - evbuf[2] = ble_ll_hci_get_num_cmd_pkts(); - put_le16(evbuf + 3, opcode); - ble_ll_hci_event_send(evbuf); - rc = BLE_ERR_SUCCESS; - } else { - rc = BLE_ERR_MEM_CAPACITY; - } + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; - return rc; + hci_ev->length = sizeof(*ev); + ev = (void *)hci_ev->data; + + ev->num_packets = ble_ll_hci_get_num_cmd_pkts(); + ev->opcode = BLE_HCI_OPCODE_NOP; + + ble_ll_hci_event_send(hci_ev); + } } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) @@ -160,23 +155,26 @@ ble_ll_hci_send_noop(void) * @return int */ static int -ble_ll_hci_le_encrypt(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_hci_le_encrypt(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, + uint8_t *rsplen) { - int rc; + const struct ble_hci_le_encrypt_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_encrypt_rp *rsp = (void *)rspbuf; struct ble_encryption_block ecb; + int rc; /* Call the link layer to encrypt the data */ - swap_buf(ecb.key, cmdbuf, BLE_ENC_BLOCK_SIZE); - swap_buf(ecb.plain_text, cmdbuf + BLE_ENC_BLOCK_SIZE, BLE_ENC_BLOCK_SIZE); + swap_buf(ecb.key, cmd->key, BLE_ENC_BLOCK_SIZE); + swap_buf(ecb.plain_text, cmd->data, BLE_ENC_BLOCK_SIZE); rc = ble_hw_encrypt_block(&ecb); if (!rc) { - swap_buf(rspbuf, ecb.cipher_text, BLE_ENC_BLOCK_SIZE); - *rsplen = BLE_ENC_BLOCK_SIZE; + swap_buf(rsp->data, ecb.cipher_text, BLE_ENC_BLOCK_SIZE); + *rsplen = sizeof(*rsp); rc = BLE_ERR_SUCCESS; } else { - *rsplen = 0; rc = BLE_ERR_CTLR_BUSY; } + return rc; } #endif @@ -193,11 +191,13 @@ ble_ll_hci_le_encrypt(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_le_rand(uint8_t *rspbuf, uint8_t *rsplen) { - int rc; + struct ble_hci_le_rand_rp *rsp = (void *) rspbuf; - rc = ble_ll_rand_data_get(rspbuf, BLE_HCI_LE_RAND_LEN); - *rsplen = BLE_HCI_LE_RAND_LEN; - return rc; + ble_ll_rand_data_get((uint8_t *)&rsp->random_number, + sizeof(rsp->random_number)); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; } /** @@ -211,21 +211,15 @@ ble_ll_hci_le_rand(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_rd_local_version(uint8_t *rspbuf, uint8_t *rsplen) { - uint16_t hci_rev; - uint16_t lmp_subver; - uint16_t mfrg; + struct ble_hci_ip_rd_local_ver_rp *rsp = (void *) rspbuf; - hci_rev = 0; - lmp_subver = 0; - mfrg = MYNEWT_VAL(BLE_LL_MFRG_ID); + rsp->hci_ver = BLE_HCI_VER_BCS_5_0; + rsp->hci_rev = 0; + rsp->lmp_ver = BLE_LMP_VER_BCS_5_0; + rsp->manufacturer = htole16(MYNEWT_VAL(BLE_LL_MFRG_ID)); + rsp->lmp_subver = 0; - /* Place the data packet length and number of packets in the buffer */ - rspbuf[0] = BLE_HCI_VER_BCS_5_0; - put_le16(rspbuf + 1, hci_rev); - rspbuf[3] = BLE_LMP_VER_BCS_5_0; - put_le16(rspbuf + 4, mfrg); - put_le16(rspbuf + 6, lmp_subver); - *rsplen = BLE_HCI_RD_LOC_VER_INFO_RSPLEN; + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -240,14 +234,16 @@ ble_ll_hci_rd_local_version(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_rd_local_supp_feat(uint8_t *rspbuf, uint8_t *rsplen) { + struct ble_hci_ip_rd_loc_supp_feat_rp *rsp = (void *) rspbuf; + /* - * The only two bits we set here currently are: + * The only two bits we set here currently are (5th byte): * BR/EDR not supported (bit 5) * LE supported (controller) (bit 6) */ - memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN); - rspbuf[4] = 0x60; - *rsplen = BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN; + rsp->features = htole64(0x0000006000000000); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -262,9 +258,12 @@ ble_ll_hci_rd_local_supp_feat(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_rd_local_supp_cmd(uint8_t *rspbuf, uint8_t *rsplen) { - memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN); - memcpy(rspbuf, g_ble_ll_supp_cmds, sizeof(g_ble_ll_supp_cmds)); - *rsplen = BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN; + struct ble_hci_ip_rd_loc_supp_cmd_rp *rsp = (void *) rspbuf; + + memset(rsp->commands, 0, sizeof(rsp->commands)); + memcpy(rsp->commands, g_ble_ll_supp_cmds, sizeof(g_ble_ll_supp_cmds)); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -280,12 +279,11 @@ ble_ll_hci_rd_local_supp_cmd(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_rd_bd_addr(uint8_t *rspbuf, uint8_t *rsplen) { - /* - * XXX: for now, assume we always have a public device address. If we - * dont, we should set this to zero - */ - memcpy(rspbuf, g_dev_addr, BLE_DEV_ADDR_LEN); - *rsplen = BLE_DEV_ADDR_LEN; + struct ble_hci_ip_rd_bd_addr_rp *rsp = (void *) rspbuf; + + memcpy(rsp->addr, g_dev_addr, BLE_DEV_ADDR_LEN); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -301,10 +299,16 @@ ble_ll_hci_rd_bd_addr(uint8_t *rspbuf, uint8_t *rsplen) * @return int BLE_ERR_SUCCESS. Does not return any errors. */ static int -ble_ll_hci_set_le_event_mask(uint8_t *cmdbuf) +ble_ll_hci_set_le_event_mask(const uint8_t *cmdbuf, uint8_t len) { - /* Copy the data into the event mask */ - memcpy(g_ble_ll_hci_le_event_mask, cmdbuf, BLE_HCI_SET_LE_EVENT_MASK_LEN); + const struct ble_hci_le_set_event_mask_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_hci_le_event_mask = le64toh(cmd->event_mask); + return BLE_ERR_SUCCESS; } @@ -320,10 +324,12 @@ ble_ll_hci_set_le_event_mask(uint8_t *cmdbuf) static int ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) { - /* Place the data packet length and number of packets in the buffer */ - put_le16(rspbuf, g_ble_ll_data.ll_acl_pkt_size); - rspbuf[2] = g_ble_ll_data.ll_num_acl_pkts; - *rsplen = BLE_HCI_RD_BUF_SIZE_RSPLEN; + struct ble_hci_le_rd_buf_size_rp *rp = (void *) rspbuf; + + rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); + rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; + + *rsplen = sizeof(*rp); return BLE_ERR_SUCCESS; } @@ -331,31 +337,19 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) /** * Checks the preferred phy masks for validity and places the preferred masks * in the input phy masks - * - * @param cmdbuf Pointer to command buffer where phy masks are located - * @param txphy Pointer to output tx phy mask - * @param rxphy Pointer to output rx phy mask - * + * @return int BLE_ERR_SUCCESS or BLE_ERR_INV_HCI_CMD_PARMS or BLE_ERR_UNSUPPORTED */ int -ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy) +ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, + uint8_t *txphy, uint8_t *rxphy) { - uint8_t all_phys; - uint8_t rx_phys; - uint8_t tx_phys; - /* Check for RFU */ - if ((cmdbuf[1] & ~BLE_HCI_LE_PHY_PREF_MASK_ALL) || - (cmdbuf[2] & ~BLE_HCI_LE_PHY_PREF_MASK_ALL)) { + if ((tx_phys & ~BLE_HCI_LE_PHY_PREF_MASK_ALL) || + (rx_phys & ~BLE_HCI_LE_PHY_PREF_MASK_ALL)) { return BLE_ERR_UNSUPPORTED; } - /* Check for valid values */ - all_phys = cmdbuf[0]; - tx_phys = cmdbuf[1] & BLE_HCI_LE_PHY_PREF_MASK_ALL; - rx_phys = cmdbuf[2] & BLE_HCI_LE_PHY_PREF_MASK_ALL; - if ((!(all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) && (tx_phys == 0)) || (!(all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) && (rx_phys == 0))) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -396,11 +390,17 @@ ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy) * @return int */ static int -ble_ll_hci_le_set_def_phy(uint8_t *cmdbuf) +ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) { + const struct ble_hci_le_set_default_phy_cp *cmd = (const void *) cmdbuf; int rc; - rc = ble_ll_hci_chk_phy_masks(cmdbuf, &g_ble_ll_data.ll_pref_tx_phys, + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = ble_ll_hci_chk_phy_masks(cmd->all_phys, cmd->tx_phys, cmd->rx_phys, + &g_ble_ll_data.ll_pref_tx_phys, &g_ble_ll_data.ll_pref_rx_phys); return rc; } @@ -423,15 +423,20 @@ ble_ll_hci_le_set_def_phy(uint8_t *cmdbuf) * @return int BLE error code */ static int -ble_ll_hci_le_wr_sugg_data_len(uint8_t *cmdbuf) +ble_ll_hci_le_wr_sugg_data_len(const uint8_t *cmdbuf, uint8_t len) { - int rc; + const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void*) cmdbuf; uint16_t tx_oct; uint16_t tx_time; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } /* Get suggested octets and time */ - tx_oct = get_le16(cmdbuf); - tx_time = get_le16(cmdbuf + 2); + tx_oct = le16toh(cmd->max_tx_octets); + tx_time = le16toh(cmd->max_tx_time); /* If valid, write into suggested and change connection initial times */ if (ble_ll_chk_txrx_octets(tx_oct) && ble_ll_chk_txrx_time(tx_time)) { @@ -468,10 +473,13 @@ ble_ll_hci_le_wr_sugg_data_len(uint8_t *cmdbuf) static int ble_ll_hci_le_rd_sugg_data_len(uint8_t *rspbuf, uint8_t *rsplen) { + struct ble_hci_le_rd_sugg_def_data_len_rp *rsp = (void *) rspbuf; + /* Place the data packet length and number of packets in the buffer */ - put_le16(rspbuf, g_ble_ll_conn_params.sugg_tx_octets); - put_le16(rspbuf + 2, g_ble_ll_conn_params.sugg_tx_time); - *rsplen = BLE_HCI_RD_SUGG_DATALEN_RSPLEN; + rsp->max_tx_octets = htole16(g_ble_ll_conn_params.sugg_tx_octets); + rsp->max_tx_time = htole16(g_ble_ll_conn_params.sugg_tx_time); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -487,12 +495,15 @@ ble_ll_hci_le_rd_sugg_data_len(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_le_rd_max_data_len(uint8_t *rspbuf, uint8_t *rsplen) { + struct ble_hci_le_rd_max_data_len_rp *rsp = (void *)rspbuf; + /* Place the data packet length and number of packets in the buffer */ - put_le16(rspbuf, g_ble_ll_conn_params.supp_max_tx_octets); - put_le16(rspbuf + 2, g_ble_ll_conn_params.supp_max_tx_time); - put_le16(rspbuf + 4, g_ble_ll_conn_params.supp_max_rx_octets); - put_le16(rspbuf + 6, g_ble_ll_conn_params.supp_max_rx_time); - *rsplen = BLE_HCI_RD_MAX_DATALEN_RSPLEN; + rsp->max_tx_octests = htole16(g_ble_ll_conn_params.supp_max_tx_octets); + rsp->max_tx_time = htole16(g_ble_ll_conn_params.supp_max_tx_time); + rsp->max_rx_octests = htole16(g_ble_ll_conn_params.supp_max_rx_octets); + rsp->max_rx_time = htole16(g_ble_ll_conn_params.supp_max_rx_time); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } #endif @@ -509,11 +520,11 @@ ble_ll_hci_le_rd_max_data_len(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_le_read_local_features(uint8_t *rspbuf, uint8_t *rsplen) { - /* Add list of supported features. */ - memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN); - put_le32(rspbuf, ble_ll_read_supp_features()); + struct ble_hci_le_rd_loc_supp_feat_rp *rsp = (void *) rspbuf; - *rsplen = BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN; + rsp->features = htole64(ble_ll_read_supp_features()); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -529,41 +540,33 @@ ble_ll_hci_le_read_local_features(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_hci_le_read_supp_states(uint8_t *rspbuf, uint8_t *rsplen) { - uint64_t supp_states; + struct ble_hci_le_rd_supp_states_rp *rsp = (void *) rspbuf; /* Add list of supported states. */ - supp_states = ble_ll_read_supp_states(); - put_le64(rspbuf, supp_states); - *rsplen = BLE_HCI_RD_SUPP_STATES_RSPLEN; + rsp->states = htole64(ble_ll_read_supp_states()); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } + /** * Checks to see if a LE event has been disabled by the host. * * @param subev Sub-event code of the LE Meta event. Note that this can - * be a value from 0 to 63, inclusive. + * be a value from 1 to 64, inclusive. * * @return uint8_t 0: event is not enabled; otherwise event is enabled. */ -uint8_t -ble_ll_hci_is_le_event_enabled(int subev) +bool +ble_ll_hci_is_le_event_enabled(unsigned int subev) { - uint8_t enabled; - uint8_t bytenum; - uint8_t bitmask; - int bitpos; - /* The LE meta event must be enabled for any LE event to be enabled */ - enabled = 0; - bitpos = subev - 1; - if (g_ble_ll_hci_event_mask[7] & 0x20) { - bytenum = bitpos / 8; - bitmask = 1 << (bitpos & 0x7); - enabled = g_ble_ll_hci_le_event_mask[bytenum] & bitmask; + if (g_ble_ll_hci_event_mask & (1ull << (BLE_HCI_EVCODE_LE_META - 1))) { + return g_ble_ll_hci_le_event_mask & (1ull << (subev - 1)); } - return enabled; + return false; } /** @@ -577,28 +580,14 @@ ble_ll_hci_is_le_event_enabled(int subev) * * @return uint8_t 0: event is not enabled; otherwise event is enabled. */ -uint8_t -ble_ll_hci_is_event_enabled(int evcode) +bool +ble_ll_hci_is_event_enabled(unsigned int evcode) { - uint8_t enabled; - uint8_t bytenum; - uint8_t bitmask; - uint8_t *evptr; - int bitpos; - if (evcode >= 64) { - evptr = &g_ble_ll_hci_event_mask2[0]; - bitpos = evcode - 64; - } else { - evptr = &g_ble_ll_hci_event_mask[0]; - bitpos = evcode - 1; + return g_ble_ll_hci_event_mask2 & (1ull << (evcode - 64)); } - bytenum = bitpos / 8; - bitmask = 1 << (bitpos & 0x7); - enabled = evptr[bytenum] & bitmask; - - return enabled; + return g_ble_ll_hci_event_mask & (1ull << (evcode - 1)); } /** @@ -645,8 +634,11 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) static int ble_ll_adv_rd_max_adv_data_len(uint8_t *rspbuf, uint8_t *rsplen) { - put_le16(rspbuf, BLE_ADV_DATA_MAX_LEN); - *rsplen = BLE_HCI_RD_MAX_ADV_DATA_LEN; + struct ble_hci_le_rd_max_adv_data_len_rp *rsp = (void *) rspbuf; + + rsp->max_adv_data_len = htole16(BLE_ADV_DATA_MAX_LEN); + + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } @@ -661,15 +653,12 @@ ble_ll_adv_rd_max_adv_data_len(uint8_t *rspbuf, uint8_t *rsplen) static int ble_ll_adv_rd_sup_adv_sets(uint8_t *rspbuf, uint8_t *rsplen) { - rspbuf[0] = BLE_ADV_INSTANCES; - *rsplen = BLE_HCI_RD_NR_SUP_ADV_SETS; - return BLE_ERR_SUCCESS; -} + struct ble_hci_le_rd_num_of_adv_sets_rp *rsp = (void *)rspbuf; -static int -ble_ll_ext_adv_set_remove(uint8_t *cmd) -{ - return ble_ll_adv_remove(cmd[0]); + rsp->num_sets = BLE_ADV_INSTANCES; + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; } static bool @@ -736,40 +725,40 @@ ble_ll_is_valid_adv_mode(uint8_t ocf) static int ble_ll_read_tx_power(uint8_t *rspbuf, uint8_t *rsplen) { - int8_t min; - int8_t max; + struct ble_hci_le_rd_transmit_power_rp *rsp = (void *) rspbuf; - min = ble_phy_txpower_round(-127); - max = ble_phy_txpower_round(126); - - rspbuf[0] = min; - rspbuf[1] = max; - - *rsplen = 2; + rsp->min_tx_power = ble_phy_txpower_round(-127); + rsp->max_tx_power = ble_phy_txpower_round(126); + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } static int ble_ll_read_rf_path_compensation(uint8_t *rspbuf, uint8_t *rsplen) { - put_le16(rspbuf, tx_path_pwr_compensation); - *rsplen = sizeof(int16_t); + struct ble_hci_le_rd_rf_path_compensation_rp *rsp = (void *) rspbuf; - put_le16(rspbuf + 2, rx_path_pwr_compensation); - *rsplen += sizeof(int16_t); + rsp->rx_path_compensation = htole16(rx_path_pwr_compensation); + rsp->tx_path_compensation = htole16(tx_path_pwr_compensation); + *rsplen = sizeof(*rsp);; return BLE_ERR_SUCCESS; } static int -ble_ll_write_rf_path_compensation(const uint8_t *cmdbuf) +ble_ll_write_rf_path_compensation(const uint8_t *cmdbuf, uint8_t len) { + const struct ble_hci_le_wr_rf_path_compensation_cp *cmd = (const void *)cmdbuf; int16_t rx; int16_t tx; - tx = get_le16(cmdbuf); - rx = get_le16(cmdbuf + 2); + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + tx = le16toh(cmd->tx_path_compensation); + rx = le16toh(cmd->rx_path_compensation); if ((tx < -1280) || (tx > 1280) || (rx < -1280) || (rx > 1280)) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -804,44 +793,41 @@ ble_ll_get_tx_pwr_compensation(void) * 256 gets added to the return value. */ static int -ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, - ble_ll_hci_post_cmd_complete_cb *cb) +ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, + uint8_t *rspbuf, uint8_t *rsplen, + ble_ll_hci_post_cmd_complete_cb *cb) { int rc; - uint8_t len; - uint8_t *rspbuf; /* Assume error; if all pass rc gets set to 0 */ rc = BLE_ERR_INV_HCI_CMD_PARMS; - /* Get length from command */ - len = cmdbuf[sizeof(uint16_t)]; - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (!ble_ll_is_valid_adv_mode(ocf)) { rc = BLE_ERR_CMD_DISALLOWED; - goto ll_hci_le_cmd_exit; + + /* + * This code is here because we add 256 to the return code to denote + * that the reply to this command should be command status (as opposed to + * command complete). + * + * For unknown HCI command let us return always command status as per + * specification Bluetooth 5, Vol. 2, Chapter 4.4 + */ + if (ble_ll_hci_le_cmd_send_cmd_status(ocf)) { + rc += (BLE_ERR_MAX + 1); + } + + return rc; } #endif - /* - * The command response pointer points into the same buffer as the - * command data itself. That is fine, as each command reads all the data - * before crafting a response. - */ - rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN; - - /* Move past HCI command header */ - cmdbuf += BLE_HCI_CMD_HDR_LEN; - switch (ocf) { case BLE_HCI_OCF_LE_SET_EVENT_MASK: - if (len == BLE_HCI_SET_LE_EVENT_MASK_LEN) { - rc = ble_ll_hci_set_le_event_mask(cmdbuf); - } + rc = ble_ll_hci_set_le_event_mask(cmdbuf, len); break; case BLE_HCI_OCF_LE_RD_BUF_SIZE: - if (len == BLE_HCI_RD_BUF_SIZE_LEN) { + if (len == 0) { rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen); } break; @@ -851,18 +837,14 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_SET_RAND_ADDR: - if (len == BLE_HCI_SET_RAND_ADDR_LEN) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - rc = ble_ll_set_random_addr(cmdbuf, hci_adv_mode == ADV_MODE_EXT); + rc = ble_ll_set_random_addr(cmdbuf, len, hci_adv_mode == ADV_MODE_EXT); #else - rc = ble_ll_set_random_addr(cmdbuf, false); + rc = ble_ll_set_random_addr(cmdbuf, len, false); #endif - } break; case BLE_HCI_OCF_LE_SET_ADV_PARAMS: - if (len == BLE_HCI_SET_ADV_PARAM_LEN) { - rc = ble_ll_adv_set_adv_params(cmdbuf); - } + rc = ble_ll_adv_set_adv_params(cmdbuf, len); break; case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR: if (len == 0) { @@ -870,36 +852,22 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_SET_ADV_DATA: - if (len == BLE_HCI_SET_ADV_DATA_LEN) { - rc = ble_ll_adv_set_adv_data(cmdbuf, len, 0, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE); - } + rc = ble_ll_hci_set_adv_data(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: - if (len == BLE_HCI_SET_SCAN_RSP_DATA_LEN) { - rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, len, 0, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE); - } + rc = ble_ll_hci_set_scan_rsp_data(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_ADV_ENABLE: - if (len == BLE_HCI_SET_ADV_ENABLE_LEN) { - rc = ble_ll_adv_set_enable(0, cmdbuf[0], -1, 0); - } + rc = ble_ll_hci_adv_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: - if (len == BLE_HCI_SET_SCAN_PARAM_LEN) { - rc = ble_ll_scan_set_scan_params(cmdbuf); - } + rc = ble_ll_scan_set_scan_params(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: - if (len == BLE_HCI_SET_SCAN_ENABLE_LEN) { - rc = ble_ll_scan_set_enable(cmdbuf, 0); - } + rc = ble_ll_hci_scan_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_CREATE_CONN: - if (len == BLE_HCI_CREATE_CONN_LEN) { - rc = ble_ll_conn_create(cmdbuf); - } + rc = ble_ll_conn_create(cmdbuf, len); break; case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL: if (len == 0) { @@ -917,40 +885,26 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_ADD_WHITE_LIST: - if (len == BLE_HCI_ADD_WHITE_LIST_LEN) { - rc = ble_ll_whitelist_add(cmdbuf + 1, cmdbuf[0]); - } + rc = ble_ll_whitelist_add(cmdbuf, len); break; case BLE_HCI_OCF_LE_RMV_WHITE_LIST: - if (len == BLE_HCI_RMV_WHITE_LIST_LEN) { - rc = ble_ll_whitelist_rmv(cmdbuf + 1, cmdbuf[0]); - } + rc = ble_ll_whitelist_rmv(cmdbuf, len); break; case BLE_HCI_OCF_LE_CONN_UPDATE: - if (len == BLE_HCI_CONN_UPDATE_LEN) { - rc = ble_ll_conn_hci_update(cmdbuf); - } + rc = ble_ll_conn_hci_update(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS: - if (BLE_HCI_SET_HOST_CHAN_CLASS_LEN) { - rc = ble_ll_conn_hci_set_chan_class(cmdbuf); - } + rc = ble_ll_conn_hci_set_chan_class(cmdbuf, len); break; case BLE_HCI_OCF_LE_RD_CHAN_MAP: - if (len == BLE_HCI_RD_CHANMAP_LEN) { - rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_RD_REM_FEAT: - if (len == BLE_HCI_CONN_RD_REM_FEAT_LEN) { - rc = ble_ll_conn_hci_read_rem_features(cmdbuf); - } + rc = ble_ll_conn_hci_read_rem_features(cmdbuf, len); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) case BLE_HCI_OCF_LE_ENCRYPT: - if (len == BLE_HCI_LE_ENCRYPT_LEN) { - rc = ble_ll_hci_le_encrypt(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_hci_le_encrypt(cmdbuf, len, rspbuf, rsplen); break; #endif case BLE_HCI_OCF_LE_RAND: @@ -960,19 +914,13 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) case BLE_HCI_OCF_LE_START_ENCRYPT: - if (len == BLE_HCI_LE_START_ENCRYPT_LEN) { - rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf); - } + rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf, len); break; case BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY: - if (len == BLE_HCI_LT_KEY_REQ_REPLY_LEN) { - rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY: - if (len == BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN) { - rc = ble_ll_conn_hci_le_ltk_neg_reply(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_le_ltk_neg_reply(cmdbuf, len, rspbuf, rsplen); break; #endif case BLE_HCI_OCF_LE_RD_SUPP_STATES : @@ -982,12 +930,10 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, break; #if MYNEWT_VAL(BLE_LL_DTM) case BLE_HCI_OCF_LE_TX_TEST: - rc = ble_ll_dtm_tx_test(cmdbuf, len, false); + rc = ble_ll_hci_dtm_tx_test(cmdbuf, len); break; case BLE_HCI_OCF_LE_RX_TEST: - if (len == BLE_HCI_RX_TEST_LEN) { - rc = ble_ll_dtm_rx_test(cmdbuf, false); - } + rc = ble_ll_hci_dtm_rx_test(cmdbuf, len); break; case BLE_HCI_OCF_LE_TEST_END: if (len == 0) { @@ -996,20 +942,14 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, break; #endif case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR: - if (len == BLE_HCI_CONN_PARAM_REPLY_LEN) { - rc = ble_ll_conn_hci_param_reply(cmdbuf, 1, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_param_rr(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR: - if (len == BLE_HCI_CONN_PARAM_NEG_REPLY_LEN) { - rc = ble_ll_conn_hci_param_reply(cmdbuf, 0, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_param_nrr(cmdbuf, len, rspbuf, rsplen); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) case BLE_HCI_OCF_LE_SET_DATA_LEN: - if (len == BLE_HCI_SET_DATALEN_LEN) { - rc = ble_ll_conn_hci_set_data_len(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_set_data_len(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN: if (len == 0) { @@ -1017,21 +957,15 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN: - if (len == BLE_HCI_WR_SUGG_DATALEN_LEN) { - rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf); - } + rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf, len); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_OCF_LE_ADD_RESOLV_LIST : - if (len == BLE_HCI_ADD_TO_RESOLV_LIST_LEN) { - rc = ble_ll_resolv_list_add(cmdbuf); - } + case BLE_HCI_OCF_LE_ADD_RESOLV_LIST: + rc = ble_ll_resolv_list_add(cmdbuf, len); break; case BLE_HCI_OCF_LE_RMV_RESOLV_LIST: - if (len == BLE_HCI_RMV_FROM_RESOLV_LIST_LEN) { - rc = ble_ll_resolv_list_rmv(cmdbuf); - } + rc = ble_ll_resolv_list_rmv(cmdbuf, len); break; case BLE_HCI_OCF_LE_CLR_RESOLV_LIST: if (len == 0) { @@ -1044,24 +978,16 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR: - if (len == BLE_HCI_RD_PEER_RESOLV_ADDR_LEN) { - rc = ble_ll_resolv_peer_addr_rd(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_resolv_peer_addr_rd(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR: - if(len == BLE_HCI_RD_LOC_RESOLV_ADDR_LEN) { - rc = ble_ll_resolv_local_addr_rd(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_resolv_local_addr_rd(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_SET_ADDR_RES_EN: - if (len == BLE_HCI_SET_ADDR_RESOL_ENA_LEN) { - rc = ble_ll_resolv_enable_cmd(cmdbuf); - } + rc = ble_ll_resolv_enable_cmd(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_RPA_TMO: - if (len == BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN) { - rc = ble_ll_resolv_set_rpa_tmo(cmdbuf); - } + rc = ble_ll_resolv_set_rpa_tmo(cmdbuf, len); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) @@ -1073,52 +999,37 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, #endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) case BLE_HCI_OCF_LE_RD_PHY: - if (len == BLE_HCI_LE_RD_PHY_LEN) { - rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_SET_DEFAULT_PHY: - if (len == BLE_HCI_LE_SET_DEFAULT_PHY_LEN) { - rc = ble_ll_hci_le_set_def_phy(cmdbuf); - } + rc = ble_ll_hci_le_set_def_phy(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_PHY: - if (len == BLE_HCI_LE_SET_PHY_LEN) { - rc = ble_ll_conn_hci_le_set_phy(cmdbuf); - } + rc = ble_ll_conn_hci_le_set_phy(cmdbuf, len); break; #endif #if MYNEWT_VAL(BLE_LL_DTM) - case BLE_HCI_OCF_LE_ENH_RX_TEST: - if (len == BLE_HCI_LE_ENH_RX_TEST_LEN) { - rc = ble_ll_dtm_rx_test(cmdbuf, true); - } + case BLE_HCI_OCF_LE_RX_TEST_V2: + rc = ble_ll_hci_dtm_rx_test_v2(cmdbuf, len); break; - case BLE_HCI_OCF_LE_ENH_TX_TEST: - rc = ble_ll_dtm_tx_test(cmdbuf, len, true); + case BLE_HCI_OCF_LE_TX_TEST_V2: + rc = ble_ll_hci_dtm_tx_test_v2(cmdbuf, len); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR: - if (len == BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN) { - rc = ble_ll_adv_set_random_addr(cmdbuf + 1, cmdbuf[0]); - } + rc = ble_ll_adv_hci_set_random_addr(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: - if (len == BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN) { - rc = ble_ll_adv_ext_set_param(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_adv_ext_set_param(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: - /* variable length */ rc = ble_ll_adv_ext_set_adv_data(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA: - /* variable length */ rc = ble_ll_adv_ext_set_scan_rsp(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE: - /* variable length */ rc = ble_ll_adv_ext_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN: @@ -1132,9 +1043,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_REMOVE_ADV_SET: - if (len == BLE_HCI_LE_REMOVE_ADV_SET_LEN) { - rc = ble_ll_ext_adv_set_remove(cmdbuf); - } + rc = ble_ll_adv_remove(cmdbuf, len); break; case BLE_HCI_OCF_LE_CLEAR_ADV_SETS: if (len == 0) { @@ -1143,41 +1052,30 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS: - if (len == BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN) { - rc = ble_ll_adv_periodic_set_param(cmdbuf); - } + rc = ble_ll_adv_periodic_set_param(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA: - /* variable length */ rc = ble_ll_adv_periodic_set_data(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE: - if (len == BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN) { - rc = ble_ll_adv_periodic_enable(cmdbuf); - } + rc = ble_ll_adv_periodic_enable(cmdbuf, len); break; #endif #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: - /* variable length */ rc = ble_ll_set_ext_scan_params(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: - if (len == BLE_HCI_LE_SET_EXT_SCAN_ENABLE_LEN) { - rc = ble_ll_scan_set_enable(cmdbuf, 1); - } + rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_EXT_CREATE_CONN: - /* variable length */ rc = ble_ll_ext_conn_create(cmdbuf, len); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: - if (len == BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN) { - rc = ble_ll_sync_create(cmdbuf); - } + rc = ble_ll_sync_create(cmdbuf, len); break; case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL: if (len == 0) { @@ -1185,19 +1083,13 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC: - if (len == BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN) { - rc = ble_ll_sync_terminate(cmdbuf); - } + rc = ble_ll_sync_terminate(cmdbuf, len); break; case BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST: - if (len == BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN) { - rc = ble_ll_sync_list_add(cmdbuf); - } + rc = ble_ll_sync_list_add(cmdbuf, len); break; case BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST: - if (len == BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN) { - rc = ble_ll_sync_list_remove(cmdbuf); - } + rc = ble_ll_sync_list_remove(cmdbuf, len); break; case BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST: if (len == 0) { @@ -1217,15 +1109,11 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, rc = ble_ll_read_rf_path_compensation(rspbuf, rsplen); break; case BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION: - if (len == BLE_HCI_LE_WR_RF_PATH_COMPENSATION_LEN) { - rc = ble_ll_write_rf_path_compensation(cmdbuf); - } + rc = ble_ll_write_rf_path_compensation(cmdbuf, len); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) case BLE_HCI_OCF_LE_SET_PRIVACY_MODE: - if (len == BLE_HCI_LE_SET_PRIVACY_MODE_LEN) { - rc = ble_ll_resolve_set_priv_mode(cmdbuf); - } + rc = ble_ll_resolve_set_priv_mode(cmdbuf, len); break; #endif default: @@ -1233,9 +1121,6 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, break; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -ll_hci_le_cmd_exit: -#endif /* * This code is here because we add 256 to the return code to denote * that the reply to this command should be command status (as opposed to @@ -1259,40 +1144,25 @@ ll_hci_le_cmd_exit: * * @param cmdbuf Pointer to command buffer. Points to start of command header. * @param ocf Opcode command field. - * @param *rsplen Pointer to length of response * * @return int This function returns a BLE error code. If a command status * event should be returned as opposed to command complete, * 256 gets added to the return value. */ static int -ble_ll_hci_link_ctrl_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) +ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf) { int rc; - uint8_t len; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - - /* Get length from command */ - len = cmdbuf[sizeof(uint16_t)]; - - /* Move past HCI command header */ - cmdbuf += BLE_HCI_CMD_HDR_LEN; switch (ocf) { case BLE_HCI_OCF_DISCONNECT_CMD: - if (len == BLE_HCI_DISCONNECT_CMD_LEN) { - rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf); - } + rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len); /* Send command status instead of command complete */ rc += (BLE_ERR_MAX + 1); break; case BLE_HCI_OCF_RD_REM_VER_INFO: - if (len == sizeof(uint16_t)) { - rc = ble_ll_conn_hci_rd_rem_ver_cmd(cmdbuf); - } + rc = ble_ll_conn_hci_rd_rem_ver_cmd(cmdbuf, len); /* Send command status instead of command complete */ rc += (BLE_ERR_MAX + 1); break; @@ -1306,32 +1176,45 @@ ble_ll_hci_link_ctrl_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) } static int -ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) +ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_cb_set_event_mask_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_hci_event_mask = le64toh(cmd->event_mask); + + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_cb_set_event_mask2_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_hci_event_mask2 = le64toh(cmd->event_mask2); + + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, + uint8_t *rspbuf, uint8_t *rsplen) { int rc; - uint8_t len; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - uint8_t *rspbuf; -#endif /* Assume error; if all pass rc gets set to 0 */ rc = BLE_ERR_INV_HCI_CMD_PARMS; - /* Get length from command */ - len = cmdbuf[sizeof(uint16_t)]; - - /* Move past HCI command header */ - cmdbuf += BLE_HCI_CMD_HDR_LEN; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN; -#endif - switch (ocf) { case BLE_HCI_OCF_CB_SET_EVENT_MASK: - if (len == BLE_HCI_SET_EVENT_MASK_LEN) { - memcpy(g_ble_ll_hci_event_mask, cmdbuf, len); - rc = BLE_ERR_SUCCESS; - } + rc = ble_ll_hci_cb_set_event_mask(cmdbuf, len); break; case BLE_HCI_OCF_CB_RESET: if (len == 0) { @@ -1339,17 +1222,14 @@ ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) } break; case BLE_HCI_OCF_CB_SET_EVENT_MASK2: - if (len == BLE_HCI_SET_EVENT_MASK_LEN) { - memcpy(g_ble_ll_hci_event_mask2, cmdbuf, len); - rc = BLE_ERR_SUCCESS; - } + rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) case BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO: - rc = ble_ll_conn_hci_rd_auth_pyld_tmo(cmdbuf, rspbuf, rsplen); + rc = ble_ll_conn_hci_rd_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO: - rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, rspbuf, rsplen); + rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); break; #endif default: @@ -1361,28 +1241,14 @@ ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) } static int -ble_ll_hci_info_params_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) +ble_ll_hci_info_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, + uint16_t ocf, uint8_t *rspbuf, uint8_t *rsplen) { int rc; - uint8_t len; - uint8_t *rspbuf; /* Assume error; if all pass rc gets set to 0 */ rc = BLE_ERR_INV_HCI_CMD_PARMS; - /* Get length from command */ - len = cmdbuf[sizeof(uint16_t)]; - - /* - * The command response pointer points into the same buffer as the - * command data itself. That is fine, as each command reads all the data - * before crafting a response. - */ - rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN; - - /* Move past HCI command header */ - cmdbuf += BLE_HCI_CMD_HDR_LEN; - switch (ocf) { case BLE_HCI_OCF_IP_RD_LOCAL_VER: if (len == 0) { @@ -1413,33 +1279,15 @@ ble_ll_hci_info_params_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) } static int -ble_ll_hci_status_params_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) +ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, + uint16_t ocf, uint8_t *rspbuf, + uint8_t *rsplen) { int rc; - uint8_t len; - uint8_t *rspbuf; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - - /* Get length from command */ - len = cmdbuf[sizeof(uint16_t)]; - - /* - * The command response pointer points into the same buffer as the - * command data itself. That is fine, as each command reads all the data - * before crafting a response. - */ - rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN; - - /* Move past HCI command header */ - cmdbuf += BLE_HCI_CMD_HDR_LEN; switch (ocf) { case BLE_HCI_OCF_RD_RSSI: - if (len == sizeof(uint16_t)) { - rc = ble_ll_conn_hci_rd_rssi(cmdbuf, rspbuf, rsplen); - } + rc = ble_ll_conn_hci_rd_rssi(cmdbuf, len, rspbuf, rsplen); break; default: rc = BLE_ERR_UNKNOWN_HCI_CMD; @@ -1460,42 +1308,55 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) int rc; uint8_t ogf; uint8_t rsplen; - uint8_t *cmdbuf; + struct ble_hci_cmd *cmd; uint16_t opcode; uint16_t ocf; ble_ll_hci_post_cmd_complete_cb post_cb = NULL; + struct ble_hci_ev *hci_ev; + struct ble_hci_ev_command_status *cmd_status; + struct ble_hci_ev_command_complete *cmd_complete; + uint8_t *rspbuf; #if MYNEWT_VAL(BLE_LL_DBG_HCI_CMD_PIN) >= 0 hal_gpio_write(MYNEWT_VAL(BLE_LL_DBG_HCI_CMD_PIN), 1); #endif /* The command buffer is the event argument */ - cmdbuf = (uint8_t *)ble_npl_event_get_arg(ev); - BLE_LL_ASSERT(cmdbuf != NULL); + cmd = ble_npl_event_get_arg(ev); + BLE_LL_ASSERT(cmd != NULL); /* Get the opcode from the command buffer */ - opcode = get_le16(cmdbuf); + opcode = le16toh(cmd->opcode); ocf = BLE_HCI_OCF(opcode); ogf = BLE_HCI_OGF(opcode); + /* + * The command response pointer points into the same buffer as the + * command data itself. That is fine, as each command reads all the data + * before crafting a response. + * Also reuse cmd buffer for complete event + */ + hci_ev = (struct ble_hci_ev *) cmd; + rspbuf = hci_ev->data + sizeof(*cmd_complete); + /* Assume response length is zero */ rsplen = 0; switch (ogf) { case BLE_HCI_OGF_LINK_CTRL: - rc = ble_ll_hci_link_ctrl_cmd_proc(cmdbuf, ocf, &rsplen); + rc = ble_ll_hci_link_ctrl_cmd_proc(cmd->data, cmd->length, ocf); break; case BLE_HCI_OGF_CTLR_BASEBAND: - rc = ble_ll_hci_ctlr_bb_cmd_proc(cmdbuf, ocf, &rsplen); + rc = ble_ll_hci_ctlr_bb_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); break; case BLE_HCI_OGF_INFO_PARAMS: - rc = ble_ll_hci_info_params_cmd_proc(cmdbuf, ocf, &rsplen); + rc = ble_ll_hci_info_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); break; case BLE_HCI_OGF_STATUS_PARAMS: - rc = ble_ll_hci_status_params_cmd_proc(cmdbuf, ocf, &rsplen); + rc = ble_ll_hci_status_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); break; case BLE_HCI_OGF_LE: - rc = ble_ll_hci_le_cmd_proc(cmdbuf, ocf, &rsplen, &post_cb); + rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb); break; default: /* XXX: Need to support other OGF. For now, return unsupported */ @@ -1507,19 +1368,24 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) BLE_LL_ASSERT(rc >= 0); if (rc <= BLE_ERR_MAX) { /* Create a command complete event with status from command */ - cmdbuf[0] = BLE_HCI_EVCODE_COMMAND_COMPLETE; - cmdbuf[1] = 4 + rsplen; - cmdbuf[2] = ble_ll_hci_get_num_cmd_pkts(); - put_le16(cmdbuf + 3, opcode); - cmdbuf[5] = (uint8_t)rc; + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; + hci_ev->length = sizeof(*cmd_complete) + rsplen; + + cmd_complete = (void *) hci_ev->data; + cmd_complete->num_packets = ble_ll_hci_get_num_cmd_pkts(); + cmd_complete->opcode = htole16(opcode); + cmd_complete->status = (uint8_t) rc; } else { /* Create a command status event */ rc -= (BLE_ERR_MAX + 1); - cmdbuf[0] = BLE_HCI_EVCODE_COMMAND_STATUS; - cmdbuf[1] = 4; - cmdbuf[2] = (uint8_t)rc; - cmdbuf[3] = ble_ll_hci_get_num_cmd_pkts(); - put_le16(cmdbuf + 4, opcode); + + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_STATUS; + hci_ev->length = sizeof(*cmd_status); + + cmd_status = (void *) hci_ev->data; + cmd_status->status = (uint8_t)rc; + cmd_status->num_packets = ble_ll_hci_get_num_cmd_pkts(); + cmd_status->opcode = htole16(opcode); } /* Count commands and those in error */ @@ -1530,7 +1396,7 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) } /* Send the event (events cannot be masked) */ - ble_ll_hci_event_send(cmdbuf); + ble_ll_hci_event_send(hci_ev); /* Call post callback if set by command handler */ if (post_cb) { @@ -1599,18 +1465,14 @@ ble_ll_hci_init(void) ble_npl_event_init(&g_ble_ll_hci_cmd_ev, ble_ll_hci_cmd_proc, NULL); /* Set defaults for LE events: Vol 2 Part E 7.8.1 */ - g_ble_ll_hci_le_event_mask[0] = 0x1f; + g_ble_ll_hci_le_event_mask = 0x1f; /* Set defaults for controller/baseband events: Vol 2 Part E 7.3.1 */ - g_ble_ll_hci_event_mask[0] = 0xff; - g_ble_ll_hci_event_mask[1] = 0xff; - g_ble_ll_hci_event_mask[2] = 0xff; - g_ble_ll_hci_event_mask[3] = 0xff; - g_ble_ll_hci_event_mask[4] = 0xff; - g_ble_ll_hci_event_mask[5] = 0x1f; + g_ble_ll_hci_event_mask = 0x1fffffffffff; + /* Set page 2 to 0 */ - memset(g_ble_ll_hci_event_mask2, 0, BLE_HCI_SET_EVENT_MASK_LEN); + g_ble_ll_hci_event_mask2 = 0; /* reset RF path compensation values */ rx_path_pwr_compensation = 0; diff --git a/nimble/controller/src/ble_ll_hci_ev.c b/nimble/controller/src/ble_ll_hci_ev.c index 95f04a622..dbc50db98 100644 --- a/nimble/controller/src/ble_ll_hci_ev.c +++ b/nimble/controller/src/ble_ll_hci_ev.c @@ -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); } diff --git a/nimble/controller/src/ble_ll_resolv.c b/nimble/controller/src/ble_ll_resolv.c index 5983a6189..b65951e11 100644 --- a/nimble/controller/src/ble_ll_resolv.c +++ b/nimble/controller/src/ble_ll_resolv.c @@ -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; } /** diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 433388130..794f6849c 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -94,28 +94,6 @@ struct ble_ll_ext_adv_hdr uint8_t hdr[0]; }; -struct ble_ll_ext_adv_report { - /* We support one report per event for now */ - uint8_t event_meta; /* BLE_HCI_EVCODE_LE_META */ - uint8_t event_len; - uint8_t subevt; - uint8_t num_reports; - - uint16_t evt_type; - uint8_t addr_type; - uint8_t addr[6]; - uint8_t prim_phy; - uint8_t sec_phy; - uint8_t sid; - uint8_t tx_power; - int8_t rssi; - uint16_t per_adv_itvl; - uint8_t dir_addr_type; - uint8_t dir_addr[6]; - uint8_t adv_data_len; - uint8_t adv_data[0]; -} __attribute__((packed)); - /* * Structure used to store advertisers. This is used to limit sending scan * requests to the same advertiser and also to filter duplicate events sent @@ -425,43 +403,58 @@ ble_ll_scan_req_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static struct ble_ll_ext_adv_report * -ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report *copy_from) +/* if copy_from is provided new report is initialized with that instead of + * defaults + */ +static struct ble_hci_ev * +ble_ll_scan_get_ext_adv_report(struct ext_adv_report *copy_from) { - struct ble_ll_ext_adv_report *evt; + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; - evt = (struct ble_ll_ext_adv_report *) ble_hci_trans_buf_alloc( - BLE_HCI_TRANS_BUF_EVT_LO); - if (!evt) { + hci_ev = ( void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { return NULL; } - if (copy_from) { - memcpy(evt, copy_from, sizeof(*evt)); - } else { - memset(evt, 0, sizeof(*evt)); + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev) + sizeof(*report); + ev = (void *) hci_ev->data; - evt->event_meta = BLE_HCI_EVCODE_LE_META; - evt->subevt = BLE_HCI_LE_SUBEV_EXT_ADV_RPT; - /* We support only one report per event now */ - evt->num_reports = 1; - /* Init TX Power with "Not available" which is 127 */ - evt->tx_power = 127; - /* Init RSSI with "Not available" which is 127 */ - evt->rssi = 127; + memset(ev, 0, sizeof(*ev)); + ev->subev_code = BLE_HCI_LE_SUBEV_EXT_ADV_RPT; + /* We support only one report per event now */ + ev->num_reports = 1; + + report = ev->reports; + + if (copy_from) { + memcpy(report, copy_from, sizeof(*report)); + report->data_len = 0; + } else { + memset(report, 0, sizeof(*report)); + + report->pri_phy = BLE_PHY_1M; /* Init SID with "Not available" which is 0xFF */ - evt->sid = 0xFF; + report->sid = 0xFF; + /* Init TX Power with "Not available" which is 127 */ + report->tx_power = 127; + /* Init RSSI with "Not available" which is 127 */ + report->rssi = 127; /* Init address type with "anonymous" which is 0xFF */ - evt->addr_type = 0xFF; + report->addr_type = 0xFF; } - return evt; + return hci_ev; } static void ble_ll_scan_send_truncated_if_chained(struct ble_ll_aux_data *aux_data) { - struct ble_ll_ext_adv_report *evt; + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { return; @@ -475,26 +468,32 @@ ble_ll_scan_send_truncated_if_chained(struct ble_ll_aux_data *aux_data) } BLE_LL_ASSERT(aux_data->evt); - evt = aux_data->evt; + hci_ev = aux_data->evt; aux_data->evt = NULL; - evt->event_len = sizeof(*evt) - BLE_HCI_EVENT_HDR_LEN; - evt->evt_type = aux_data->evt_type; - evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); + hci_ev->length = sizeof(*ev) + sizeof(*report); + + ev = (void *) hci_ev->data; + report = ev->reports; + + report->data_len = 0; + + report->evt_type = aux_data->evt_type; + report->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); BLE_LL_AUX_SET_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT); if (BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_AUX_HAS_ADDRA)) { - memcpy(evt->addr, aux_data->addr, 6); - evt->addr_type = aux_data->addr_type; + memcpy(report->addr, aux_data->addr, 6); + report->addr_type = aux_data->addr_type; } if (BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_AUX_HAS_DIR_ADDRA)) { - memcpy(evt->dir_addr, aux_data->dir_addr, 6); - evt->dir_addr_type = aux_data->dir_addr_type; + memcpy(report->dir_addr, aux_data->dir_addr, 6); + report->dir_addr_type = aux_data->dir_addr_type; } - evt->sid = (aux_data->adi >> 12); - ble_ll_hci_event_send((uint8_t *)evt); + report->sid = aux_data->adi >> 12; + ble_ll_hci_event_send(hci_ev); } static int @@ -631,124 +630,185 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static int ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype, - uint8_t addr_type, uint8_t *addr, + const uint8_t *addr, uint8_t addr_type, uint8_t rssi, - uint8_t adv_data_len, struct os_mbuf *adv_data, - uint8_t *inita, uint8_t inita_type) + uint8_t adv_data_len, + struct os_mbuf *adv_data, + const uint8_t *inita, uint8_t inita_type) { - struct ble_ll_ext_adv_report *evt; + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { return -1; } - /* Drop packet if it does not fit into event buffer */ - if ((sizeof(*evt) + adv_data_len) + 1 > MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) { + /* Drop packet if adv data doesn't fit */ + if ((sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len) > BLE_HCI_MAX_DATA_LEN) { STATS_INC(ble_ll_stats, adv_evt_dropped); return -1; } - evt = ble_ll_scan_init_ext_adv_report(NULL); - if (!evt) { - return 0; + hci_ev = ble_ll_scan_get_ext_adv_report(NULL); + if (!hci_ev) { + return -1; } + ev = (void *) hci_ev->data; + report = ev->reports; + switch (evtype) { case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND: - evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND; + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND; break; case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND: - evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND; + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND; break; case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND: - evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND; + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND; break; case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP: - evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND; + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND; break; case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND: - evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND; + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND; break; default: BLE_LL_ASSERT(0); - break; + ble_hci_trans_buf_free((uint8_t *) hci_ev); + return -1; } - evt->addr_type = addr_type; - memcpy(evt->addr, addr, BLE_DEV_ADDR_LEN); - - evt->event_len = sizeof(*evt) - BLE_HCI_EVENT_HDR_LEN; + report->addr_type = addr_type; + memcpy(report->addr, addr, BLE_DEV_ADDR_LEN); + report->pri_phy = BLE_PHY_1M; + report->sid = 0xFF; + report->tx_power = 127; + report->rssi = rssi; if (inita) { - evt->dir_addr_type = inita_type; - memcpy(evt->dir_addr, inita, BLE_DEV_ADDR_LEN); - } else if (adv_data_len <= (MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE) - sizeof(*evt))) { - evt->adv_data_len = adv_data_len; - os_mbuf_copydata(adv_data, 0, adv_data_len, evt->adv_data); - evt->event_len += adv_data_len; + report->dir_addr_type = inita_type; + memcpy(report->dir_addr, inita, BLE_DEV_ADDR_LEN); } - evt->rssi = rssi; - evt->prim_phy = BLE_PHY_1M; + if (adv_data_len) { + hci_ev->length += adv_data_len; + report->data_len = adv_data_len; + os_mbuf_copydata(adv_data, 0, adv_data_len, report->data); + } - return ble_ll_hci_event_send((uint8_t *) evt); + return ble_ll_hci_event_send(hci_ev); } #endif static int -ble_ll_hci_send_adv_report(uint8_t subev, uint8_t evtype,uint8_t event_len, - uint8_t addr_type, uint8_t *addr, uint8_t rssi, - uint8_t adv_data_len, struct os_mbuf *adv_data, - uint8_t *inita, uint8_t inita_type) +ble_ll_hci_send_adv_report(uint8_t evtype, + const uint8_t *addr, uint8_t addr_type, int8_t rssi, + uint8_t adv_data_len, struct os_mbuf *adv_data) { - uint8_t *evbuf; - uint8_t *tmp; + struct ble_hci_ev_le_subev_adv_rpt *ev; + struct ble_hci_ev *hci_ev; + int8_t *ev_rssi; - if (!ble_ll_hci_is_le_event_enabled(subev)) { + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_RPT)) { return -1; } - /* Drop packet if it does not fit into event buffer */ - if (event_len + 1 > MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) { + /* Drop packet if adv data doesn't fit, note extra 1 is for RSSI */ + if ((sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len + 1) > BLE_HCI_MAX_DATA_LEN) { STATS_INC(ble_ll_stats, adv_evt_dropped); return -1; } - 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; } - evbuf[0] = BLE_HCI_EVCODE_LE_META; - evbuf[1] = event_len; - evbuf[2] = subev; - evbuf[3] = 1; /* number of reports */ - evbuf[4] = evtype; - evbuf[5] = addr_type; - memcpy(&evbuf[6], addr, BLE_DEV_ADDR_LEN); + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len + 1; + ev = (void *) hci_ev->data; - tmp = &evbuf[12]; - if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { - BLE_LL_ASSERT(inita); - tmp[0] = inita_type; - memcpy(tmp + 1, inita, BLE_DEV_ADDR_LEN); - tmp += BLE_DEV_ADDR_LEN + 1; - } else if (subev == BLE_HCI_LE_SUBEV_ADV_RPT) { - tmp[0] = adv_data_len; - os_mbuf_copydata(adv_data, 0, adv_data_len, tmp + 1); - tmp += adv_data_len + 1; - } else { - BLE_LL_ASSERT(0); - return -1; - } + ev->subev_code = BLE_HCI_LE_SUBEV_ADV_RPT; + ev->num_reports = 1; - tmp[0] = rssi; + ev->reports[0].type = evtype; + ev->reports[0].addr_type = addr_type; + memcpy(ev->reports[0].addr, addr, BLE_DEV_ADDR_LEN); + ev->reports[0].data_len = adv_data_len; + os_mbuf_copydata(adv_data, 0, adv_data_len, ev->reports[0].data); - return ble_ll_hci_event_send(evbuf); + /* RSSI is after adv data... */ + ev_rssi = (int8_t *) (hci_ev->data + sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len); + *ev_rssi = rssi; + + return ble_ll_hci_event_send(hci_ev); } -static int ble_ll_scan_dup_update_legacy(uint8_t addr_type, uint8_t *addr, uint8_t subev, - uint8_t evtype); +static int +ble_ll_hci_send_dir_adv_report(const uint8_t *addr, uint8_t addr_type, + const uint8_t *inita, uint8_t inita_type, + int8_t rssi) +{ + struct ble_hci_ev_le_subev_direct_adv_rpt *ev; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT)) { + return -1; + } + + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return -1; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev) + sizeof(*(ev->reports)); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT; + ev->num_reports = 1; + + ev->reports[0].type = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; + ev->reports[0].addr_type = addr_type; + memcpy(ev->reports[0].addr, addr, BLE_DEV_ADDR_LEN); + ev->reports[0].dir_addr_type = inita_type; + memcpy(ev->reports[0].dir_addr, inita, BLE_DEV_ADDR_LEN); + ev->reports[0].rssi = rssi; + + return ble_ll_hci_event_send(hci_ev); +} + +static int +ble_ll_scan_dup_update_legacy(uint8_t addr_type, const uint8_t *addr, + uint8_t subev, uint8_t evtype) +{ + struct ble_ll_scan_dup_entry *e; + uint8_t type; + + type = BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type); + + /* + * We assume ble_ll_scan_dup_check() was called before which either matched + * some entry or allocated new one and placed in on the top of queue. + */ + + e = TAILQ_FIRST(&g_scan_dup_list); + BLE_LL_ASSERT(e && e->type == type && !memcmp(e->addr, addr, 6)); + + if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { + e->flags |= BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT; + } else { + if (evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { + e->flags |= BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT; + } else { + e->flags |= BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; + } + } + + return 0; +} /** * Send an advertising report to the host. @@ -763,33 +823,27 @@ static int ble_ll_scan_dup_update_legacy(uint8_t addr_type, uint8_t *addr, uint8 * @param scansm */ static void -ble_ll_scan_send_adv_report(uint8_t pdu_type, uint8_t *adva, uint8_t adva_type, - uint8_t *inita, uint8_t inita_type, +ble_ll_scan_send_adv_report(uint8_t pdu_type, + const uint8_t *adva, uint8_t adva_type, + const uint8_t *inita, uint8_t inita_type, struct os_mbuf *om, struct ble_mbuf_hdr *hdr, struct ble_ll_scan_sm *scansm) { - int rc; - uint8_t *rxbuf = om->om_data; - uint8_t evtype; - uint8_t subev; + uint8_t subev = BLE_HCI_LE_SUBEV_ADV_RPT; uint8_t adv_data_len; - uint8_t event_len; + uint8_t evtype; + int rc; if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { if (ble_ll_is_rpa(inita, inita_type)) { - /* For resolvable we send separate event */ + /* For resolvable we send separate subevent */ subev = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT; - event_len = BLE_HCI_LE_ADV_DIRECT_RPT_LEN; - } else { - subev = BLE_HCI_LE_SUBEV_ADV_RPT; - event_len = BLE_HCI_LE_ADV_RPT_MIN_LEN; } - evtype = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; + evtype = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; adv_data_len = 0; } else { - subev = BLE_HCI_LE_SUBEV_ADV_RPT; if (pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) { evtype = BLE_HCI_ADV_RPT_EVTYPE_ADV_IND; } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND) { @@ -799,9 +853,7 @@ ble_ll_scan_send_adv_report(uint8_t pdu_type, uint8_t *adva, uint8_t adva_type, } else { evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP; } - adv_data_len = rxbuf[1]; - adv_data_len -= BLE_DEV_ADDR_LEN; - event_len = BLE_HCI_LE_ADV_RPT_MIN_LEN + adv_data_len; + adv_data_len = om->om_data[1] - BLE_DEV_ADDR_LEN; os_mbuf_adj(om, BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN); } @@ -820,25 +872,23 @@ ble_ll_scan_send_adv_report(uint8_t pdu_type, uint8_t *adva, uint8_t adva_type, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (scansm->ext_scanning) { rc = ble_ll_hci_send_legacy_ext_adv_report(evtype, - adva_type, adva, + adva, adva_type, hdr->rxinfo.rssi, adv_data_len, om, inita, inita_type); - } else { - rc = ble_ll_hci_send_adv_report(subev, evtype, event_len, - adva_type, adva, - hdr->rxinfo.rssi, - adv_data_len, om, - inita, inita_type); + goto done; } -#else - rc = ble_ll_hci_send_adv_report(subev, evtype, event_len, - adva_type, adva, - hdr->rxinfo.rssi, - adv_data_len, om, - inita, inita_type); #endif + if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { + rc = ble_ll_hci_send_dir_adv_report(adva, adva_type, inita, inita_type, + hdr->rxinfo.rssi); + goto done; + } + + rc = ble_ll_hci_send_adv_report(evtype, adva, adva_type, hdr->rxinfo.rssi, + adv_data_len, om); +done: if (!rc && scansm->scan_filt_dups) { ble_ll_scan_dup_update_legacy(adva_type, adva, subev, evtype); } @@ -1722,14 +1772,13 @@ ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf) } static void -ble_ll_ext_scan_parse_adv_info(struct ble_ll_scan_sm *scansm, - struct ble_ll_ext_adv_report *evt, uint8_t *buf) +ble_ll_ext_scan_parse_adv_info(struct ext_adv_report *report, const uint8_t *buf) { uint16_t adv_info = get_le16(buf); /* TODO Use DID */ - evt->sid = (adv_info >> 12); + report->sid = (adv_info >> 12); } /** @@ -1913,12 +1962,12 @@ ble_ll_scan_get_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf) * >= 0: Success (number of bytes left in PDU) * */ -int +static 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, + const uint8_t *adva, uint8_t adva_type, + const uint8_t *inita, uint8_t inita_type, struct ble_mbuf_hdr *ble_hdr, - struct ble_ll_ext_adv_report *out_evt) + struct ext_adv_report *report) { uint8_t pdu_len; uint8_t ext_hdr_len; @@ -1929,9 +1978,7 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, struct ble_ll_scan_sm *scansm; struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; - if (!out_evt) { - return -1; - } + BLE_LL_ASSERT(report); scansm = &g_ble_ll_scan_sm; @@ -1945,13 +1992,13 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, return -1; } - out_evt->evt_type = rxbuf[2] >> 6; - if (out_evt->evt_type > BLE_LL_EXT_ADV_MODE_SCAN) { + report->evt_type = rxbuf[2] >> 6; + if ( report->evt_type > BLE_LL_EXT_ADV_MODE_SCAN) { return -1; } if (BLE_MBUF_HDR_SCAN_RSP_RCV(ble_hdr)) { - out_evt->evt_type |= BLE_HCI_ADV_SCAN_RSP_MASK; + report->evt_type |= BLE_HCI_ADV_SCAN_RSP_MASK; } ext_hdr_len = rxbuf[2] & 0x3F; @@ -1967,8 +2014,8 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, } if (adva) { - memcpy(out_evt->addr, adva, 6); - out_evt->addr_type = adva_type; + memcpy(report->addr, adva, 6); + report->addr_type = adva_type; } if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { @@ -1976,9 +2023,9 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, } if (inita) { - memcpy(out_evt->dir_addr, inita, 6); - out_evt->dir_addr_type = inita_type; - out_evt->evt_type |= BLE_HCI_ADV_DIRECT_MASK; + memcpy(report->dir_addr, inita, 6); + report->dir_addr_type = inita_type; + report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; } if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_RFU_BIT)) { @@ -1987,10 +2034,10 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, } if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - ble_ll_ext_scan_parse_adv_info(scansm, out_evt, (ext_hdr + i)); + ble_ll_ext_scan_parse_adv_info(report, (ext_hdr + i)); i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } else if (out_evt->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { - out_evt->sid = (aux_data->adi >> 12); + } else if (report->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { + report->sid = (aux_data->adi >> 12); } /* In this point of time we don't want to care about aux ptr */ @@ -1999,12 +2046,12 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, } if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - out_evt->per_adv_itvl = get_le16(ext_hdr + i + 2); + report->periodic_itvl = get_le16(ext_hdr + i + 2); i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; } if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - out_evt->tx_power = *(ext_hdr + i); + report->tx_power = *(ext_hdr + i); i += BLE_LL_EXT_ADV_TX_POWER_SIZE; } @@ -2015,12 +2062,12 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, * advertising. */ if (!aux_data) { - out_evt->prim_phy = ble_hdr->rxinfo.phy; + report->pri_phy = ble_hdr->rxinfo.phy; goto done; } - out_evt->sec_phy = aux_data->aux_phy; - out_evt->prim_phy = aux_data->aux_primary_phy; + report->sec_phy = aux_data->aux_phy; + report->pri_phy = aux_data->aux_primary_phy; if (ext_hdr_len) { /* Adjust mbuf to contain advertising data only */ @@ -2031,8 +2078,8 @@ ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, * Note that in aux chain and aux scan response packets * we do miss original event type, which we need for advertising report. */ - aux_data->evt_type |= out_evt->evt_type; - out_evt->evt_type = aux_data->evt_type; + aux_data->evt_type |= report->evt_type; + report->evt_type = aux_data->evt_type; done: return pdu_len - ext_hdr_len - 1; @@ -2587,13 +2634,15 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, struct ble_mbuf_hdr *hdr) { struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; - struct ble_ll_ext_adv_report *evt; - struct ble_ll_ext_adv_report *next_evt; + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + struct ble_hci_ev *hci_ev_next; int offset; int datalen; int rc; bool need_event; - uint16_t max_event_len; + uint8_t max_data_len; if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { rc = -1; @@ -2606,16 +2655,20 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, * is the first event for this chain. */ if (aux_data && aux_data->evt) { - evt = aux_data->evt; + hci_ev = aux_data->evt; aux_data->evt = NULL; + + hci_ev->length = sizeof(*ev) + sizeof(*report); } else { - evt = ble_ll_scan_init_ext_adv_report(NULL); - if (!evt) { + hci_ev = ble_ll_scan_get_ext_adv_report(NULL); + if (!hci_ev) { rc = -1; goto done; } } + ev = (void *) hci_ev->data; + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) /* If RPA has been used, make sure we use correct address types * in the advertising report. @@ -2628,42 +2681,47 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, } #endif - datalen = ble_ll_scan_parse_ext_hdr(om, adva, adva_type, inita, inita_type, hdr, evt); + datalen = ble_ll_scan_parse_ext_hdr(om, adva, adva_type, inita, inita_type, + hdr, ev->reports); if (datalen < 0) { rc = -1; /* If we were in the middle of advertising report, let us send truncated report. */ if (aux_data && BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_SENT_EVENT_TO_HOST) && BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_AUX_CHAIN_BIT)) { - evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); + report = ev->reports; + + report->data_len = 0; + report->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); BLE_LL_AUX_SET_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT); - ble_ll_hci_event_send((uint8_t *)evt); + ble_ll_hci_event_send(hci_ev); goto done; } - ble_hci_trans_buf_free((uint8_t *)evt); + ble_hci_trans_buf_free((uint8_t *)hci_ev); goto done; } - /* 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) - sizeof(*report); offset = 0; - max_event_len = min(UINT8_MAX + BLE_HCI_EVENT_HDR_LEN, BLE_LL_MAX_EVT_LEN); do { need_event = false; - next_evt = NULL; + hci_ev_next = NULL; - evt->adv_data_len = min(max_event_len - sizeof(*evt), - datalen - offset); - /* Event len, should not contain event meta code and let itself */ - evt->event_len = (sizeof(*evt) - BLE_HCI_EVENT_HDR_LEN) + evt->adv_data_len; - evt->rssi = hdr->rxinfo.rssi; + ev = (void *) hci_ev->data; + report = ev->reports; - os_mbuf_copydata(om, offset, evt->adv_data_len, evt->adv_data); - offset += evt->adv_data_len; + report->data_len = min(max_data_len, datalen - offset); + + /* adjust event length */ + hci_ev->length += report->data_len; + report->rssi = hdr->rxinfo.rssi; + + os_mbuf_copydata(om, offset, report->data_len, report->data); + offset += report->data_len; if (offset < datalen) { @@ -2684,17 +2742,17 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, * We will need another event so let's try to allocate one now. If * we cannot do this, need to mark event as truncated. */ - next_evt = ble_ll_scan_init_ext_adv_report(evt); + hci_ev_next = ble_ll_scan_get_ext_adv_report(report); - if (next_evt) { - evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE); + if (hci_ev_next) { + report->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE); } else { - evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); + report->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); rc = -1; if (aux_data) { BLE_LL_AUX_SET_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT); if (!BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_SENT_EVENT_TO_HOST)) { - ble_hci_trans_buf_free((uint8_t *)evt); + ble_hci_trans_buf_free((uint8_t *)hci_ev); goto done; } } @@ -2702,11 +2760,11 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, } } else if (aux_data) { if (BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) { - evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); + report->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED); BLE_LL_AUX_SET_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT); rc = -1; } else if (BLE_LL_AUX_CHECK_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_BIT)) { - evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE); + report->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE); } else { rc = 0; } @@ -2714,7 +2772,7 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, rc = 0; } - ble_ll_hci_event_send((uint8_t *)evt); + ble_ll_hci_event_send(hci_ev); if (aux_data) { BLE_LL_AUX_SET_FLAG(aux_data, BLE_LL_SENT_EVENT_TO_HOST); @@ -2730,17 +2788,17 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, } } - evt = next_evt; - } while ((offset < datalen) && evt); + hci_ev = hci_ev_next; + } while ((offset < datalen) && hci_ev); BLE_LL_ASSERT(offset <= datalen); if (aux_data) { /* Store any event left for later use */ - aux_data->evt = evt; + aux_data->evt = hci_ev; } else { /* If it is empty beacon, evt shall be NULL */ - BLE_LL_ASSERT(!evt); + BLE_LL_ASSERT(!hci_ev); } done: @@ -2888,36 +2946,6 @@ ble_ll_scan_dup_check_legacy(uint8_t addr_type, uint8_t *addr, uint8_t pdu_type) return rc; } -static int -ble_ll_scan_dup_update_legacy(uint8_t addr_type, uint8_t *addr, uint8_t subev, - uint8_t evtype) -{ - struct ble_ll_scan_dup_entry *e; - uint8_t type; - - type = BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type); - - /* - * We assume ble_ll_scan_dup_check() was called before which either matched - * some entry or allocated new one and placed in on the top of queue. - */ - - e = TAILQ_FIRST(&g_scan_dup_list); - BLE_LL_ASSERT(e && e->type == type && !memcmp(e->addr, addr, 6)); - - if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { - e->flags |= BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT; - } else { - if (evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { - e->flags |= BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT; - } else { - e->flags |= BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; - } - } - - return 0; -} - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static int ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, @@ -3275,16 +3303,18 @@ scan_continue: } int -ble_ll_scan_set_scan_params(uint8_t *cmd) +ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) { - uint8_t scan_type; - uint8_t own_addr_type; - uint8_t filter_policy; + const struct ble_hci_le_set_scan_params_cp *cmd = (const void *)cmdbuf; uint16_t scan_itvl; uint16_t scan_window; struct ble_ll_scan_sm *scansm; struct ble_ll_scan_params *scanp; + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* If already enabled, we return an error */ scansm = &g_ble_ll_scan_sm; if (scansm->scan_enabled) { @@ -3292,15 +3322,12 @@ ble_ll_scan_set_scan_params(uint8_t *cmd) } /* Get the scan interval and window */ - scan_type = cmd[0]; - scan_itvl = get_le16(cmd + 1); - scan_window = get_le16(cmd + 3); - own_addr_type = cmd[5]; - filter_policy = cmd[6]; + scan_itvl = le16toh(cmd->scan_itvl); + scan_window = le16toh(cmd->scan_window); /* Check scan type */ - if ((scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) && - (scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) { + if ((cmd->scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) && + (cmd->scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -3314,23 +3341,23 @@ ble_ll_scan_set_scan_params(uint8_t *cmd) } /* Check own addr type */ - if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Check scanner filter policy */ - if (filter_policy > BLE_HCI_SCAN_FILT_MAX) { + if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Store scan parameters */ scanp = &g_ble_ll_scan_params[PHY_UNCODED]; scanp->configured = 1; - scanp->scan_type = scan_type; + scanp->scan_type = cmd->scan_type; scanp->scan_itvl = scan_itvl; scanp->scan_window = scan_window; - scanp->scan_filt_policy = filter_policy; - scanp->own_addr_type = own_addr_type; + scanp->scan_filt_policy = cmd->filter_policy; + scanp->own_addr_type = cmd->own_addr_type; #if (BLE_LL_SCAN_PHY_NUMBER == 2) g_ble_ll_scan_params[PHY_CODED].configured = 0; @@ -3362,59 +3389,59 @@ ble_ll_check_scan_params(uint8_t type, uint16_t itvl, uint16_t window) } int -ble_ll_set_ext_scan_params(uint8_t *cmd, uint8_t cmdlen) +ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) { + const struct ble_hci_le_set_ext_scan_params_cp *cmd = (const void *) cmdbuf; + const struct scan_params *params = cmd->scans; + struct ble_ll_scan_params new_params[BLE_LL_SCAN_PHY_NUMBER] = { }; struct ble_ll_scan_params *uncoded = &new_params[PHY_UNCODED]; struct ble_ll_scan_params *coded = &new_params[PHY_CODED]; - uint8_t idx; int rc; - if (cmdlen < 3) { + if (len <= sizeof(*cmd)) { return BLE_ERR_INV_HCI_CMD_PARMS; } + len -= sizeof(*cmd); + /* If already enabled, we return an error */ if (g_ble_ll_scan_sm.scan_enabled) { return BLE_ERR_CMD_DISALLOWED; } /* Check own addr type */ - if (cmd[0] > BLE_HCI_ADV_OWN_ADDR_MAX) { + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - coded->own_addr_type = cmd[0]; - uncoded->own_addr_type = cmd[0]; + coded->own_addr_type = cmd->own_addr_type; + uncoded->own_addr_type = cmd->own_addr_type; /* Check scanner filter policy */ - if (cmd[1] > BLE_HCI_SCAN_FILT_MAX) { + if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - coded->scan_filt_policy = cmd[1]; - uncoded->scan_filt_policy = cmd[1]; + coded->scan_filt_policy = cmd->filter_policy; + uncoded->scan_filt_policy = cmd->filter_policy; /* Check if no reserved bits in PHYS are set and that at least one valid PHY * is set. */ - if (!(cmd[2] & ble_ll_valid_scan_phy_mask) || - (cmd[2] & ~ble_ll_valid_scan_phy_mask)) { + if (!(cmd->phys & ble_ll_valid_scan_phy_mask) || + (cmd->phys & ~ble_ll_valid_scan_phy_mask)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - idx = 3; - if (cmd[2] & BLE_HCI_LE_PHY_1M_PREF_MASK) { - if (cmdlen < idx + 5) { + if (cmd->phys & BLE_HCI_LE_PHY_1M_PREF_MASK) { + if (len < sizeof(*params)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - uncoded->scan_type = cmd[idx]; - idx++; - uncoded->scan_itvl = get_le16(cmd + idx); - idx += 2; - uncoded->scan_window = get_le16(cmd + idx); - idx += 2; + uncoded->scan_type = params->type; + uncoded->scan_itvl = le16toh(params->itvl); + uncoded->scan_window = le16toh(params->window); rc = ble_ll_check_scan_params(uncoded->scan_type, uncoded->scan_itvl, @@ -3423,22 +3450,21 @@ ble_ll_set_ext_scan_params(uint8_t *cmd, uint8_t cmdlen) return rc; } - /* That means user whats to use this PHY for scanning */ + /* That means user wants to use this PHY for scanning */ uncoded->configured = 1; + params++; + len -= sizeof(*params); } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (cmd[2] & BLE_HCI_LE_PHY_CODED_PREF_MASK) { - if (cmdlen < idx + 5) { + if (cmd->phys & BLE_HCI_LE_PHY_CODED_PREF_MASK) { + if (len < sizeof(*params)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - coded->scan_type = cmd[idx]; - idx++; - coded->scan_itvl = get_le16(cmd + idx); - idx += 2; - coded->scan_window = get_le16(cmd + idx); - idx += 2; + coded->scan_type = params->type; + coded->scan_itvl = le16toh(params->itvl); + coded->scan_window = le16toh(params->window); rc = ble_ll_check_scan_params(coded->scan_type, coded->scan_itvl, @@ -3447,7 +3473,7 @@ ble_ll_set_ext_scan_params(uint8_t *cmd, uint8_t cmdlen) return rc; } - /* That means user whats to use this PHY for scanning */ + /* That means user wants to use this PHY for scanning */ coded->configured = 1; } #endif @@ -3525,20 +3551,17 @@ ble_ll_scan_period_timer_cb(void *arg) /** * ble ll scan set enable * - * HCI scan set enable command processing function + * HCI scan set enable command processing function * * Context: Link Layer task (HCI Command parser). * - * @param cmd Pointer to command buffer - * * @return int BLE error code. */ -int -ble_ll_scan_set_enable(uint8_t *cmd, uint8_t ext) +static int +ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, + uint16_t dur, bool ext) { int rc; - uint8_t filter_dups; - uint8_t enable; struct ble_ll_scan_sm *scansm; struct ble_ll_scan_params *scanp; struct ble_ll_scan_params *scanphy; @@ -3546,13 +3569,9 @@ ble_ll_scan_set_enable(uint8_t *cmd, uint8_t ext) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) uint32_t period_ticks = 0; uint32_t dur_ticks = 0; - uint16_t period; - uint16_t dur; #endif /* Check for valid parameters */ - enable = cmd[0]; - filter_dups = cmd[1]; if ((filter_dups > 1) || (enable > 1)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -3564,12 +3583,8 @@ ble_ll_scan_set_enable(uint8_t *cmd, uint8_t ext) scansm->ext_scanning = ext; if (ext) { - dur = get_le16(cmd + 2); - /* Period parameter is ignored when the Duration parameter is zero */ - if (dur) { - period = get_le16(cmd + 4); - } else { + if (!dur) { period = 0; } @@ -3678,6 +3693,33 @@ ble_ll_scan_set_enable(uint8_t *cmd, uint8_t ext) return rc; } +int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_scan_enable_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_scan_set_enable(cmd->enable, cmd->filter_duplicates, 0, 0, + false); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_ext_scan_enable_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_scan_set_enable(cmd->enable, cmd->filter_dup, + le16toh(cmd->period), le16toh(cmd->duration), + true); +} +#endif + /** * Checks if controller can change the whitelist. If scanning is enabled and * using the whitelist the controller is not allowed to change the whitelist. diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index c0c287ecf..9eb46db5b 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -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; } diff --git a/nimble/controller/src/ble_ll_whitelist.c b/nimble/controller/src/ble_ll_whitelist.c index 31b866589..04ec6428b 100644 --- a/nimble/controller/src/ble_ll_whitelist.c +++ b/nimble/controller/src/ble_ll_whitelist.c @@ -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; diff --git a/nimble/drivers/native/src/ble_hw.c b/nimble/drivers/native/src/ble_hw.c index 92c008155..5eb1eb95e 100644 --- a/nimble/drivers/native/src/ble_hw.c +++ b/nimble/drivers/native/src/ble_hw.c @@ -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; } diff --git a/nimble/drivers/nrf51/src/ble_hw.c b/nimble/drivers/nrf51/src/ble_hw.c index 0bf834cd1..3c7296b84 100644 --- a/nimble/drivers/nrf51/src/ble_hw.c +++ b/nimble/drivers/nrf51/src/ble_hw.c @@ -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; diff --git a/nimble/drivers/nrf52/src/ble_hw.c b/nimble/drivers/nrf52/src/ble_hw.c index 68104e444..82e6d17ed 100644 --- a/nimble/drivers/nrf52/src/ble_hw.c +++ b/nimble/drivers/nrf52/src/ble_hw.c @@ -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; diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index a23cdd458..6602e6199 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -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; /** diff --git a/nimble/host/include/host/ble_hs_adv.h b/nimble/host/include/host/ble_hs_adv.h index b0d85c02a..e3b6ea709 100644 --- a/nimble/host/include/host/ble_hs_adv.h +++ b/nimble/host/include/host/ble_hs_adv.h @@ -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); diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 5a16552ff..9a0f003ee 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -509,10 +509,9 @@ ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode) int ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy) { + struct ble_hci_le_rd_phy_cp cmd; + struct ble_hci_le_rd_phy_rp rsp; struct ble_hs_conn *conn; - uint8_t buf[BLE_HCI_LE_RD_PHY_LEN]; - uint8_t rspbuf[4]; - uint8_t rsplen; int rc; ble_hs_lock(); @@ -523,25 +522,21 @@ ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy) return BLE_HS_ENOTCONN; } - rc = ble_hs_hci_cmd_build_le_read_phy(conn_handle, buf, sizeof(buf)); - if (rc != 0) { - return rc; - } + cmd.conn_handle = htole16(conn_handle); rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_PHY), - buf, sizeof(buf), rspbuf, sizeof(rspbuf), &rsplen); + &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (rc != 0) { return rc; } - if (rsplen != sizeof(rspbuf)) { + /* sanity check for response */ + if (le16toh(rsp.conn_handle) != conn_handle) { return BLE_HS_ECONTROLLER; } - /* First two octets is conn_handle. We can ignore it */ - - *tx_phy = rspbuf[2]; - *rx_phy = rspbuf[3]; + *tx_phy = rsp.tx_phy; + *rx_phy = rsp.rx_phy; return 0; } @@ -549,27 +544,45 @@ ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy) int ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask) { - uint8_t buf[BLE_HCI_LE_SET_DEFAULT_PHY_LEN]; - int rc; + struct ble_hci_le_set_default_phy_cp cmd; - rc = ble_hs_hci_cmd_build_le_set_default_phy(tx_phys_mask, rx_phys_mask, - buf, sizeof(buf)); - if (rc != 0) { - return rc; + if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (rx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + memset(&cmd, 0, sizeof(cmd)); + + if (tx_phys_mask == 0) { + cmd.all_phys |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK; + } else { + cmd.tx_phys = tx_phys_mask; + } + + if (rx_phys_mask == 0) { + cmd.all_phys |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK; + } else { + cmd.rx_phys = rx_phys_mask; } return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DEFAULT_PHY), - buf, sizeof(buf), NULL, 0, NULL); + &cmd, sizeof(cmd), NULL, 0); } int ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask, uint8_t rx_phys_mask, uint16_t phy_opts) { + struct ble_hci_le_set_phy_cp cmd; struct ble_hs_conn *conn; - uint8_t buf[BLE_HCI_LE_SET_PHY_LEN]; - int rc; ble_hs_lock(); conn = ble_hs_conn_find(conn_handle); @@ -579,16 +592,41 @@ ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask, return BLE_HS_ENOTCONN; } - rc = ble_hs_hci_cmd_build_le_set_phy(conn_handle, tx_phys_mask, - rx_phys_mask, phy_opts, buf, - sizeof(buf)); - if (rc != 0) { - return rc; + if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; } - return ble_hs_hci_cmd_tx( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PHY), - buf, sizeof(buf), NULL, 0, NULL); + if (rx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (phy_opts > BLE_HCI_LE_PHY_CODED_S8_PREF) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + memset(&cmd, 0, sizeof(cmd)); + cmd.conn_handle = htole16(conn_handle); + + if (tx_phys_mask == 0) { + cmd.all_phys |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK; + } else { + cmd.tx_phys = tx_phys_mask; + } + + if (rx_phys_mask == 0) { + cmd.all_phys |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK; + } else { + cmd.rx_phys = rx_phys_mask; + } + + cmd.phy_options = htole16(phy_opts); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PHY), + &cmd, sizeof(cmd), NULL, 0); } /***************************************************************************** @@ -746,30 +784,6 @@ ble_gap_adv_finished(uint8_t instance, int reason, uint16_t conn_handle, } } -#if MYNEWT_VAL(BLE_EXT_ADV) -static void -ble_gap_scan_req_rcvd(uint8_t instance, uint8_t scan_addr_type, - uint8_t *scan_addr) -{ - struct ble_gap_event event; - ble_gap_event_fn *cb; - void *cb_arg; - - memset(&event, 0, sizeof event); - event.type = BLE_GAP_EVENT_SCAN_REQ_RCVD; - event.scan_req_rcvd.instance = instance; - event.scan_req_rcvd.scan_addr.type = scan_addr_type; - memcpy(event.scan_req_rcvd.scan_addr.val, scan_addr, 6); - - ble_gap_slave_extract_cb(instance, &cb, &cb_arg); - if (cb != NULL) { - cb(&event, cb_arg); - } - - ble_gap_event_listener_call(&event); -} -#endif - static int ble_gap_master_connect_failure(int status) { @@ -1079,32 +1093,32 @@ ble_gap_update_to_l2cap(const struct ble_gap_upd_params *params, } void -ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt) +ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev) { #if !NIMBLE_BLE_CONNECT return; #endif struct ble_gap_event event; + uint16_t handle = le16toh(ev->conn_handle); STATS_INC(ble_gap_stats, rx_disconnect); - if (evt->status == 0) { - ble_gap_conn_broken(evt->connection_handle, - BLE_HS_HCI_ERR(evt->reason)); + if (ev->status == 0) { + ble_gap_conn_broken(handle, BLE_HS_HCI_ERR(ev->reason)); } else { memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_TERM_FAILURE; - event.term_failure.conn_handle = evt->connection_handle; - event.term_failure.status = BLE_HS_HCI_ERR(evt->status); + event.term_failure.conn_handle = handle; + event.term_failure.status = BLE_HS_HCI_ERR(ev->status); ble_gap_event_listener_call(&event); - ble_gap_call_conn_event_cb(&event, evt->connection_handle); + ble_gap_call_conn_event_cb(&event, handle); } } void -ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt) +ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev) { #if !NIMBLE_BLE_CONNECT return; @@ -1114,6 +1128,7 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt) struct ble_l2cap_sig_update_params l2cap_params; struct ble_gap_event event; struct ble_hs_conn *conn; + uint16_t conn_handle; int cb_status; int call_cb; int rc; @@ -1125,14 +1140,16 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt) ble_hs_lock(); - conn = ble_hs_conn_find(evt->connection_handle); + conn_handle = le16toh(ev->conn_handle); + + conn = ble_hs_conn_find(conn_handle); if (conn != NULL) { - switch (evt->status) { + switch (ev->status) { case 0: /* Connection successfully updated. */ - conn->bhc_itvl = evt->conn_itvl; - conn->bhc_latency = evt->conn_latency; - conn->bhc_supervision_timeout = evt->supervision_timeout; + conn->bhc_itvl = le16toh(ev->conn_itvl); + conn->bhc_latency = le16toh(ev->conn_latency); + conn->bhc_supervision_timeout = le16toh(ev->supervision_timeout); break; case BLE_ERR_UNSUPP_REM_FEATURE: @@ -1141,7 +1158,7 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt) * Request Procedure. If we are the slave, fail over to the L2CAP * update procedure. */ - entry = ble_gap_update_entry_find(evt->connection_handle, NULL); + entry = ble_gap_update_entry_find(conn_handle, NULL); if (entry != NULL && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { ble_gap_update_to_l2cap(&entry->params, &l2cap_params); entry->exp_os_ticks = ble_npl_time_get() + @@ -1156,15 +1173,14 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt) /* We aren't failing over to L2CAP, the update procedure is complete. */ if (l2cap_params.itvl_min == 0) { - entry = ble_gap_update_entry_remove(evt->connection_handle); + entry = ble_gap_update_entry_remove(conn_handle); ble_gap_update_entry_free(entry); } ble_hs_unlock(); if (l2cap_params.itvl_min != 0) { - rc = ble_l2cap_sig_update(evt->connection_handle, - &l2cap_params, + rc = ble_l2cap_sig_update(conn_handle, &l2cap_params, ble_gap_update_l2cap_cb, NULL); if (rc == 0) { call_cb = 0; @@ -1174,11 +1190,11 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt) } } else { call_cb = 1; - cb_status = BLE_HS_HCI_ERR(evt->status); + cb_status = BLE_HS_HCI_ERR(ev->status); } if (call_cb) { - ble_gap_update_notify(evt->connection_handle, cb_status); + ble_gap_update_notify(conn_handle, cb_status); } } @@ -1251,7 +1267,7 @@ ble_gap_accept_slave_conn(uint8_t instance) } static int -ble_gap_rx_adv_report_sanity_check(uint8_t *adv_data, uint8_t adv_data_len) +ble_gap_rx_adv_report_sanity_check(const uint8_t *adv_data, uint8_t adv_data_len) { const struct ble_hs_adv_field *flags; int rc; @@ -1311,29 +1327,40 @@ 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) +ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev) { uint16_t conn_handle; int reason; /* Currently spec allows only 0x3c and 0x43 when advertising was stopped * due to timeout or events limit, mp this for timeout error for now */ - if (evt->status) { + if (ev->status) { reason = BLE_HS_ETIMEOUT; conn_handle = 0; } else { reason = 0; - conn_handle = evt->conn_handle; + conn_handle = le16toh(ev->conn_handle); } - ble_gap_adv_finished(evt->adv_handle, reason, conn_handle, - evt->completed_events); + ble_gap_adv_finished(ev->adv_handle, reason, conn_handle, ev->num_events); } void -ble_gap_rx_scan_req_rcvd(struct hci_le_scan_req_rcvd *evt) +ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev) { - ble_gap_scan_req_rcvd(evt->adv_handle, evt->scan_addr_type, evt->scan_addr); + struct ble_gap_event event; + ble_gap_event_fn *cb; + void *cb_arg; + + ble_gap_slave_extract_cb(ev->adv_handle, &cb, &cb_arg); + if (cb != NULL) { + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_SCAN_REQ_RCVD; + event.scan_req_rcvd.instance = ev->adv_handle; + event.scan_req_rcvd.scan_addr.type = ev->peer_addr_type; + memcpy(event.scan_req_rcvd.scan_addr.val, ev->peer_addr, BLE_DEV_ADDR_LEN); + cb(&event, cb_arg); + } } #endif @@ -1341,8 +1368,9 @@ ble_gap_rx_scan_req_rcvd(struct hci_le_scan_req_rcvd *evt) #if MYNEWT_VAL(BLE_PERIODIC_ADV) void -ble_gap_rx_peroidic_adv_sync_estab(struct hci_le_subev_periodic_adv_sync_estab *evt) +ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev) { + uint16_t sync_handle = le16toh(ev->sync_handle); struct ble_gap_event event; ble_gap_event_fn *cb; void *cb_arg; @@ -1350,27 +1378,27 @@ ble_gap_rx_peroidic_adv_sync_estab(struct hci_le_subev_periodic_adv_sync_estab * memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_PERIODIC_SYNC; - event.periodic_sync.status = evt->status; + event.periodic_sync.status = ev->status; ble_hs_lock(); BLE_HS_DBG_ASSERT(ble_gap_sync.psync); - if (!evt->status) { - ble_gap_sync.psync->sync_handle = evt->sync_handle; - ble_gap_sync.psync->adv_sid = evt->sid; - memcpy(ble_gap_sync.psync->advertiser_addr.val, evt->adv_addr, 6); - ble_gap_sync.psync->advertiser_addr.type = evt->adv_addr_type; + if (!ev->status) { + ble_gap_sync.psync->sync_handle = sync_handle; + ble_gap_sync.psync->adv_sid = ev->sid; + memcpy(ble_gap_sync.psync->advertiser_addr.val, ev->peer_addr, 6); + ble_gap_sync.psync->advertiser_addr.type = ev->peer_addr_type; ble_gap_sync.psync->cb = ble_gap_sync.cb; ble_gap_sync.psync->cb_arg = ble_gap_sync.cb_arg; - event.periodic_sync.sync_handle = evt->sync_handle; - event.periodic_sync.sid = evt->sid; + event.periodic_sync.sync_handle = sync_handle; + event.periodic_sync.sid = ev->sid; event.periodic_sync.adv_addr = ble_gap_sync.psync->advertiser_addr; - event.periodic_sync.adv_phy = evt->adv_phy; - event.periodic_sync.per_adv_ival = evt->per_adv_ival; - event.periodic_sync.adv_clk_accuracy = evt->adv_clk_accuracy; + event.periodic_sync.adv_phy = ev->phy; + event.periodic_sync.per_adv_ival = ev->interval; + event.periodic_sync.adv_clk_accuracy = ev->aca; ble_hs_periodic_sync_insert(ble_gap_sync.psync); } else { @@ -1394,7 +1422,7 @@ ble_gap_rx_peroidic_adv_sync_estab(struct hci_le_subev_periodic_adv_sync_estab * } void -ble_gap_rx_periodic_adv_rpt(struct hci_le_subev_periodic_adv_rpt *evt) +ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev) { struct ble_hs_periodic_sync *psync; struct ble_gap_event event; @@ -1402,7 +1430,7 @@ ble_gap_rx_periodic_adv_rpt(struct hci_le_subev_periodic_adv_rpt *evt) void *cb_arg; ble_hs_lock(); - psync = ble_hs_periodic_sync_find_by_handle(evt->sync_handle); + psync = ble_hs_periodic_sync_find_by_handle(le16toh(ev->sync_handle)); if (psync) { cb = psync->cb; cb_arg = psync->cb_arg; @@ -1416,12 +1444,12 @@ ble_gap_rx_periodic_adv_rpt(struct hci_le_subev_periodic_adv_rpt *evt) memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_PERIODIC_REPORT; - event.periodic_report.sync_handle = evt->sync_handle; - event.periodic_report.tx_power = evt->tx_power; - event.periodic_report.rssi = evt->rssi; - event.periodic_report.data_status = evt->data_status; - event.periodic_report.data_length = evt->data_length; - event.periodic_report.data = evt->data; + event.periodic_report.sync_handle = psync->sync_handle; + event.periodic_report.tx_power = ev->tx_power; + event.periodic_report.rssi = ev->rssi; + event.periodic_report.data_status = ev->data_status; + event.periodic_report.data_length = ev->data_len; + event.periodic_report.data = ev->data; /* TODO should we allow for listener too? this can be spammy and is more * like ACL data, not general event @@ -1430,22 +1458,16 @@ 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) +ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev) { struct ble_hs_periodic_sync *psync; struct ble_gap_event event; ble_gap_event_fn *cb; void *cb_arg; - memset(&event, 0, sizeof event); - - event.type = BLE_GAP_EVENT_PERIODIC_SYNC_LOST; - event.periodic_sync_lost.sync_handle = evt->sync_handle; - event.periodic_sync_lost.reason = BLE_HS_ETIMEOUT; - ble_hs_lock(); /* The handle must be in the list */ - psync = ble_hs_periodic_sync_find_by_handle(evt->sync_handle); + psync = ble_hs_periodic_sync_find_by_handle(le16toh(ev->sync_handle)); BLE_HS_DBG_ASSERT(psync); cb = psync->cb; @@ -1455,6 +1477,12 @@ ble_gap_rx_periodic_adv_sync_lost(struct hci_le_subev_periodic_adv_sync_lost *ev ble_hs_periodic_sync_remove(psync); ble_hs_unlock(); + memset(&event, 0, sizeof event); + + event.type = BLE_GAP_EVENT_PERIODIC_SYNC_LOST; + event.periodic_sync_lost.sync_handle = psync->sync_handle; + event.periodic_sync_lost.reason = BLE_HS_ETIMEOUT; + /* remove any sync_lost event from queue */ ble_npl_eventq_remove(ble_hs_evq_get(), &psync->lost_ev); @@ -1471,22 +1499,13 @@ ble_gap_rx_periodic_adv_sync_lost(struct hci_le_subev_periodic_adv_sync_lost *ev static int ble_gap_rd_rem_sup_feat_tx(uint16_t handle) { - uint8_t buf[BLE_HCI_CONN_RD_REM_FEAT_LEN]; - int rc; + struct ble_hci_le_rd_rem_feat_cp cmd; - rc = ble_hs_hci_cmd_build_le_read_remote_feat(handle, buf, sizeof buf); - if (rc != 0) { - return BLE_HS_EUNKNOWN; - } + cmd.conn_handle = htole16(handle); - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_RD_REM_FEAT), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_RD_REM_FEAT), + &cmd, sizeof(cmd), NULL, 0); } /** @@ -1494,7 +1513,7 @@ ble_gap_rd_rem_sup_feat_tx(uint16_t handle) * instance parameter is valid only for slave connection. */ int -ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt, uint8_t instance) +ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) { #if !NIMBLE_BLE_CONNECT return BLE_HS_ENOTSUP; @@ -1634,8 +1653,7 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt, uint8_t instance) } void -ble_gap_rx_rd_rem_sup_feat_complete( - struct hci_le_rd_rem_supp_feat_complete *evt) +ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev) { #if !NIMBLE_BLE_CONNECT return; @@ -1645,9 +1663,9 @@ ble_gap_rx_rd_rem_sup_feat_complete( ble_hs_lock(); - conn = ble_hs_conn_find(evt->connection_handle); - if (conn != NULL && evt->status == 0) { - conn->supported_feat = get_le32(evt->features); + conn = ble_hs_conn_find(le16toh(ev->conn_handle)); + if ((conn != NULL) && (ev->status == 0)) { + conn->supported_feat = get_le32(ev->features); } ble_hs_unlock(); @@ -1670,19 +1688,20 @@ ble_gap_rx_l2cap_update_req(uint16_t conn_handle, } void -ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt) +ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev) { struct ble_gap_event event; + uint16_t conn_handle = le16toh(ev->conn_handle); memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_PHY_UPDATE_COMPLETE; - event.phy_updated.status = evt->status; - event.phy_updated.conn_handle = evt->connection_handle; - event.phy_updated.tx_phy = evt->tx_phy; - event.phy_updated.rx_phy = evt->rx_phy; + event.phy_updated.status = ev->status; + event.phy_updated.conn_handle = conn_handle; + event.phy_updated.tx_phy = ev->tx_phy; + event.phy_updated.rx_phy = ev->rx_phy; ble_gap_event_listener_call(&event); - ble_gap_call_conn_event_cb(&event, evt->connection_handle); + ble_gap_call_conn_event_cb(&event, conn_handle); } static int32_t @@ -1869,38 +1888,26 @@ ble_gap_wl_busy(void) static int ble_gap_wl_tx_add(const ble_addr_t *addr) { - uint8_t buf[BLE_HCI_ADD_WHITE_LIST_LEN]; - int rc; + struct ble_hci_le_add_whte_list_cp cmd; - rc = ble_hs_hci_cmd_build_le_add_to_whitelist(addr->val, addr->type, - buf, sizeof buf); - if (rc != 0) { - return rc; + if (addr->type > BLE_ADDR_RANDOM) { + return BLE_HS_EINVAL; } - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_ADD_WHITE_LIST), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } + memcpy(cmd.addr, addr->val, BLE_DEV_ADDR_LEN); + cmd.addr_type = addr->type; - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_ADD_WHITE_LIST), + &cmd, sizeof(cmd), NULL, 0); } static int ble_gap_wl_tx_clear(void) { - int rc; - - rc = ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_WHITE_LIST), - NULL, 0); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CLEAR_WHITE_LIST), + NULL, 0, NULL, 0 ); } int @@ -1970,19 +1977,13 @@ done: static int ble_gap_adv_enable_tx(int enable) { - uint8_t buf[BLE_HCI_SET_ADV_ENABLE_LEN]; - uint16_t opcode; - int rc; + struct ble_hci_le_set_adv_enable_cp cmd; - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE); - ble_hs_hci_cmd_build_le_set_adv_enable(!!enable, buf, sizeof buf); + cmd.enable = !!enable; - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); - 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_ADV_ENABLE), + &cmd, sizeof(cmd), NULL, 0); } static int @@ -2093,6 +2094,8 @@ ble_gap_adv_dflt_itvls(uint8_t conn_mode, default: BLE_HS_DBG_ASSERT(0); + *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN; + *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX; break; } } @@ -2103,52 +2106,43 @@ ble_gap_adv_params_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr, { const ble_addr_t *peer_any = BLE_ADDR_ANY; - struct hci_adv_params hci_adv_params; - uint8_t buf[BLE_HCI_SET_ADV_PARAM_LEN]; - int rc; + struct ble_hci_le_set_adv_params_cp cmd; + uint16_t opcode; + uint16_t min; + uint16_t max; + + /* Fill optional fields if application did not specify them. */ + if ((adv_params->itvl_min == 0) && (adv_params->itvl_max == 0)) { + ble_gap_adv_dflt_itvls(adv_params->conn_mode, &min, &max); + cmd.min_interval = htole16(min); + cmd.max_interval = htole16(max); + } else { + cmd.min_interval = htole16(adv_params->itvl_min); + cmd.max_interval = htole16(adv_params->itvl_max); + } + + cmd.type = ble_gap_adv_type(adv_params); + cmd.own_addr_type = own_addr_type; if (peer_addr == NULL) { peer_addr = peer_any; } - hci_adv_params.own_addr_type = own_addr_type; - hci_adv_params.peer_addr_type = peer_addr->type; - memcpy(hci_adv_params.peer_addr, peer_addr->val, - sizeof hci_adv_params.peer_addr); + cmd.peer_addr_type = peer_addr->type; + memcpy(&cmd.peer_addr, peer_addr->val, sizeof(cmd.peer_addr)); - /* Fill optional fields if application did not specify them. */ - if (adv_params->itvl_min == 0 && adv_params->itvl_max == 0) { - ble_gap_adv_dflt_itvls(adv_params->conn_mode, - &hci_adv_params.adv_itvl_min, - &hci_adv_params.adv_itvl_max); - } else { - hci_adv_params.adv_itvl_min = adv_params->itvl_min; - hci_adv_params.adv_itvl_max = adv_params->itvl_max; - } if (adv_params->channel_map == 0) { - hci_adv_params.adv_channel_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; + cmd.chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; } else { - hci_adv_params.adv_channel_map = adv_params->channel_map; + cmd.chan_map = adv_params->channel_map; } /* Zero is the default value for filter policy and high duty cycle */ - hci_adv_params.adv_filter_policy = adv_params->filter_policy; + cmd.filter_policy = adv_params->filter_policy; - hci_adv_params.adv_type = ble_gap_adv_type(adv_params); - rc = ble_hs_hci_cmd_build_le_set_adv_params(&hci_adv_params, - buf, sizeof buf); - if (rc != 0) { - return BLE_HS_EINVAL; - } + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_PARAMS); - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_SET_ADV_PARAMS), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } static int @@ -2317,31 +2311,23 @@ ble_gap_adv_set_data(const uint8_t *data, int data_len) return BLE_HS_ENOTSUP; #endif - uint8_t buf[BLE_HCI_SET_ADV_DATA_LEN]; + struct ble_hci_le_set_adv_data_cp cmd; uint16_t opcode; - int rc; STATS_INC(ble_gap_stats, adv_set_data); - ble_hs_lock(); + /* Check for valid parameters */ + if (((data == NULL) && (data_len != 0)) || + (data_len > BLE_HCI_MAX_ADV_DATA_LEN)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + memcpy(cmd.adv_data, data, data_len); + cmd.adv_data_len = data_len; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_DATA); - rc = ble_hs_hci_cmd_build_le_set_adv_data(data, data_len, buf, - sizeof(buf)); - if (rc != 0) { - goto done; - } - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); - if (rc != 0) { - goto done; - } - - rc = 0; - -done: - ble_hs_unlock(); - return rc; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } int @@ -2351,30 +2337,22 @@ ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len) return BLE_HS_ENOTSUP; #endif - uint8_t buf[BLE_HCI_SET_SCAN_RSP_DATA_LEN]; + struct ble_hci_le_set_scan_rsp_data_cp cmd; uint16_t opcode; - int rc; - ble_hs_lock(); + + /* Check for valid parameters */ + if (((data == NULL) && (data_len != 0)) || + (data_len > BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) { + return BLE_HS_EINVAL; + } + + memcpy(cmd.scan_rsp, data, data_len); + cmd.scan_rsp_len = data_len; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA); - rc = ble_hs_hci_cmd_build_le_set_scan_rsp_data(data, data_len, - buf, sizeof(buf)); - if (rc != 0) { - rc = BLE_HS_HCI_ERR(rc); - goto done; - } - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); - if (rc != 0) { - goto done; - } - - rc = 0; - -done: - ble_hs_unlock(); - return rc; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } int @@ -2438,87 +2416,81 @@ ble_gap_ext_adv_params_tx(uint8_t instance, int8_t *selected_tx_power) { - struct hci_ext_adv_params hci_adv_params; - uint8_t buf[BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN]; - uint8_t rsp; + struct ble_hci_le_set_ext_adv_params_cp cmd; + struct ble_hci_le_set_ext_adv_params_rp rsp; int rc; - memset(&hci_adv_params, 0, sizeof(hci_adv_params)); + memset(&cmd, 0, sizeof(cmd)); + + cmd.adv_handle = instance; if (params->connectable) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE; + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE; } if (params->scannable) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; } if (params->directed) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; - hci_adv_params.peer_addr_type = params->peer.type; - memcpy(hci_adv_params.peer_addr, params->peer.val, 6); + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; + cmd.peer_addr_type = params->peer.type; + memcpy(cmd.peer_addr, params->peer.val, BLE_DEV_ADDR_LEN); } if (params->high_duty_directed) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; } if (params->legacy_pdu) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; } if (params->anonymous) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; } if (params->include_tx_power) { - hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; } /* Fill optional fields if application did not specify them. */ if (params->itvl_min == 0 && params->itvl_max == 0) { /* TODO for now limited to legacy values*/ - hci_adv_params.min_interval = BLE_GAP_ADV_FAST_INTERVAL1_MIN; - hci_adv_params.max_interval = BLE_GAP_ADV_FAST_INTERVAL2_MAX; - + put_le24(cmd.pri_itvl_min, BLE_GAP_ADV_FAST_INTERVAL1_MIN); + put_le24(cmd.pri_itvl_max, BLE_GAP_ADV_FAST_INTERVAL2_MAX); } else { - hci_adv_params.min_interval = params->itvl_min; - hci_adv_params.max_interval = params->itvl_max; + put_le24(cmd.pri_itvl_min, params->itvl_min); + put_le24(cmd.pri_itvl_max, params->itvl_max); } if (params->channel_map == 0) { - hci_adv_params.chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; + cmd.pri_chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; } else { - hci_adv_params.chan_map = params->channel_map; + cmd.pri_chan_map = params->channel_map; } /* Zero is the default value for filter policy and high duty cycle */ - hci_adv_params.filter_policy = params->filter_policy; - hci_adv_params.tx_power = params->tx_power; + cmd.filter_policy = params->filter_policy; + cmd.tx_power = params->tx_power; if (params->legacy_pdu) { - hci_adv_params.primary_phy = BLE_HCI_LE_PHY_1M; - hci_adv_params.secondary_phy = BLE_HCI_LE_PHY_1M; + cmd.pri_phy = BLE_HCI_LE_PHY_1M; + cmd.sec_phy = BLE_HCI_LE_PHY_1M; } else { - hci_adv_params.primary_phy = params->primary_phy; - hci_adv_params.secondary_phy = params->secondary_phy; + cmd.pri_phy = params->primary_phy; + cmd.sec_phy = params->secondary_phy; } - hci_adv_params.own_addr_type = params->own_addr_type; - hci_adv_params.max_skip = 0; - hci_adv_params.sid = params->sid; - hci_adv_params.scan_req_notif = params->scan_req_notif; + cmd.own_addr_type = params->own_addr_type; + cmd.sec_max_skip = 0; + cmd.sid = params->sid; + cmd.scan_req_notif = params->scan_req_notif; - rc = ble_hs_hci_cmd_build_le_ext_adv_params(instance, &hci_adv_params, - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - rc = ble_hs_hci_cmd_tx( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM), - buf, sizeof(buf), &rsp, 1, NULL); + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM), + &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (rc != 0) { return rc; } if (selected_tx_power) { - *selected_tx_power = rsp; + *selected_tx_power = rsp.tx_power; } return 0; @@ -2617,18 +2589,15 @@ ble_gap_ext_adv_configure(uint8_t instance, static int ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr) { - uint8_t buf[BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN]; + struct ble_hci_le_set_adv_set_rnd_addr_cp cmd; int rc; - rc = ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(instance, addr, buf, - sizeof(buf)); - if (rc != 0) { - return rc; - } + cmd.adv_handle = instance; + memcpy(cmd.addr, addr, BLE_DEV_ADDR_LEN); - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR), - buf, sizeof(buf)); + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR), + &cmd, sizeof(cmd), NULL, 0); if (rc != 0) { return rc; } @@ -2658,9 +2627,9 @@ ble_gap_ext_adv_set_addr(uint8_t instance, const ble_addr_t *addr) int ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events) { + struct ble_hci_le_set_ext_adv_enable_cp *cmd; + uint8_t buf[sizeof(*cmd) + sizeof(cmd->sets[0])]; const uint8_t *rnd_addr; - uint8_t buf[6]; - struct hci_ext_adv_set set; uint16_t opcode; int rc; @@ -2731,17 +2700,16 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events) opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE); - set.handle = instance; - set.duration = duration; - set.events = max_events; + cmd = (void *) buf; - rc = ble_hs_hci_cmd_build_le_ext_adv_enable(1, 1, &set, buf, sizeof(buf)); - if (rc != 0) { - ble_hs_unlock(); - return rc; - } + cmd->enable = 0x01; + cmd->num_sets = 1; - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + cmd->sets[0].adv_handle = instance; + cmd->sets[0].duration = htole16(duration); + cmd->sets[0].max_events = max_events; + + rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(buf), NULL, 0); if (rc != 0) { ble_hs_unlock(); return rc; @@ -2756,8 +2724,8 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events) static int ble_gap_ext_adv_stop_no_lock(uint8_t instance) { - uint8_t buf[6]; - struct hci_ext_adv_set set; + struct ble_hci_le_set_ext_adv_enable_cp *cmd; + uint8_t buf[sizeof(*cmd) + sizeof(cmd->sets[0])]; uint16_t opcode; bool active; int rc; @@ -2768,18 +2736,17 @@ ble_gap_ext_adv_stop_no_lock(uint8_t instance) active = ble_gap_adv_active_instance(instance); + cmd = (void *) buf; + + cmd->enable = 0x00; + cmd->num_sets = 1; + cmd->sets[0].adv_handle = instance; + cmd->sets[0].duration = 0x0000; + cmd->sets[0].max_events = 0x00; + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE); - set.handle = instance; - set.duration = 0; - set.events = 0; - - rc = ble_hs_hci_cmd_build_le_ext_adv_enable(0, 1, &set, buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(buf), NULL, 0); if (rc != 0) { return rc; } @@ -2856,65 +2823,63 @@ ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data) { /* in that case we always fit all data in single HCI command */ #if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_EXT_ADV_DATA_LEN - static uint8_t buf[BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + \ + static uint8_t buf[sizeof(struct ble_hci_le_set_ext_adv_data_cp) + \ MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)]; + struct ble_hci_le_set_ext_adv_data_cp *cmd = (void *)buf; uint16_t len = OS_MBUF_PKTLEN(*data); - int rc; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode); + cmd->adv_handle = instance; + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE; + cmd->fragment_pref = 0; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, len, cmd->adv_data); - rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE, - 0, *data, len, buf, sizeof(buf)); - if (rc) { - return rc; - } - - os_mbuf_adj(*data, MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)); + os_mbuf_adj(*data, len); *data = os_mbuf_trim_front(*data); - return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, - BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len); + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); #else - static uint8_t buf[BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + \ + static uint8_t buf[sizeof(struct ble_hci_le_set_ext_adv_data_cp) + \ BLE_HCI_MAX_EXT_ADV_DATA_LEN]; + struct ble_hci_le_set_ext_adv_data_cp *cmd = (void *)buf; uint16_t len = OS_MBUF_PKTLEN(*data); uint8_t op; int rc; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode); + cmd->adv_handle = instance; + /* complete data */ if (len <= BLE_HCI_MAX_EXT_ADV_DATA_LEN) { - rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE, - 0, *data, len, buf,sizeof(buf)); - if (rc) { - return rc; - } + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE; + cmd->fragment_pref = 0; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, len, cmd->adv_data); os_mbuf_adj(*data, len); *data = os_mbuf_trim_front(*data); - return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, - BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len); + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); } /* first fragment */ op = BLE_HCI_LE_SET_DATA_OPER_FIRST; do { - rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, op, 0, *data, - BLE_HCI_MAX_EXT_ADV_DATA_LEN, - buf, sizeof(buf)); - if (rc) { - return rc; - } + cmd->operation = op; + cmd->fragment_pref = 0; + cmd->adv_data_len = BLE_HCI_MAX_EXT_ADV_DATA_LEN; + os_mbuf_copydata(*data, 0, BLE_HCI_MAX_EXT_ADV_DATA_LEN, cmd->adv_data); os_mbuf_adj(*data, BLE_HCI_MAX_EXT_ADV_DATA_LEN); *data = os_mbuf_trim_front(*data); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); if (rc) { return rc; } @@ -2924,18 +2889,16 @@ ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data) } while (len > BLE_HCI_MAX_EXT_ADV_DATA_LEN); /* last fragment */ - rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, - BLE_HCI_LE_SET_DATA_OPER_LAST, - 0, *data, len, buf, sizeof(buf)); - if (rc) { - return rc; - } + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_LAST; + cmd->fragment_pref = 0; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, len, cmd->adv_data); os_mbuf_adj(*data, len); *data = os_mbuf_trim_front(*data); - return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, - BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len); + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); #endif } @@ -3036,7 +2999,7 @@ done: int ble_gap_ext_adv_remove(uint8_t instance) { - uint8_t buf[BLE_HCI_LE_REMOVE_ADV_SET_LEN]; + struct ble_hci_le_remove_adv_set_cp cmd; uint16_t opcode; int rc; @@ -3055,15 +3018,10 @@ ble_gap_ext_adv_remove(uint8_t instance) return BLE_HS_EBUSY; } + cmd.adv_handle = instance; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REMOVE_ADV_SET); - rc = ble_hs_hci_cmd_build_le_ext_adv_remove(instance, buf, sizeof(buf)); - if (rc != 0) { - ble_hs_unlock(); - return rc; - } - - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); if (rc != 0) { ble_hs_unlock(); return rc; @@ -3103,7 +3061,7 @@ ble_gap_ext_adv_clear(void) opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_ADV_SETS); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, NULL, 0); + rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, NULL, 0); if (rc != 0) { ble_hs_unlock(); return rc; @@ -3118,44 +3076,34 @@ ble_gap_ext_adv_clear(void) #if MYNEWT_VAL(BLE_PERIODIC_ADV) static int ble_gap_periodic_adv_params_tx(uint8_t instance, - const struct ble_gap_periodic_adv_params *params) + const struct ble_gap_periodic_adv_params *params) { - struct hci_periodic_adv_params hci_adv_params; - uint8_t buf[BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN]; - int rc; + struct ble_hci_le_set_periodic_adv_params_cp cmd; + uint16_t opcode; - memset(&hci_adv_params, 0, sizeof(hci_adv_params)); - - if (params->include_tx_power) { - hci_adv_params.properties |= BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR; - } + cmd.adv_handle = instance; /* Fill optional fields if application did not specify them. */ if (params->itvl_min == 0 && params->itvl_max == 0) { - hci_adv_params.min_interval = 30 / 1.25; //30 ms - hci_adv_params.max_interval = 60 / 1.25; //150 ms + /* TODO defines for those */ + cmd.min_itvl = htole16(30 / 1.25); //30 ms + cmd.max_itvl = htole16(60 / 1.25); //150 ms } else { - hci_adv_params.min_interval = params->itvl_min; - hci_adv_params.max_interval = params->itvl_max; + cmd.min_itvl = htole16( params->itvl_min); + cmd.max_itvl = htole16(params->itvl_max); } - rc = ble_hs_hci_cmd_build_le_periodic_adv_params(instance, &hci_adv_params, buf, - sizeof(buf)); - if (rc != 0) { - return rc; + if (params->include_tx_power) { + cmd.props = BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR; + } else { + cmd.props = 0; } - rc = ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS), buf, - sizeof(buf)); + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } static int @@ -3223,7 +3171,7 @@ ble_gap_periodic_adv_configure(uint8_t instance, int ble_gap_periodic_adv_start(uint8_t instance) { - uint8_t buf[BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN]; + struct ble_hci_le_set_periodic_adv_enable_cp cmd; uint16_t opcode; int rc; @@ -3239,16 +3187,12 @@ ble_gap_periodic_adv_start(uint8_t instance) return BLE_HS_EINVAL; } - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE); - rc = ble_hs_hci_cmd_build_le_periodic_adv_enable(1, instance, buf, - sizeof(buf)); - if (rc != 0) { - ble_hs_unlock(); - return rc; - } + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + cmd.enable = 0x01; + cmd.adv_handle = instance; + + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); if (rc != 0) { ble_hs_unlock(); return rc; @@ -3261,57 +3205,51 @@ ble_gap_periodic_adv_start(uint8_t instance) } static int -ble_gap_periodic_adv_set(uint8_t instance, uint16_t opcode, - struct os_mbuf **data) +ble_gap_periodic_adv_set(uint8_t instance, struct os_mbuf **data) { /* In that case we always fit all data in single HCI command */ #if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN - - static uint8_t buf[BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + + static uint8_t buf[sizeof(struct ble_hci_le_set_periodic_adv_data_cp) + MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)]; + struct ble_hci_le_set_periodic_adv_data_cp *cmd = (void *) buf; uint16_t len = OS_MBUF_PKTLEN(*data); - int rc; + uint16_t opcode; - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode); + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA); - rc = ble_hs_hci_cmd_build_le_periodic_adv_data( - instance, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE, - *data, len, - buf, sizeof(buf)); + cmd->adv_handle = instance; + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, len, cmd->adv_data); - if (rc) { - return rc; - } - - os_mbuf_adj(*data, MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)); + os_mbuf_adj(*data, len); *data = os_mbuf_trim_front(*data); - return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, - BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + len); + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); #else - static uint8_t buf[BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + + static uint8_t buf[sizeof(struct ble_hci_le_set_periodic_adv_data_cp) + BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN]; + struct ble_hci_le_set_periodic_adv_data_cp *cmd = (void *) buf; uint16_t len = OS_MBUF_PKTLEN(*data); + uint16_t opcode; uint8_t op; int rc; - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode); + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA); + cmd->adv_handle = instance; /* Complete data */ if (len <= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN) { - rc = ble_hs_hci_cmd_build_le_periodic_adv_data(instance, - BLE_HCI_LE_SET_DATA_OPER_COMPLETE, *data, len, buf, - sizeof(buf)); - if (rc) { - return rc; - } + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, len, cmd->adv_data); os_mbuf_adj(*data, len); *data = os_mbuf_trim_front(*data); - return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, - BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + len); + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); } /* If the periodic advertising is already enabled, the periodic advertising @@ -3326,16 +3264,16 @@ ble_gap_periodic_adv_set(uint8_t instance, uint16_t opcode, op = BLE_HCI_LE_SET_DATA_OPER_FIRST; do{ - rc = ble_hs_hci_cmd_build_le_periodic_adv_data(instance, op, *data, - BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN, buf, sizeof(buf)); - if (rc) { - return rc; - } + cmd->operation = op; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN, + cmd->adv_data); os_mbuf_adj(*data, BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN); *data = os_mbuf_trim_front(*data); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); if (rc) { return rc; } @@ -3345,19 +3283,15 @@ ble_gap_periodic_adv_set(uint8_t instance, uint16_t opcode, } while (len > BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN); /* Last fragment */ - rc = ble_hs_hci_cmd_build_le_periodic_adv_data( - instance, - BLE_HCI_LE_SET_DATA_OPER_LAST, - *data, len, buf, sizeof(buf)); - if (rc) { - return rc; - } + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_LAST; + cmd->adv_data_len = len; + os_mbuf_copydata(*data, 0, len, cmd->adv_data); os_mbuf_adj(*data, len); *data = os_mbuf_trim_front(*data); - return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, - BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN + len); + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); #endif } @@ -3400,8 +3334,7 @@ ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data) goto done; } - rc = ble_gap_periodic_adv_set(instance, - BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA, &data); + rc = ble_gap_periodic_adv_set(instance, &data); ble_hs_unlock(); @@ -3413,18 +3346,16 @@ done: static int ble_gap_periodic_adv_stop_no_lock(uint8_t instance) { - uint8_t buf[BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN]; + struct ble_hci_le_set_periodic_adv_enable_cp cmd; uint16_t opcode; int rc; + cmd.enable = 0x00; + cmd.adv_handle = instance; + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE); - rc = ble_hs_hci_cmd_build_le_periodic_adv_enable(0, instance, buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); if (rc != 0) { return rc; } @@ -3483,10 +3414,21 @@ ble_gap_periodic_adv_create_sync(const ble_addr_t *addr, uint8_t adv_sid, const struct ble_gap_periodic_sync_params *params, ble_gap_event_fn *cb, void *cb_arg) { - uint8_t buf[BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN]; + struct ble_hci_le_periodic_adv_create_sync_cp cmd; struct ble_hs_periodic_sync *psync; uint16_t opcode; - int rc = 0; + int rc; + + if (addr && (addr->type > BLE_ADDR_RANDOM)) { + return BLE_HS_EINVAL; + } + if (adv_sid > 0x0f) { + return BLE_HS_EINVAL; + } + if ((params->skip > 0x1f3) || (params->sync_timeout > 0x4000) || + (params->sync_timeout < 0x0A)) { + return BLE_HS_EINVAL; + } ble_hs_lock(); @@ -3512,24 +3454,22 @@ ble_gap_periodic_adv_create_sync(const ble_addr_t *addr, uint8_t adv_sid, ble_npl_event_init(&psync->lost_ev, ble_gap_npl_sync_lost, psync); if (addr) { - rc = ble_hs_hci_cmd_build_le_periodic_adv_create_sync(0x00, adv_sid, - addr->type, addr->val, params->skip, - params->sync_timeout, buf, sizeof(buf)); + cmd.options = 0x00; + cmd.peer_addr_type = addr->type; + memcpy(cmd.peer_addr, addr->val, BLE_DEV_ADDR_LEN); } else { - rc = ble_hs_hci_cmd_build_le_periodic_adv_create_sync(0x01, adv_sid, - BLE_ADDR_ANY->type, BLE_ADDR_ANY->val, params->skip, - params->sync_timeout, buf, sizeof(buf)); + cmd.options = 0x01; + cmd.peer_addr_type = BLE_ADDR_ANY->type; + memcpy(cmd.peer_addr, BLE_ADDR_ANY->val, BLE_DEV_ADDR_LEN); } - if (rc != 0) { - ble_hs_periodic_sync_free(psync); - ble_hs_unlock(); - return rc; - } + cmd.sid = adv_sid; + cmd.skip = params->skip; + cmd.sync_timeout = htole16(params->sync_timeout); + cmd.sync_cte_type = 0x00; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); - + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); if (!rc) { /* This shall be reset upon receiving sync_established event, * or if the sync is cancelled before receiving that event. @@ -3563,7 +3503,7 @@ ble_gap_periodic_adv_create_sync_cancel(void) opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, NULL, 0); + rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, NULL, 0); if (!rc) { ble_gap_sync.op = BLE_GAP_OP_NULL; @@ -3581,10 +3521,10 @@ ble_gap_periodic_adv_create_sync_cancel(void) int ble_gap_periodic_adv_terminate_sync(uint16_t sync_handle) { - uint8_t buf[BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN]; - uint16_t opcode; + struct ble_hci_le_periodic_adv_term_sync_cp cmd; struct ble_hs_periodic_sync *psync; - int rc = 0; + uint16_t opcode; + int rc; ble_hs_lock(); @@ -3606,15 +3546,9 @@ ble_gap_periodic_adv_terminate_sync(uint16_t sync_handle) opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC); - rc = ble_hs_hci_cmd_build_le_periodic_adv_terminate_sync(sync_handle, - buf, sizeof(buf)); - if (rc != 0) { - ble_hs_unlock(); - return rc; - } - - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + cmd.sync_handle = htole16(sync_handle); + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); if (rc == 0) { /* Remove the handle from the list */ ble_hs_periodic_sync_remove(psync); @@ -3634,47 +3568,41 @@ int ble_gap_add_dev_to_periodic_adv_list(const ble_addr_t *peer_addr, uint8_t adv_sid) { - uint8_t buf[BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN]; + struct ble_hci_le_add_dev_to_periodic_adv_list_cp cmd; uint16_t opcode; - int rc = 0; + + if ((peer_addr->type > BLE_ADDR_RANDOM) || (adv_sid > 0x0f)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd.peer_addr_type = peer_addr->type; + memcpy(cmd.peer_addr, peer_addr->val, BLE_DEV_ADDR_LEN); + cmd.sid = adv_sid; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST); - rc = ble_hs_hci_cmd_build_le_add_dev_to_periodic_adv_list(peer_addr->type, - peer_addr->val, - adv_sid, buf, - sizeof(buf)); - if (rc != 0) { - return rc; - } - - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); - - return rc; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } int ble_gap_rem_dev_from_periodic_adv_list(const ble_addr_t *peer_addr, uint8_t adv_sid) { - uint8_t buf[BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN]; + struct ble_hci_le_rem_dev_from_periodic_adv_list_cp cmd; uint16_t opcode; - int rc = 0; + + if ((peer_addr->type > BLE_ADDR_RANDOM) || (adv_sid > 0x0f)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd.peer_addr_type = peer_addr->type; + memcpy(cmd.peer_addr, peer_addr->val, BLE_DEV_ADDR_LEN); + cmd.sid = adv_sid; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST); - rc = ble_hs_hci_cmd_build_le_rem_dev_from_periodic_adv_list(peer_addr->type, - peer_addr->val, - adv_sid, buf, - sizeof(buf)); - if (rc != 0) { - return rc; - } - - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); - - return rc; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } int @@ -3685,7 +3613,7 @@ ble_gap_clear_periodic_adv_list(void) opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST); - rc = ble_hs_hci_cmd_tx_empty_ack(opcode, NULL, 0); + rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, NULL, 0); return rc; } @@ -3693,23 +3621,18 @@ ble_gap_clear_periodic_adv_list(void) int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size) { - uint8_t rspbuf[1]; - uint8_t rsplen; + struct ble_hci_le_rd_periodic_adv_list_size_rp rsp; uint16_t opcode; int rc = 0; opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE); - rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, rspbuf, sizeof(rspbuf), &rsplen); + rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, &rsp, sizeof(rsp)); if (rc != 0) { return rc; } - if (rsplen != sizeof(rspbuf)) { - return BLE_HS_ECONTROLLER; - } - - *per_adv_list_size = rspbuf[0]; + *per_adv_list_size = rsp.list_size; return 0; } @@ -3725,58 +3648,73 @@ ble_gap_ext_disc_tx_params(uint8_t own_addr_type, uint8_t filter_policy, const struct ble_hs_hci_ext_scan_param *uncoded_params, const struct ble_hs_hci_ext_scan_param *coded_params) { - uint8_t buf[BLE_HCI_LE_EXT_SCAN_BASE_LEN + - 2 * BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN]; - uint8_t phy_mask = 0; - struct ble_hs_hci_ext_scan_param param[2] = {{0}}; - struct ble_hs_hci_ext_scan_param *p = param; - int phy_count = 0; - uint8_t len; - int rc; + struct ble_hci_le_set_ext_scan_params_cp *cmd; + struct scan_params *params; + uint8_t buf[sizeof(*cmd) + 2 * sizeof(*params)]; + uint8_t len = sizeof(*cmd); + + /* Check own addr type */ + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check scanner filter policy */ + if (filter_policy > BLE_HCI_SCAN_FILT_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd = (void *) buf; + params = cmd->scans; + + cmd->filter_policy = filter_policy; + cmd->own_addr_type = own_addr_type; + cmd->phys = 0; if (uncoded_params) { - phy_mask |= BLE_HCI_LE_PHY_1M_PREF_MASK; - memcpy(¶m[phy_count], uncoded_params, sizeof(*uncoded_params)); - phy_count++; + cmd->phys |= BLE_HCI_LE_PHY_1M_PREF_MASK; + + params->type = uncoded_params->scan_type; + params->itvl = htole16(uncoded_params->scan_itvl); + params->window = htole16(uncoded_params->scan_window); + + len += sizeof(*params); + params++; } if (coded_params) { - phy_mask |= BLE_HCI_LE_PHY_CODED_PREF_MASK; - memcpy(¶m[phy_count], coded_params, sizeof(*coded_params)); - phy_count++; + cmd->phys |= BLE_HCI_LE_PHY_CODED_PREF_MASK; + + params->type = coded_params->scan_type; + params->itvl = htole16(coded_params->scan_itvl); + params->window = htole16(coded_params->scan_window); + + len += sizeof(*params); + params++; } - rc = ble_hs_hci_cmd_build_le_set_ext_scan_params(own_addr_type, - filter_policy, - phy_mask, - phy_count, - &p, buf, sizeof(buf)); - - if (rc != 0) { - return BLE_HS_EINVAL; + if (!cmd->phys) { + return BLE_ERR_INV_HCI_CMD_PARMS; } - len = BLE_HCI_LE_EXT_SCAN_BASE_LEN + - BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN * phy_count; - - return ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM), - buf, len); + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM), + cmd, len, NULL, 0); } static int ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates, uint16_t duration, uint16_t period) { - uint8_t buf[BLE_HCI_LE_SET_EXT_SCAN_ENABLE_LEN]; + struct ble_hci_le_set_ext_scan_enable_cp cmd; - ble_hs_hci_cmd_build_le_set_ext_scan_enable(enable, filter_duplicates, - duration, period, - buf, sizeof buf); + cmd.enable = enable; + cmd.filter_dup = filter_duplicates; + cmd.duration = htole16(duration); + cmd.period = htole16(period); - return ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE), - buf, sizeof(buf)); + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE), + &cmd, sizeof(cmd), NULL, 0); } #endif #endif @@ -3785,53 +3723,38 @@ ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates, static int ble_gap_disc_enable_tx(int enable, int filter_duplicates) { - uint8_t buf[BLE_HCI_SET_SCAN_ENABLE_LEN]; - int rc; + struct ble_hci_le_set_scan_enable_cp cmd; + uint16_t opcode; - ble_hs_hci_cmd_build_le_set_scan_enable(!!enable, !!filter_duplicates, - buf, sizeof buf); - rc = ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } + cmd.enable = !!enable; + cmd.filter_duplicates = !!filter_duplicates; - return 0; + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE); + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } static int ble_gap_disc_tx_params(uint8_t own_addr_type, const struct ble_gap_disc_params *disc_params) { - uint8_t buf[BLE_HCI_SET_SCAN_PARAM_LEN]; - uint8_t scan_type; - int rc; + struct ble_hci_le_set_scan_params_cp cmd; + uint16_t opcode; if (disc_params->passive) { - scan_type = BLE_HCI_SCAN_TYPE_PASSIVE; + cmd.scan_type = BLE_HCI_SCAN_TYPE_PASSIVE; } else { - scan_type = BLE_HCI_SCAN_TYPE_ACTIVE; + cmd.scan_type = BLE_HCI_SCAN_TYPE_ACTIVE; } - rc = ble_hs_hci_cmd_build_le_set_scan_params(scan_type, - disc_params->itvl, - disc_params->window, - own_addr_type, - disc_params->filter_policy, - buf, sizeof buf); - if (rc != 0) { - return BLE_HS_EINVAL; - } + cmd.scan_itvl = htole16(disc_params->itvl); + cmd.scan_window = htole16(disc_params->window); + cmd.own_addr_type = own_addr_type; + cmd.filter_policy = disc_params->filter_policy; - rc = ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_PARAMS), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_PARAMS); - return 0; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } #endif @@ -4073,6 +3996,20 @@ ble_gap_disc_validate(uint8_t own_addr_type, return BLE_HS_EINVAL; } + /* Check interval and window */ + if ((disc_params->itvl < BLE_HCI_SCAN_ITVL_MIN) || + (disc_params->itvl > BLE_HCI_SCAN_ITVL_MAX) || + (disc_params->window < BLE_HCI_SCAN_WINDOW_MIN) || + (disc_params->window > BLE_HCI_SCAN_WINDOW_MAX) || + (disc_params->itvl < disc_params->window)) { + return BLE_HS_EINVAL; + } + + /* Check scanner filter policy */ + if (disc_params->filter_policy > BLE_HCI_SCAN_FILT_MAX) { + return BLE_HS_EINVAL; + } + return ble_gap_disc_ext_validate(own_addr_type); } #endif @@ -4191,64 +4128,83 @@ static int ble_gap_conn_create_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr, const struct ble_gap_conn_params *params) { - uint8_t buf[BLE_HCI_CREATE_CONN_LEN]; - struct hci_create_conn hcc; - int rc; - - hcc.scan_itvl = params->scan_itvl; - hcc.scan_window = params->scan_window; + struct ble_hci_le_create_conn_cp cmd; + uint16_t opcode; + cmd.scan_itvl = htole16(params->scan_itvl); + cmd.scan_window = htole16(params->scan_window); if (peer_addr == NULL) { /* Application wants to connect to any device in the white list. The * peer address type and peer address fields are ignored by the * controller; fill them with dummy values. */ - hcc.filter_policy = BLE_HCI_CONN_FILT_USE_WL; - hcc.peer_addr_type = 0; - memset(hcc.peer_addr, 0, sizeof hcc.peer_addr); + cmd.filter_policy = BLE_HCI_CONN_FILT_USE_WL; + cmd.peer_addr_type = 0; + memset(cmd.peer_addr, 0, sizeof(cmd.peer_addr)); } else { - hcc.filter_policy = BLE_HCI_CONN_FILT_NO_WL; - hcc.peer_addr_type = peer_addr->type; - memcpy(hcc.peer_addr, peer_addr->val, sizeof hcc.peer_addr); + cmd.filter_policy = BLE_HCI_CONN_FILT_NO_WL; + cmd.peer_addr_type = peer_addr->type; + memcpy(cmd.peer_addr, peer_addr->val, sizeof(cmd.peer_addr)); } - hcc.own_addr_type = own_addr_type; - hcc.conn_itvl_min = params->itvl_min; - hcc.conn_itvl_max = params->itvl_max; - hcc.conn_latency = params->latency; - hcc.supervision_timeout = params->supervision_timeout; - hcc.min_ce_len = params->min_ce_len; - hcc.max_ce_len = params->max_ce_len; + cmd.own_addr_type = own_addr_type; + cmd.min_conn_itvl = htole16(params->itvl_min); + cmd.max_conn_itvl = htole16(params->itvl_max); + cmd.conn_latency = htole16(params->latency); + cmd.tmo = htole16(params->supervision_timeout); + cmd.min_ce = htole16(params->min_ce_len); + cmd.max_ce = htole16(params->max_ce_len); - rc = ble_hs_hci_cmd_build_le_create_connection(&hcc, buf, sizeof buf); - if (rc != 0) { - return BLE_HS_EUNKNOWN; - } + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN); - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_CREATE_CONN), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } #endif #if MYNEWT_VAL(BLE_EXT_ADV) -static void -ble_gap_copy_params(struct hci_ext_conn_params *hcc_params, - const struct ble_gap_conn_params *gap_params) +static int +ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params) { - hcc_params->scan_itvl = gap_params->scan_itvl; - hcc_params->scan_window = gap_params->scan_window; - hcc_params->conn_itvl_max = gap_params->itvl_max; - hcc_params->conn_itvl_min = gap_params->itvl_min; - hcc_params->max_ce_len = gap_params->max_ce_len; - hcc_params->min_ce_len = gap_params->min_ce_len; - hcc_params->conn_latency = gap_params->latency; - hcc_params->supervision_timeout = gap_params->supervision_timeout; + if (phy != BLE_HCI_LE_PHY_2M) { + /* Check scan interval and window */ + if ((params->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || + (params->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || + (params->scan_window < BLE_HCI_SCAN_WINDOW_MIN) || + (params->scan_window > BLE_HCI_SCAN_WINDOW_MAX) || + (params->scan_itvl < params->scan_window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + /* Check connection interval min */ + if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) || + (params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* Check connection interval max */ + if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) || + (params->itvl_max > BLE_HCI_CONN_ITVL_MAX) || + (params->itvl_max < params->itvl_min)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection latency */ + if ((params->latency < BLE_HCI_CONN_LATENCY_MIN) || + (params->latency > BLE_HCI_CONN_LATENCY_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check supervision timeout */ + if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || + (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection event length */ + if (params->min_ce_len > params->max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return 0; } static int @@ -4258,56 +4214,108 @@ ble_gap_ext_conn_create_tx( const struct ble_gap_conn_params *phy_2m_conn_params, const struct ble_gap_conn_params *phy_coded_conn_params) { - uint8_t buf[sizeof(struct hci_ext_create_conn)]; - struct hci_ext_create_conn hcc = {0}; + struct ble_hci_le_ext_create_conn_cp *cmd; + struct conn_params *params; + uint8_t buf[sizeof(*cmd) + 3 * sizeof(*params)]; + uint8_t len = sizeof(*cmd); int rc; + /* Check own addr type */ + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check peer addr type */ + if (peer_addr->type > BLE_HCI_CONN_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd = (void *) buf; + params = cmd->conn_params; + if (peer_addr == NULL) { /* Application wants to connect to any device in the white list. The * peer address type and peer address fields are ignored by the * controller; fill them with dummy values. */ - hcc.filter_policy = BLE_HCI_CONN_FILT_USE_WL; - hcc.peer_addr_type = 0; - memset(hcc.peer_addr, 0, sizeof hcc.peer_addr); + cmd->filter_policy = BLE_HCI_CONN_FILT_USE_WL; + cmd->peer_addr_type = 0; + memset(cmd->peer_addr, 0, sizeof(cmd->peer_addr)); } else { - hcc.filter_policy = BLE_HCI_CONN_FILT_NO_WL; - hcc.peer_addr_type = peer_addr->type;; - memcpy(hcc.peer_addr, peer_addr->val, sizeof hcc.peer_addr); + cmd->filter_policy = BLE_HCI_CONN_FILT_NO_WL; + cmd->peer_addr_type = peer_addr->type; + memcpy(cmd->peer_addr, peer_addr->val, sizeof(cmd->peer_addr)); } - hcc.own_addr_type = own_addr_type; - - hcc.init_phy_mask = phy_mask; + cmd->own_addr_type = own_addr_type; + cmd->init_phy_mask = phy_mask; if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) { - /* XXX same structs */ - ble_gap_copy_params(&hcc.params[0], phy_1m_conn_params); + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_1M, phy_1m_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_1m_conn_params->scan_itvl); + params->scan_window = htole16(phy_1m_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_1m_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_1m_conn_params->itvl_max); + params->conn_latency = htole16(phy_1m_conn_params->latency); + params->supervision_timeout = htole16(phy_1m_conn_params->supervision_timeout); + params->min_ce = htole16(phy_1m_conn_params->min_ce_len); + params->max_ce = htole16(phy_1m_conn_params->max_ce_len); + + params++; + len += sizeof(*params); } if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) { - /* XXX same structs */ - ble_gap_copy_params(&hcc.params[1], phy_2m_conn_params); + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_2M, phy_2m_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_2m_conn_params->scan_itvl); + params->scan_window = htole16(phy_2m_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_2m_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_2m_conn_params->itvl_max); + params->conn_latency = htole16(phy_2m_conn_params->latency); + params->supervision_timeout = htole16(phy_2m_conn_params->supervision_timeout); + params->min_ce = htole16(phy_2m_conn_params->min_ce_len); + params->max_ce = htole16(phy_2m_conn_params->max_ce_len); + + params++; + len += sizeof(*params); } if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) { - /* XXX same structs */ - ble_gap_copy_params(&hcc.params[2], phy_coded_conn_params); + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_CODED, phy_coded_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_coded_conn_params->scan_itvl); + params->scan_window = htole16(phy_coded_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_coded_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_coded_conn_params->itvl_max); + params->conn_latency = htole16(phy_coded_conn_params->latency); + params->supervision_timeout = htole16(phy_coded_conn_params->supervision_timeout); + params->min_ce = htole16(phy_coded_conn_params->min_ce_len); + params->max_ce = htole16(phy_coded_conn_params->max_ce_len); + + params++; + len += sizeof(*params); } - rc = ble_hs_hci_cmd_build_le_ext_create_conn(&hcc, buf, sizeof buf); - if (rc != 0) { - return BLE_HS_EUNKNOWN; - } - - rc = ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_EXT_CREATE_CONN), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_EXT_CREATE_CONN), + cmd, len, NULL, 0); } /** @@ -4619,7 +4627,7 @@ ble_gap_conn_active(void) int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason) { - uint8_t buf[BLE_HCI_DISCONNECT_CMD_LEN]; + struct ble_hci_lc_disconnect_cp cmd; int rc; BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task()); @@ -4631,11 +4639,12 @@ ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason) "conn_handle=%d hci_reason=%d\n", conn->bhc_handle, hci_reason); - ble_hs_hci_cmd_build_disconnect(conn->bhc_handle, hci_reason, - buf, sizeof buf); - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, - BLE_HCI_OCF_DISCONNECT_CMD), - buf, sizeof(buf)); + cmd.conn_handle = htole16(conn->bhc_handle); + cmd.reason = hci_reason; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, + BLE_HCI_OCF_DISCONNECT_CMD), + &cmd, sizeof(cmd), NULL, 0); if (rc != 0) { return rc; } @@ -4680,9 +4689,9 @@ ble_gap_conn_cancel_tx(void) { int rc; - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_CREATE_CONN_CANCEL), - NULL, 0); + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CREATE_CONN_CANCEL), + NULL, 0, NULL, 0); if (rc != 0) { return rc; } @@ -4841,52 +4850,36 @@ static int ble_gap_tx_param_pos_reply(uint16_t conn_handle, struct ble_gap_upd_params *params) { - uint8_t buf[BLE_HCI_CONN_PARAM_REPLY_LEN]; - struct hci_conn_param_reply pos_reply; - int rc; + struct ble_hci_le_rem_conn_param_rr_cp cmd; - pos_reply.handle = conn_handle; - pos_reply.conn_itvl_min = params->itvl_min; - pos_reply.conn_itvl_max = params->itvl_max; - pos_reply.conn_latency = params->latency; - pos_reply.supervision_timeout = params->supervision_timeout; - pos_reply.min_ce_len = params->min_ce_len; - pos_reply.max_ce_len = params->max_ce_len; + cmd.conn_handle = htole16(conn_handle); + cmd.conn_itvl_min = htole16(params->itvl_min); + cmd.conn_itvl_max = htole16(params->itvl_max); + cmd.conn_latency = htole16(params->latency); + cmd.supervision_timeout = htole16(params->supervision_timeout); + cmd.min_ce = htole16(params->min_ce_len); + cmd.max_ce = htole16(params->max_ce_len); - ble_hs_hci_cmd_build_le_conn_param_reply(&pos_reply, buf, sizeof buf); - rc = ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_RR), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_REM_CONN_PARAM_RR), + &cmd, sizeof(cmd), NULL, 0); } static int ble_gap_tx_param_neg_reply(uint16_t conn_handle, uint8_t reject_reason) { - uint8_t buf[BLE_HCI_CONN_PARAM_NEG_REPLY_LEN]; - struct hci_conn_param_neg_reply neg_reply; - int rc; + struct ble_hci_le_rem_conn_params_nrr_cp cmd; - neg_reply.handle = conn_handle; - neg_reply.reason = reject_reason; + cmd.conn_handle = htole16(conn_handle); + cmd.reason = reject_reason; - ble_hs_hci_cmd_build_le_conn_param_neg_reply(&neg_reply, buf, sizeof buf); - rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR), + &cmd, sizeof(cmd), NULL, 0); } void -ble_gap_rx_param_req(struct hci_le_conn_param_req *evt) +ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev) { #if !NIMBLE_BLE_CONNECT return; @@ -4895,17 +4888,15 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt) struct ble_gap_upd_params peer_params; struct ble_gap_upd_params self_params; struct ble_gap_event event; - uint8_t reject_reason; + uint16_t conn_handle; int rc; - reject_reason = 0; /* Silence warning. */ - memset(&event, 0, sizeof event); - peer_params.itvl_min = evt->itvl_min; - peer_params.itvl_max = evt->itvl_max; - peer_params.latency = evt->latency; - peer_params.supervision_timeout = evt->timeout; + peer_params.itvl_min = le16toh(ev->min_interval); + peer_params.itvl_max = le16toh(ev->max_interval); + peer_params.latency = le16toh(ev->latency); + peer_params.supervision_timeout = le16toh(ev->timeout); peer_params.min_ce_len = 0; peer_params.max_ce_len = 0; @@ -4915,23 +4906,21 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt) */ self_params = peer_params; + conn_handle = le16toh(ev->conn_handle); + memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_CONN_UPDATE_REQ; - event.conn_update_req.conn_handle = evt->connection_handle; + event.conn_update_req.conn_handle = conn_handle; event.conn_update_req.self_params = &self_params; event.conn_update_req.peer_params = &peer_params; - rc = ble_gap_call_conn_event_cb(&event, evt->connection_handle); - if (rc != 0) { - reject_reason = rc; - } - + rc = ble_gap_call_conn_event_cb(&event, conn_handle); if (rc == 0) { - rc = ble_gap_tx_param_pos_reply(evt->connection_handle, &self_params); + rc = ble_gap_tx_param_pos_reply(conn_handle, &self_params); if (rc != 0) { - ble_gap_update_failed(evt->connection_handle, rc); + ble_gap_update_failed(conn_handle, rc); } } else { - ble_gap_tx_param_neg_reply(evt->connection_handle, reject_reason); + ble_gap_tx_param_neg_reply(conn_handle, rc); } } @@ -4939,31 +4928,19 @@ static int ble_gap_update_tx(uint16_t conn_handle, const struct ble_gap_upd_params *params) { - uint8_t buf[BLE_HCI_CONN_UPDATE_LEN]; - struct hci_conn_update cmd; - int rc; + struct ble_hci_le_conn_update_cp cmd; - cmd.handle = conn_handle; - cmd.conn_itvl_min = params->itvl_min; - cmd.conn_itvl_max = params->itvl_max; - cmd.conn_latency = params->latency; - cmd.supervision_timeout = params->supervision_timeout; - cmd.min_ce_len = params->min_ce_len; - cmd.max_ce_len = params->max_ce_len; + cmd.conn_handle = htole16(conn_handle); + cmd.conn_itvl_min = htole16(params->itvl_min); + cmd.conn_itvl_max = htole16(params->itvl_max); + cmd.conn_latency = htole16(params->latency); + cmd.supervision_timeout = htole16(params->supervision_timeout); + cmd.min_ce_len = htole16(params->min_ce_len); + cmd.max_ce_len = htole16(params->max_ce_len); - rc = ble_hs_hci_cmd_build_le_conn_update(&cmd, 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_CONN_UPDATE), - buf, sizeof(buf)); - if (rc != 0) { - return rc; - } - - return 0; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CONN_UPDATE), + &cmd, sizeof(cmd), NULL, 0); } static bool diff --git a/nimble/host/src/ble_gap_priv.h b/nimble/host/src/ble_gap_priv.h index a2eff5398..06ab765ca 100644 --- a/nimble/host/src/ble_gap_priv.h +++ b/nimble/host/src/ble_gap_priv.h @@ -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, diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c index 2e5451a99..23ac1d146 100644 --- a/nimble/host/src/ble_hs.c +++ b/nimble/host/src/ble_hs.c @@ -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 diff --git a/nimble/host/src/ble_hs_adv.c b/nimble/host/src/ble_hs_adv.c index 7a582b7b3..084076735 100644 --- a/nimble/host/src/ble_hs_adv.c +++ b/nimble/host/src/ble_hs_adv.c @@ -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; diff --git a/nimble/host/src/ble_hs_hci.c b/nimble/host/src/ble_hs_hci.c index 758b9c9d4..2062eb96d 100644 --- a/nimble/host/src/ble_hs_hci.c +++ b/nimble/host/src/ble_hs_hci.c @@ -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); } diff --git a/nimble/host/src/ble_hs_hci_cmd.c b/nimble/host/src/ble_hs_hci_cmd.c index ee2ba6552..a0fd1ceac 100644 --- a/nimble/host/src/ble_hs_hci_cmd.c +++ b/nimble/host/src/ble_hs_hci_cmd.c @@ -29,16 +29,16 @@ #include "ble_monitor_priv.h" static int -ble_hs_hci_cmd_transport(uint8_t *cmdbuf) +ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) { int rc; #if BLE_MONITOR - ble_monitor_send(BLE_MONITOR_OPCODE_COMMAND_PKT, cmdbuf, - cmdbuf[2] + BLE_HCI_CMD_HDR_LEN); + ble_monitor_send(BLE_MONITOR_OPCODE_COMMAND_PKT, cmd, + cmd->length + sizeof(*cmd)); #endif - rc = ble_hci_trans_hs_cmd_tx(cmdbuf); + rc = ble_hci_trans_hs_cmd_tx((uint8_t *) cmd); switch (rc) { case 0: return 0; @@ -51,35 +51,22 @@ ble_hs_hci_cmd_transport(uint8_t *cmdbuf) } } -void -ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint16_t ocf, uint8_t len, void *buf) -{ - uint16_t opcode; - uint8_t *u8ptr; - - u8ptr = buf; - - opcode = (ogf << 10) | ocf; - put_le16(u8ptr, opcode); - u8ptr[2] = len; -} - static int ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) { - uint8_t *buf; + struct ble_hci_cmd *cmd; int rc; - buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - BLE_HS_DBG_ASSERT(buf != NULL); + cmd = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); + BLE_HS_DBG_ASSERT(cmd != NULL); - put_le16(buf, opcode); - buf[2] = len; + cmd->opcode = htole16(opcode); + cmd->length = len; if (len != 0) { - memcpy(buf + BLE_HCI_CMD_HDR_LEN, cmddata, len); + memcpy(cmd->data, cmddata, len); } - rc = ble_hs_hci_cmd_transport(buf); + rc = ble_hs_hci_cmd_transport(cmd); if (rc == 0) { STATS_INC(ble_hs_stats, hci_cmd); @@ -91,7 +78,7 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) } int -ble_hs_hci_cmd_send_buf(uint16_t opcode, void *buf, uint8_t buf_len) +ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len) { switch (ble_hs_sync_state) { case BLE_HS_SYNC_STATE_BAD: @@ -113,1716 +100,3 @@ ble_hs_hci_cmd_send_buf(uint16_t opcode, void *buf, uint8_t buf_len) return ble_hs_hci_cmd_send(opcode, buf_len, buf); } - - -/** - * Send a LE command from the host to the controller. - * - * @param ocf - * @param len - * @param cmddata - * - * @return int - */ -static int -ble_hs_hci_cmd_le_send(uint16_t ocf, uint8_t len, void *cmddata) -{ - return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_LE, ocf), len, cmddata); -} - -static int -ble_hs_hci_cmd_body_le_whitelist_chg(const uint8_t *addr, uint8_t addr_type, - uint8_t *dst) -{ - if (addr_type > BLE_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = addr_type; - memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN); - - return 0; -} - -static int -ble_hs_hci_cmd_body_le_set_adv_params(const struct hci_adv_params *adv, - uint8_t *dst) -{ - uint16_t itvl; - - BLE_HS_DBG_ASSERT(adv != NULL); - - /* Make sure parameters are valid */ - if ((adv->adv_itvl_min > adv->adv_itvl_max) || - (adv->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) || - (adv->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) || - (adv->adv_filter_policy > BLE_HCI_ADV_FILT_MAX) || - (adv->adv_type > BLE_HCI_ADV_TYPE_MAX) || - (adv->adv_channel_map == 0) || - ((adv->adv_channel_map & 0xF8) != 0)) { - /* These parameters are not valid */ - return -1; - } - -/* When build with nimBLE controller we know it is BT5 compliant so no need - * to limit non-connectable advertising interval - */ -#if MYNEWT_VAL(BLE_CONTROLLER) - itvl = BLE_HCI_ADV_ITVL_MIN; -#else - /* Make sure interval is valid for advertising type. */ - if (((adv->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) || - (adv->adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) && - ble_hs_hci_get_hci_version() < BLE_HCI_VER_BCS_5_0) { - itvl = BLE_HCI_ADV_ITVL_NONCONN_MIN; - } else { - itvl = BLE_HCI_ADV_ITVL_MIN; - } -#endif - - /* Do not check if high duty-cycle directed */ - if (adv->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { - if ((adv->adv_itvl_min < itvl) || - (adv->adv_itvl_min > BLE_HCI_ADV_ITVL_MAX)) { - return -1; - } - } - - put_le16(dst, adv->adv_itvl_min); - put_le16(dst + 2, adv->adv_itvl_max); - dst[4] = adv->adv_type; - dst[5] = adv->own_addr_type; - dst[6] = adv->peer_addr_type; - memcpy(dst + 7, adv->peer_addr, BLE_DEV_ADDR_LEN); - dst[13] = adv->adv_channel_map; - dst[14] = adv->adv_filter_policy; - - return 0; -} - -int -ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params *adv, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADV_PARAM_LEN); - - return ble_hs_hci_cmd_body_le_set_adv_params(adv, dst); -} - -/** - * Set advertising data - * - * OGF = 0x08 (LE) - * OCF = 0x0008 - * - * @param data - * @param len - * @param dst - * - * @return int - */ -static int -ble_hs_hci_cmd_body_le_set_adv_data(const uint8_t *data, uint8_t len, - uint8_t *dst) -{ - /* Check for valid parameters */ - if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_ADV_DATA_LEN)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - memset(dst, 0, BLE_HCI_SET_ADV_DATA_LEN); - dst[0] = len; - memcpy(dst + 1, data, len); - - return 0; -} - -/** - * Set advertising data - * - * OGF = 0x08 (LE) - * OCF = 0x0008 - * - * @param data - * @param len - * @param dst - * - * @return int - */ -int -ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t *data, uint8_t len, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADV_DATA_LEN); - - return ble_hs_hci_cmd_body_le_set_adv_data(data, len, dst); -} - -static int -ble_hs_hci_cmd_body_le_set_scan_rsp_data(const uint8_t *data, uint8_t len, - uint8_t *dst) -{ - /* Check for valid parameters */ - if (((data == NULL) && (len != 0)) || - (len > BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - memset(dst, 0, BLE_HCI_SET_SCAN_RSP_DATA_LEN); - dst[0] = len; - memcpy(dst + 1, data, len); - - return 0; -} - -int -ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t *data, uint8_t len, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_SCAN_RSP_DATA_LEN); - - return ble_hs_hci_cmd_body_le_set_scan_rsp_data(data, len, dst); -} - -static void -ble_hs_hci_cmd_body_set_event_mask(uint64_t event_mask, uint8_t *dst) -{ - put_le64(dst, event_mask); -} - -void -ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_EVENT_MASK_LEN); - - ble_hs_hci_cmd_body_set_event_mask(event_mask, dst); -} - -void -ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_EVENT_MASK_LEN); - - ble_hs_hci_cmd_body_set_event_mask(event_mask, dst); -} - -static void -ble_hs_hci_cmd_body_disconnect(uint16_t handle, uint8_t reason, uint8_t *dst) -{ - put_le16(dst + 0, handle); - dst[2] = reason; -} - -void -ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_DISCONNECT_CMD_LEN); - - ble_hs_hci_cmd_body_disconnect(handle, reason, dst); -} - -static void -ble_hs_hci_cmd_body_le_set_event_mask(uint64_t event_mask, uint8_t *dst) -{ - put_le64(dst, event_mask); -} - -void -ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_LE_EVENT_MASK_LEN); - - ble_hs_hci_cmd_body_le_set_event_mask(event_mask, dst); -} - -static void -ble_hs_hci_cmd_body_le_set_adv_enable(uint8_t enable, uint8_t *dst) -{ - dst[0] = enable; -} - -void -ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst, - int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADV_ENABLE_LEN); - - ble_hs_hci_cmd_body_le_set_adv_enable(enable, dst); -} - -static int -ble_hs_hci_cmd_body_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) { - - /* Make sure parameters are valid */ - if ((scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) && - (scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check interval and window */ - if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || - (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || - (scan_window < BLE_HCI_SCAN_WINDOW_MIN) || - (scan_window > BLE_HCI_SCAN_WINDOW_MAX) || - (scan_itvl < scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check own addr type */ - if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check scanner filter policy */ - if (filter_policy > BLE_HCI_SCAN_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = scan_type; - put_le16(dst + 1, scan_itvl); - put_le16(dst + 3, scan_window); - dst[5] = own_addr_type; - dst[6] = filter_policy; - - return 0; -} - -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_SCAN_PARAM_LEN); - - return ble_hs_hci_cmd_body_le_set_scan_params(scan_type, scan_itvl, - scan_window, own_addr_type, - filter_policy, dst); -} - -static void -ble_hs_hci_cmd_body_le_set_scan_enable(uint8_t enable, uint8_t filter_dups, - uint8_t *dst) -{ - dst[0] = enable; - dst[1] = filter_dups; -} - -void -ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable, uint8_t filter_dups, - uint8_t *dst, uint8_t dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_SCAN_ENABLE_LEN); - - ble_hs_hci_cmd_body_le_set_scan_enable(enable, filter_dups, dst); -} - -static int -ble_hs_hci_cmd_body_le_create_connection(const struct hci_create_conn *hcc, - uint8_t *cmd) -{ - /* Check scan interval and scan window */ - if ((hcc->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || - (hcc->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || - (hcc->scan_window < BLE_HCI_SCAN_WINDOW_MIN) || - (hcc->scan_window > BLE_HCI_SCAN_WINDOW_MAX) || - (hcc->scan_itvl < hcc->scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check initiator filter policy */ - if (hcc->filter_policy > BLE_HCI_CONN_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check peer addr type */ - if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check own addr type */ - if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection interval min */ - if ((hcc->conn_itvl_min < BLE_HCI_CONN_ITVL_MIN) || - (hcc->conn_itvl_min > BLE_HCI_CONN_ITVL_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection interval max */ - if ((hcc->conn_itvl_max < BLE_HCI_CONN_ITVL_MIN) || - (hcc->conn_itvl_max > BLE_HCI_CONN_ITVL_MAX) || - (hcc->conn_itvl_max < hcc->conn_itvl_min)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection latency */ - if ((hcc->conn_latency < BLE_HCI_CONN_LATENCY_MIN) || - (hcc->conn_latency > BLE_HCI_CONN_LATENCY_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check supervision timeout */ - if ((hcc->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || - (hcc->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection event length */ - if (hcc->min_ce_len > hcc->max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - put_le16(cmd + 0, hcc->scan_itvl); - put_le16(cmd + 2, hcc->scan_window); - cmd[4] = hcc->filter_policy; - cmd[5] = hcc->peer_addr_type; - memcpy(cmd + 6, hcc->peer_addr, BLE_DEV_ADDR_LEN); - cmd[12] = hcc->own_addr_type; - put_le16(cmd + 13, hcc->conn_itvl_min); - put_le16(cmd + 15, hcc->conn_itvl_max); - put_le16(cmd + 17, hcc->conn_latency); - put_le16(cmd + 19, hcc->supervision_timeout); - put_le16(cmd + 21, hcc->min_ce_len); - put_le16(cmd + 23, hcc->max_ce_len); - - return 0; -} - -int -ble_hs_hci_cmd_build_le_create_connection(const struct hci_create_conn *hcc, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_CREATE_CONN_LEN); - - return ble_hs_hci_cmd_body_le_create_connection(hcc, cmd); -} - -int -ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t *addr, - uint8_t addr_type, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_ADD_WHITE_LIST_LEN); - - return ble_hs_hci_cmd_body_le_whitelist_chg(addr, addr_type, dst); -} - -/** - * Reset the controller and link manager. - * - * @return int - */ -int -ble_hs_hci_cmd_reset(void) -{ - return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, - BLE_HCI_OCF_CB_RESET), - 0, NULL); -} - -/** Set controller to host flow control (OGF 0x03, OCF 0x0031). */ -int -ble_hs_hci_cmd_tx_set_ctlr_to_host_fc(uint8_t fc_enable) -{ - if (fc_enable > BLE_HCI_CTLR_TO_HOST_FC_BOTH) { - return BLE_HS_EINVAL; - } - - return ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, - BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC), - &fc_enable, 1); -} - -/* Host buffer size (OGF 0x03, OCF 0x0033). */ -int -ble_hs_hci_cmd_tx_host_buf_size(const struct hci_host_buf_size *cmd) -{ - uint8_t buf[BLE_HCI_HOST_BUF_SIZE_LEN]; - - put_le16(buf + 0, cmd->acl_pkt_len); - buf[2] = cmd->sync_pkt_len; - put_le16(buf + 3, cmd->num_acl_pkts); - put_le16(buf + 5, cmd->num_sync_pkts); - - return ble_hs_hci_cmd_tx_empty_ack( - BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_HOST_BUF_SIZE), - buf, sizeof buf); -} - -/* Host number of completed packets (OGF 0x03, OCF 0x0035). */ -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) -{ - if (dst_len < BLE_HCI_HOST_NUM_COMP_PKTS_ENT_LEN) { - return BLE_HS_EMSGSIZE; - } - - put_le16(dst + 0, entry->conn_handle); - put_le16(dst + 2, entry->num_pkts); - - return 0; -} - -/** - * Read the transmit power level used for LE advertising channel packets. - * - * @return int - */ -int -ble_hs_hci_cmd_read_adv_pwr(void) -{ - return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR), - 0, NULL); -} - -int -ble_hs_hci_cmd_le_create_conn_cancel(void) -{ - return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_CREATE_CONN_CANCEL), - 0, NULL); -} - -static int -ble_hs_hci_cmd_body_le_conn_update(const struct hci_conn_update *hcu, - uint8_t *dst) -{ - /* XXX: add parameter checking later */ - put_le16(dst + 0, hcu->handle); - put_le16(dst + 2, hcu->conn_itvl_min); - put_le16(dst + 4, hcu->conn_itvl_max); - put_le16(dst + 6, hcu->conn_latency); - put_le16(dst + 8, hcu->supervision_timeout); - put_le16(dst + 10, hcu->min_ce_len); - put_le16(dst + 12, hcu->max_ce_len); - - return 0; -} - -int -ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update *hcu, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_UPDATE_LEN); - - return ble_hs_hci_cmd_body_le_conn_update(hcu, dst); -} - -int -ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update *hcu) -{ - uint8_t cmd[BLE_HCI_CONN_UPDATE_LEN]; - int rc; - - rc = ble_hs_hci_cmd_body_le_conn_update(hcu, cmd); - if (rc != 0) { - return rc; - } - - return ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_CONN_UPDATE, - BLE_HCI_CONN_UPDATE_LEN, cmd); -} - -static void -ble_hs_hci_cmd_body_le_lt_key_req_reply(const struct hci_lt_key_req_reply *hkr, - uint8_t *dst) -{ - put_le16(dst + 0, hkr->conn_handle); - memcpy(dst + 2, hkr->long_term_key, sizeof hkr->long_term_key); -} - -/** - * Sends the long-term key (LTK) to the controller. - * - * Note: This function expects the 128-bit key to be in little-endian byte - * order. - * - * OGF = 0x08 (LE) - * OCF = 0x001a - * - * @param key - * @param pt - * - * @return int - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LT_KEY_REQ_REPLY_LEN); - - ble_hs_hci_cmd_body_le_lt_key_req_reply(hkr, dst); -} - -void -ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN); - - put_le16(dst, conn_handle); -} - -static void -ble_hs_hci_cmd_body_le_conn_param_reply(const struct hci_conn_param_reply *hcr, - uint8_t *dst) -{ - put_le16(dst + 0, hcr->handle); - put_le16(dst + 2, hcr->conn_itvl_min); - put_le16(dst + 4, hcr->conn_itvl_max); - put_le16(dst + 6, hcr->conn_latency); - put_le16(dst + 8, hcr->supervision_timeout); - put_le16(dst + 10, hcr->min_ce_len); - put_le16(dst + 12, hcr->max_ce_len); -} - -void -ble_hs_hci_cmd_build_le_conn_param_reply( - const struct hci_conn_param_reply *hcr, uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_PARAM_REPLY_LEN); - - ble_hs_hci_cmd_body_le_conn_param_reply(hcr, dst); -} - -int -ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply *hcr) -{ - uint8_t cmd[BLE_HCI_CONN_PARAM_REPLY_LEN]; - - put_le16(cmd + 0, hcr->handle); - put_le16(cmd + 2, hcr->conn_itvl_min); - put_le16(cmd + 4, hcr->conn_itvl_max); - put_le16(cmd + 6, hcr->conn_latency); - put_le16(cmd + 8, hcr->supervision_timeout); - put_le16(cmd + 10, hcr->min_ce_len); - put_le16(cmd + 12, hcr->max_ce_len); - - return ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_RR, - BLE_HCI_CONN_PARAM_REPLY_LEN, cmd); -} - -static void -ble_hs_hci_cmd_body_le_conn_param_neg_reply( - const struct hci_conn_param_neg_reply *hcn, uint8_t *dst) -{ - put_le16(dst + 0, hcn->handle); - dst[2] = hcn->reason; -} - - -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_PARAM_NEG_REPLY_LEN); - - ble_hs_hci_cmd_body_le_conn_param_neg_reply(hcn, dst); -} - -int -ble_hs_hci_cmd_le_conn_param_neg_reply( - const struct hci_conn_param_neg_reply *hcn) -{ - uint8_t cmd[BLE_HCI_CONN_PARAM_NEG_REPLY_LEN]; - - ble_hs_hci_cmd_body_le_conn_param_neg_reply(hcn, cmd); - - return ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR, - BLE_HCI_CONN_PARAM_NEG_REPLY_LEN, cmd); -} - -static void -ble_hs_hci_cmd_body_le_start_encrypt(const struct hci_start_encrypt *cmd, - uint8_t *dst) -{ - put_le16(dst + 0, cmd->connection_handle); - put_le64(dst + 2, cmd->random_number); - put_le16(dst + 10, cmd->encrypted_diversifier); - memcpy(dst + 12, cmd->long_term_key, sizeof cmd->long_term_key); -} - -/* - * OGF=0x08 OCF=0x0019 - */ -void -ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt *cmd, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_START_ENCRYPT_LEN); - - ble_hs_hci_cmd_body_le_start_encrypt(cmd, dst); -} - -/** - * Read the RSSI for a given connection handle - * - * NOTE: OGF=0x05 OCF=0x0005 - * - * @param handle - * - * @return int - */ -static void -ble_hs_hci_cmd_body_read_rssi(uint16_t handle, uint8_t *dst) -{ - put_le16(dst, handle); -} - -void -ble_hs_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_READ_RSSI_LEN); - - ble_hs_hci_cmd_body_read_rssi(handle, dst); -} - -/** - * LE Set Host Channel Classification - * - * OGF = 0x08 (LE) - * OCF = 0x0014 - */ -void -ble_hs_hci_cmd_build_le_set_host_chan_class(const uint8_t *chan_map, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_HOST_CHAN_CLASS_LEN); - - memcpy(dst, chan_map, BLE_HCI_SET_HOST_CHAN_CLASS_LEN); -} - -/** - * LE Read Channel Map - * - * OGF = 0x08 (LE) - * OCF = 0x0015 - */ -void -ble_hs_hci_cmd_build_le_read_chan_map(uint16_t conn_handle, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RD_CHANMAP_LEN); - - put_le16(dst + 0, conn_handle); -} - -static int -ble_hs_hci_cmd_body_set_data_len(uint16_t connection_handle, - uint16_t tx_octets, - uint16_t tx_time, uint8_t *dst) -{ - - 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; - } - - put_le16(dst + 0, connection_handle); - put_le16(dst + 2, tx_octets); - put_le16(dst + 4, tx_time); - - return 0; -} - -/* - * OGF=0x08 OCF=0x0022 - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_DATALEN_LEN); - - return ble_hs_hci_cmd_body_set_data_len(connection_handle, tx_octets, - tx_time, dst); -} - -/** - * IRKs are in little endian. - */ -static int -ble_hs_hci_cmd_body_add_to_resolv_list(uint8_t addr_type, const uint8_t *addr, - const uint8_t *peer_irk, - const uint8_t *local_irk, - uint8_t *dst) -{ - if (addr_type > BLE_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = addr_type; - memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN); - memcpy(dst + 1 + 6, peer_irk , 16); - memcpy(dst + 1 + 6 + 16, local_irk , 16); - /* 16 + 16 + 6 + 1 == 39 */ - return 0; -} - -/** - * OGF=0x08 OCF=0x0027 - * - * IRKs are in little endian. - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_ADD_TO_RESOLV_LIST_LEN); - - return ble_hs_hci_cmd_body_add_to_resolv_list( - padd->addr_type, padd->addr, padd->peer_irk, padd->local_irk, dst); -} - -static int -ble_hs_hci_cmd_body_remove_from_resolv_list(uint8_t addr_type, - const uint8_t *addr, - uint8_t *dst) -{ - if (addr_type > BLE_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = addr_type; - memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN); - return 0; -} - - -int -ble_hs_hci_cmd_build_remove_from_resolv_list(uint8_t addr_type, - const uint8_t *addr, - uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RMV_FROM_RESOLV_LIST_LEN); - - return ble_hs_hci_cmd_body_remove_from_resolv_list(addr_type, addr, dst); -} - -static int -ble_hs_hci_cmd_body_read_peer_resolv_addr(uint8_t peer_identity_addr_type, - const uint8_t *peer_identity_addr, - uint8_t *dst) -{ - if (peer_identity_addr_type > BLE_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = peer_identity_addr_type; - memcpy(dst + 1, peer_identity_addr, BLE_DEV_ADDR_LEN); - return 0; -} - -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RD_PEER_RESOLV_ADDR_LEN); - - return ble_hs_hci_cmd_body_read_peer_resolv_addr(peer_identity_addr_type, - peer_identity_addr, dst); -} - -static int -ble_hs_hci_cmd_body_read_lcl_resolv_addr( - uint8_t local_identity_addr_type, - const uint8_t *local_identity_addr, - uint8_t *dst) -{ - if (local_identity_addr_type > BLE_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = local_identity_addr_type; - memcpy(dst + 1, local_identity_addr, BLE_DEV_ADDR_LEN); - return 0; -} - -/* - * OGF=0x08 OCF=0x002c - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RD_LOC_RESOLV_ADDR_LEN); - - return ble_hs_hci_cmd_body_read_lcl_resolv_addr(local_identity_addr_type, - local_identity_addr, dst); -} - -static int -ble_hs_hci_cmd_body_set_addr_res_en(uint8_t enable, uint8_t *dst) -{ - if (enable > 1) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = enable; - return 0; -} - -/* - * OGF=0x08 OCF=0x002d - */ -int -ble_hs_hci_cmd_build_set_addr_res_en(uint8_t enable, uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADDR_RESOL_ENA_LEN); - - return ble_hs_hci_cmd_body_set_addr_res_en(enable, dst); -} - -static int -ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(uint16_t timeout, - uint8_t *dst) -{ - if (timeout == 0 || timeout > 0xA1B8) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - put_le16(dst, timeout); - return 0; -} - -/* - * OGF=0x08 OCF=0x002e - */ -int -ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout( - uint16_t timeout, uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN); - - return ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(timeout, dst); -} - -/* - * OGF=0x08 OCF=0x0030 - */ -int -ble_hs_hci_cmd_build_le_read_phy(uint16_t conn_handle, uint8_t *dst, int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_RD_PHY_LEN); - - put_le16(dst, conn_handle); - - return 0; -} - -static int -ble_hs_hci_verify_le_phy_params(uint8_t tx_phys_mask, uint8_t rx_phys_mask, - uint16_t phy_opts) -{ - if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | - BLE_HCI_LE_PHY_2M_PREF_MASK | - BLE_HCI_LE_PHY_CODED_PREF_MASK)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (rx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | - BLE_HCI_LE_PHY_2M_PREF_MASK | - BLE_HCI_LE_PHY_CODED_PREF_MASK)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (phy_opts > BLE_HCI_LE_PHY_CODED_S8_PREF) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return 0; -} - -static int -ble_hs_hci_cmd_body_le_set_default_phy(uint8_t tx_phys_mask, - uint8_t rx_phys_mask, uint8_t *dst) -{ - int rc; - - rc = ble_hs_hci_verify_le_phy_params(tx_phys_mask, rx_phys_mask, 0); - if (rc !=0 ) { - return rc; - } - - if (tx_phys_mask == 0) { - dst[0] |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK; - } else { - dst[1] = tx_phys_mask; - } - - if (rx_phys_mask == 0){ - dst[0] |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK; - } else { - dst[2] = rx_phys_mask; - } - - return 0; -} - -/* - * OGF=0x08 OCF=0x0031 - */ -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) -{ - - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_DEFAULT_PHY_LEN); - - memset(dst, 0, dst_len); - - return ble_hs_hci_cmd_body_le_set_default_phy(tx_phys_mask, rx_phys_mask, - dst); -} - -static int -ble_hs_hci_cmd_body_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 rc; - - rc = ble_hs_hci_verify_le_phy_params(tx_phys_mask, rx_phys_mask, phy_opts); - if (rc != 0) { - return rc; - } - - put_le16(dst, conn_handle); - - if (tx_phys_mask == 0) { - dst[2] |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK; - } else { - dst[3] = tx_phys_mask; - } - - if (rx_phys_mask == 0){ - dst[2] |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK; - } else { - dst[4] = rx_phys_mask; - } - - put_le16(dst + 5, phy_opts); - - return 0; -} - -/* - * OGF=0x08 OCF=0x0032 - */ -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) -{ - - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_PHY_LEN); - - memset(dst, 0, dst_len); - - return ble_hs_hci_cmd_body_le_set_phy(conn_handle, tx_phys_mask, - rx_phys_mask, phy_opts, dst); -} - -static int -ble_hs_hci_cmd_body_le_enhanced_recv_test(uint8_t chan, uint8_t phy, - uint8_t mod_idx, uint8_t *dst) -{ - /* Parameters check according to Bluetooth 5.0 Vol 2, Part E - * 7.8.50 LE Enhanced Receiver Test Command - */ - if (phy > BLE_HCI_LE_PHY_CODED || chan > 0x27 || mod_idx > 1) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = chan; - dst[1] = phy; - dst[2] = mod_idx; - - return 0; -} - -/* - * OGF=0x08 OCF=0x0033 - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_RX_TEST_LEN); - - return ble_hs_hci_cmd_body_le_enhanced_recv_test(rx_chan, phy, mod_idx, dst); -} - -static int -ble_hs_hci_cmd_body_le_enhanced_trans_test(uint8_t chan, uint8_t test_data_len, - uint8_t packet_payload_idx, - uint8_t phy, - uint8_t *dst) -{ - /* Parameters check according to Bluetooth 5.0 Vol 2, Part E - * 7.8.51 LE Enhanced Transmitter Test Command - */ - if (phy > BLE_HCI_LE_PHY_CODED_S2 || chan > 0x27 || - packet_payload_idx > 0x07) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = chan; - dst[1] = test_data_len; - dst[2] = packet_payload_idx; - dst[3] = phy; - - return 0; -} - -/* - * OGF=0x08 OCF=0x0034 - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_TX_TEST_LEN); - - return ble_hs_hci_cmd_body_le_enhanced_trans_test(tx_chan, test_data_len, - packet_payload_idx, - phy, dst); -} - -#if MYNEWT_VAL(BLE_EXT_ADV) -static int -ble_hs_hci_check_scan_params(uint16_t scan_itvl, uint16_t scan_window) -{ - /* Check interval and window */ - if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || - (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || - (scan_window < BLE_HCI_SCAN_WINDOW_MIN) || - (scan_window > BLE_HCI_SCAN_WINDOW_MAX) || - (scan_itvl < scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return 0; -} - -static int -ble_hs_hci_cmd_body_le_set_ext_scan_param(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) -{ - int i; - int rc; - uint8_t *dst_params; - struct ble_hs_hci_ext_scan_param *p; - - if (phy_mask > - (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check own addr type */ - if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check scanner filter policy */ - if (filter_policy > BLE_HCI_SCAN_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = own_addr_type; - dst[1] = filter_policy; - dst[2] = phy_mask; - dst_params = &dst[3]; - - for (i = 0; i < phy_count; i++) { - p = (*params) + i; - rc = ble_hs_hci_check_scan_params(p->scan_itvl, p->scan_window); - if (rc) { - return rc; - } - - dst_params[0] = p->scan_type; - put_le16(dst_params + 1, p->scan_itvl); - put_le16(dst_params + 3, p->scan_window); - - dst_params += BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN; - } - - return 0; -} - -/* - * OGF=0x08 OCF=0x0041 - */ -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) -{ - if (phy_count == 0) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_EXT_SCAN_BASE_LEN + - BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN * phy_count); - - return ble_hs_hci_cmd_body_le_set_ext_scan_param(own_addr_type, - filter_policy, - phy_mask, - phy_count, - params, - dst); -} - -static int -ble_hs_hci_cmd_body_le_set_ext_scan_enable(uint8_t enable, uint8_t filter_dups, - uint16_t duration, uint16_t period, - uint8_t *dst) -{ - if (enable > 0x01 || filter_dups > 0x03) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = enable; - dst[1] = filter_dups; - put_le16(dst + 2, duration); - put_le16(dst + 4, period); - - return 0; -} - -/* - * OGF=0x08 OCF=0x0042 - */ -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) -{ - - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_EXT_SCAN_ENABLE_LEN); - - return ble_hs_hci_cmd_body_le_set_ext_scan_enable(enable, filter_dups, - duration, period, dst); -} - -static int -ble_hs_hci_check_conn_params(uint8_t phy, - const struct hci_ext_conn_params *params) -{ - if (phy != BLE_HCI_LE_PHY_2M) { - if (ble_hs_hci_check_scan_params(params->scan_itvl, params->scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - } - /* Check connection interval min */ - if ((params->conn_itvl_min < BLE_HCI_CONN_ITVL_MIN) || - (params->conn_itvl_min > BLE_HCI_CONN_ITVL_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - /* Check connection interval max */ - if ((params->conn_itvl_max < BLE_HCI_CONN_ITVL_MIN) || - (params->conn_itvl_max > BLE_HCI_CONN_ITVL_MAX) || - (params->conn_itvl_max < params->conn_itvl_min)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection latency */ - if ((params->conn_latency < BLE_HCI_CONN_LATENCY_MIN) || - (params->conn_latency > BLE_HCI_CONN_LATENCY_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check supervision timeout */ - if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || - (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check connection event length */ - if (params->min_ce_len > params->max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - return 0; -} - -static int -ble_hs_hci_cmd_body_le_ext_create_conn(const struct hci_ext_create_conn *hcc, - uint8_t *cmd) -{ - int iter = 0; - const struct hci_ext_conn_params *params; - - /* Check initiator filter policy */ - if (hcc->filter_policy > BLE_HCI_CONN_FILT_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - cmd[iter] = hcc->filter_policy; - iter++; - /* Check own addr type */ - if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - cmd[iter] = hcc->own_addr_type; - iter++; - - /* Check peer addr type */ - if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - cmd[iter] = hcc->peer_addr_type; - iter++; - - memcpy(cmd + iter, hcc->peer_addr, BLE_DEV_ADDR_LEN); - iter += BLE_DEV_ADDR_LEN; - - if (hcc->init_phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | - BLE_HCI_LE_PHY_2M_PREF_MASK | - BLE_HCI_LE_PHY_CODED_PREF_MASK)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - cmd[iter] = hcc->init_phy_mask; - iter++; - - if (hcc->init_phy_mask & BLE_HCI_LE_PHY_1M_PREF_MASK) { - params = &hcc->params[0]; - if (ble_hs_hci_check_conn_params(BLE_HCI_LE_PHY_1M, params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - put_le16(cmd + iter, params->scan_itvl); - put_le16(cmd + iter + 2, params->scan_window); - put_le16(cmd + iter + 4, params->conn_itvl_min); - put_le16(cmd + iter + 6, params->conn_itvl_max); - put_le16(cmd + iter + 8, params->conn_latency); - put_le16(cmd + iter + 10, params->supervision_timeout); - put_le16(cmd + iter + 12, params->min_ce_len); - put_le16(cmd + iter + 14, params->max_ce_len); - iter += 16; - } - - if (hcc->init_phy_mask & BLE_HCI_LE_PHY_2M_PREF_MASK) { - params = &hcc->params[1]; - if (ble_hs_hci_check_conn_params(BLE_HCI_LE_PHY_2M, params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - put_le16(cmd + iter, 0); - put_le16(cmd + iter + 2, 0); - put_le16(cmd + iter + 4, params->conn_itvl_min); - put_le16(cmd + iter + 6, params->conn_itvl_max); - put_le16(cmd + iter + 8, params->conn_latency); - put_le16(cmd + iter + 10, params->supervision_timeout); - put_le16(cmd + iter + 12, params->min_ce_len); - put_le16(cmd + iter + 14, params->max_ce_len); - iter += 16; - } - - if (hcc->init_phy_mask & BLE_HCI_LE_PHY_CODED_PREF_MASK) { - params = &hcc->params[2]; - if (ble_hs_hci_check_conn_params(BLE_HCI_LE_PHY_CODED, params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - put_le16(cmd + iter, params->scan_itvl); - put_le16(cmd + iter + 2, params->scan_window); - put_le16(cmd + iter + 4, params->conn_itvl_min); - put_le16(cmd + iter + 6, params->conn_itvl_max); - put_le16(cmd + iter + 8, params->conn_latency); - put_le16(cmd + iter + 10, params->supervision_timeout); - put_le16(cmd + iter + 12, params->min_ce_len); - put_le16(cmd + iter + 14, params->max_ce_len); - iter += 16; - } - - return 0; -} - -int -ble_hs_hci_cmd_build_le_ext_create_conn(const struct hci_ext_create_conn *hcc, - uint8_t *cmd, int cmd_len) -{ - uint8_t size; - - size = BLE_HCI_LE_EXT_CREATE_CONN_BASE_LEN; - if (hcc->init_phy_mask & BLE_HCI_LE_PHY_1M_PREF_MASK) { - size += sizeof(struct hci_ext_conn_params); - } - - if (hcc->init_phy_mask & BLE_HCI_LE_PHY_2M_PREF_MASK) { - size += sizeof(struct hci_ext_conn_params); - } - - if (hcc->init_phy_mask & BLE_HCI_LE_PHY_CODED_PREF_MASK) { - size += sizeof(struct hci_ext_conn_params); - } - - BLE_HS_DBG_ASSERT(cmd_len >= size); - - return ble_hs_hci_cmd_body_le_ext_create_conn(hcc, cmd); -} - -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) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN); - - cmd[0] = handle; - memcpy(cmd + 1, addr, BLE_DEV_ADDR_LEN); - - return 0; -} - -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) -{ - BLE_HS_DBG_ASSERT(cmd_len >= 4 + data_len); - - cmd[0] = handle; - cmd[1] = operation; - cmd[2] = frag_pref; - cmd[3] = data_len; - os_mbuf_copydata(data, 0, data_len, cmd + 4); - - return 0; -} - -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 i; - - BLE_HS_DBG_ASSERT(cmd_len >= 2 + (sets_num * 4)); - - cmd[0] = enable; - cmd[1] = sets_num; - - cmd += 2; - - for (i = 0; i < sets_num; i++) { - cmd[0] = sets[i].handle; - put_le16(&cmd[1], sets[i].duration); - cmd[3] = sets[i].events; - - cmd += 4; - } - - return 0; -} - -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) -{ - uint32_t tmp; - - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN); - - cmd[0] = handle; - put_le16(&cmd[1], params->properties); - - tmp = htole32(params->min_interval); - memcpy(&cmd[3], &tmp, 3); - - tmp = htole32(params->max_interval); - memcpy(&cmd[6], &tmp, 3); - - cmd[9] = params->chan_map; - cmd[10] = params->own_addr_type; - cmd[11] = params->peer_addr_type; - memcpy(&cmd[12], params->peer_addr, BLE_DEV_ADDR_LEN); - cmd[18] = params->filter_policy; - cmd[19] = params->tx_power; - cmd[20] = params->primary_phy; - cmd[21] = params->max_skip; - cmd[22] = params->secondary_phy; - cmd[23] = params->sid; - cmd[24] = params->scan_req_notif; - - return 0; -} -int -ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_REMOVE_ADV_SET_LEN); - - cmd[0] = handle; - - return 0; -} - -#if MYNEWT_VAL(BLE_PERIODIC_ADV) -int -ble_hs_hci_cmd_build_le_periodic_adv_params(uint8_t handle, - const struct hci_periodic_adv_params *params, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN); - - if (handle > 0xEF){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (params->max_interval > 0xFFFF || params->max_interval < 6){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (params->min_interval > 0xFFFF || params->min_interval < 6){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - cmd[0] = handle; - - put_le16(&cmd[1], params->min_interval); - put_le16(&cmd[3], params->max_interval); - put_le16(&cmd[5], params->properties); - - return 0; -} - -int -ble_hs_hci_cmd_build_le_periodic_adv_enable(uint8_t enable, - uint8_t handle, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN); - - if (enable > 1){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - cmd[0] = enable; - cmd[1] = handle; - - return 0; -} - -int -ble_hs_hci_cmd_build_le_periodic_adv_data(uint8_t handle, - uint8_t operation, - struct os_mbuf *data, - uint8_t data_len, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= 3 + data_len); - - if (!data){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (!data->om_data){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (handle > 0xEF){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - cmd[0] = handle; - cmd[1] = operation; - cmd[2] = data_len; - os_mbuf_copydata(data, 0, data_len, cmd + 3); - - return 0; -} - -int -ble_hs_hci_cmd_build_le_periodic_adv_create_sync(uint8_t filter_policy, - uint8_t adv_sid, - uint8_t adv_add_type, - const uint8_t *adv_addr, - uint16_t skip, - uint16_t sync_timeout, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN); - - if (filter_policy > 1 || adv_add_type > 1){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (adv_sid > 0x0f){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (skip > 0x1f3 || sync_timeout > 0x4000 || sync_timeout < 0x0A){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - cmd[0] = filter_policy; - cmd[1] = adv_sid; - cmd[2] = adv_add_type; - memcpy(&cmd[3], adv_addr, 6); - put_le16(&cmd[9], skip); - put_le16(&cmd[11], sync_timeout); - cmd[13] = 0x00; - return 0; -} - -int -ble_hs_hci_cmd_build_le_periodic_adv_terminate_sync(uint16_t sync_handle, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN); - - if (sync_handle > 0xEF){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - cmd[0] = sync_handle; - - return 0; -} - -int -ble_hs_hci_cmd_build_le_add_dev_to_periodic_adv_list( - uint8_t adv_add_type, - const uint8_t *adv_addr, - uint8_t adv_sid, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN); - - if (adv_add_type > 1 || adv_sid > 0x0f){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - cmd[0] = adv_add_type; - memcpy(&cmd[1], adv_addr, 6); - cmd[7] = adv_sid; - - return 0; -} - -int -ble_hs_hci_cmd_build_le_rem_dev_from_periodic_adv_list( - uint8_t adv_add_type, - const uint8_t *adv_addr, - uint8_t adv_sid, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN); - - if (adv_add_type > 1 || adv_sid > 0x0f){ - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - cmd[0] = adv_add_type; - memcpy(&cmd[1], adv_addr, 6); - cmd[7] = adv_sid; - - return 0; -} -#endif - -#endif - -static int -ble_hs_hci_cmd_body_le_set_priv_mode(const uint8_t *addr, uint8_t addr_type, - uint8_t priv_mode, uint8_t *dst) -{ - /* In this command addr type can be either: - * - public identity (0x00) - * - random (static) identity (0x01) - */ - if (addr_type > BLE_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - dst[0] = addr_type; - memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN); - dst[7] = priv_mode; - - return 0; -} - -/* - * OGF=0x08 OCF=0x004e - */ -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) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_PRIVACY_MODE_LEN); - - return ble_hs_hci_cmd_body_le_set_priv_mode(addr, addr_type, priv_mode, dst); -} - -static int -ble_hs_hci_cmd_body_set_random_addr(const struct hci_rand_addr *paddr, - uint8_t *dst) -{ - memcpy(dst, paddr->addr, BLE_DEV_ADDR_LEN); - return 0; -} - -int -ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr, - uint8_t *dst, int dst_len) -{ - struct hci_rand_addr r_addr; - - memcpy(r_addr.addr, addr, sizeof(r_addr.addr)); - - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_RAND_ADDR_LEN); - - return ble_hs_hci_cmd_body_set_random_addr(&r_addr, dst); -} - -static void -ble_hs_hci_cmd_body_le_read_remote_feat(uint16_t handle, uint8_t *dst) -{ - put_le16(dst, handle); -} - -int -ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle, uint8_t *dst, - int dst_len) -{ - BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_RD_REM_FEAT_LEN); - - ble_hs_hci_cmd_body_le_read_remote_feat(handle, dst); - - return 0; -} diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index 709cea395..92abbdf5e 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -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; } diff --git a/nimble/host/src/ble_hs_hci_priv.h b/nimble/host/src/ble_hs_hci_priv.h index 51ac3e9e4..b02d4ab2e 100644 --- a/nimble/host/src/ble_hs_hci_priv.h +++ b/nimble/host/src/ble_hs_hci_priv.h @@ -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 diff --git a/nimble/host/src/ble_hs_hci_util.c b/nimble/host/src/ble_hs_hci_util.c index e99dcbdff..996e0fc10 100644 --- a/nimble/host/src/ble_hs_hci_util.c +++ b/nimble/host/src/ble_hs_hci_util.c @@ -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, ¶ms_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, ¶ms_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), ¶ms_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, ¶ms_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, - ¶ms_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); } diff --git a/nimble/host/src/ble_hs_pvcy.c b/nimble/host/src/ble_hs_pvcy.c index e744b55b1..01556aa00 100644 --- a/nimble/host/src/ble_hs_pvcy.c +++ b/nimble/host/src/ble_hs_pvcy.c @@ -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); } diff --git a/nimble/host/src/ble_hs_startup.c b/nimble/host/src/ble_hs_startup.c index b21db7513..2ef890087 100644 --- a/nimble/host/src/ble_hs_startup.c +++ b/nimble/host/src/ble_hs_startup.c @@ -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 diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index 6c85d1ca2..8ce5c9fe4 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -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; } diff --git a/nimble/host/src/ble_sm_priv.h b/nimble/host/src/ble_sm_priv.h index 1c3e080b2..86775506c 100644 --- a/nimble/host/src/ble_sm_priv.h +++ b/nimble/host/src/ble_sm_priv.h @@ -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); diff --git a/nimble/host/test/src/ble_gap_test.c b/nimble/host/test/src/ble_gap_test.c index 4902821ad..3962bacc2 100644 --- a/nimble/host/test/src/ble_gap_test.c +++ b/nimble/host/test/src/ble_gap_test.c @@ -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 == diff --git a/nimble/host/test/src/ble_gatt_conn_test.c b/nimble/host/test/src/ble_gatt_conn_test.c index 46ef9692a..8d95f7433 100644 --- a/nimble/host/test/src/ble_gatt_conn_test.c +++ b/nimble/host/test/src/ble_gatt_conn_test.c @@ -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) { diff --git a/nimble/host/test/src/ble_hs_adv_test.c b/nimble/host/test/src/ble_hs_adv_test.c index 6ecb43699..b267dc2a0 100644 --- a/nimble/host/test/src/ble_hs_adv_test.c +++ b/nimble/host/test/src/ble_hs_adv_test.c @@ -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) { diff --git a/nimble/host/test/src/ble_hs_conn_test.c b/nimble/host/test/src/ble_hs_conn_test.c index 46533d626..04137d4f5 100644 --- a/nimble/host/test/src/ble_hs_conn_test.c +++ b/nimble/host/test/src/ble_hs_conn_test.c @@ -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; diff --git a/nimble/host/test/src/ble_hs_hci_test.c b/nimble/host/test/src/ble_hs_hci_test.c index fee025318..5f72742c6 100644 --- a/nimble/host/test/src/ble_hs_hci_test.c +++ b/nimble/host/test/src/ble_hs_hci_test.c @@ -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); diff --git a/nimble/host/test/src/ble_hs_test_util.c b/nimble/host/test/src/ble_hs_test_util.c index af30b8fa6..d82648e3a 100644 --- a/nimble/host/test/src/ble_hs_test_util.c +++ b/nimble/host/test/src/ble_hs_test_util.c @@ -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(); diff --git a/nimble/host/test/src/ble_hs_test_util.h b/nimble/host/test/src/ble_hs_test_util.h index cb5d14809..411443cfd 100644 --- a/nimble/host/test/src/ble_hs_test_util.h +++ b/nimble/host/test/src/ble_hs_test_util.h @@ -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; diff --git a/nimble/host/test/src/ble_hs_test_util_hci.c b/nimble/host/test/src/ble_hs_test_util_hci.c index b9b36d102..31c7967ab 100644 --- a/nimble/host/test/src/ble_hs_test_util_hci.c +++ b/nimble/host/test/src/ble_hs_test_util_hci.c @@ -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; diff --git a/nimble/host/test/src/ble_hs_test_util_hci.h b/nimble/host/test/src/ble_hs_test_util_hci.h index 500f8ed68..1edd99b2e 100644 --- a/nimble/host/test/src/ble_hs_test_util_hci.h +++ b/nimble/host/test/src/ble_hs_test_util_hci.h @@ -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 */ diff --git a/nimble/host/test/src/ble_l2cap_test.c b/nimble/host/test/src/ble_l2cap_test.c index 49769155b..1f0e40f1b 100644 --- a/nimble/host/test/src/ble_l2cap_test.c +++ b/nimble/host/test/src/ble_l2cap_test.c @@ -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) diff --git a/nimble/host/test/src/ble_os_test.c b/nimble/host/test/src/ble_os_test.c index 18a1a07f2..fa57571b4 100644 --- a/nimble/host/test/src/ble_os_test.c +++ b/nimble/host/test/src/ble_os_test.c @@ -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)); diff --git a/nimble/host/test/src/ble_sm_test.c b/nimble/host/test/src/ble_sm_test.c index 5dc6b7f12..be4285fdc 100644 --- a/nimble/host/test/src/ble_sm_test.c +++ b/nimble/host/test/src/ble_sm_test.c @@ -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); diff --git a/nimble/host/test/src/ble_sm_test_util.c b/nimble/host/test/src/ble_sm_test_util.c index 177e3495c..6170371f5 100644 --- a/nimble/host/test/src/ble_sm_test_util.c +++ b/nimble/host/test/src/ble_sm_test_util.c @@ -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); } diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 1b049c88b..b2a4dc958 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -26,16 +26,22 @@ extern "C" { #endif -/* - * HCI Command Header - * - * Comprises the following fields - * -> Opcode group field & Opcode command field (2) - * -> Parameter Length (1) - * Length of all the parameters (does not include any part of the hci - * command header - */ -#define BLE_HCI_CMD_HDR_LEN (3) +#define BLE_HCI_MAX_DATA_LEN (MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE) - \ + sizeof(struct ble_hci_ev)) + +/* Generic command header */ +struct ble_hci_cmd { + uint16_t opcode; + uint8_t length; + uint8_t data[0]; +} __attribute__((packed)); + +/* Generic event header */ +struct ble_hci_ev { + uint8_t opcode; + uint8_t length; + uint8_t data[0]; +} __attribute__((packed)); #define BLE_HCI_OPCODE_NOP (0) @@ -64,173 +70,708 @@ extern "C" { /* List of OCF for Link Control commands (OGF=0x01) */ #define BLE_HCI_OCF_DISCONNECT_CMD (0x0006) +struct ble_hci_lc_disconnect_cp { + uint16_t conn_handle; + uint8_t reason; +} __attribute__((packed)); + #define BLE_HCI_OCF_RD_REM_VER_INFO (0x001D) +struct ble_hci_rd_rem_ver_info_cp { + uint16_t conn_handle; +} __attribute__((packed)); /* List of OCF for Controller and Baseband commands (OGF=0x03) */ #define BLE_HCI_OCF_CB_SET_EVENT_MASK (0x0001) +struct ble_hci_cb_set_event_mask_cp { + uint64_t event_mask; +} __attribute__((packed)); + #define BLE_HCI_OCF_CB_RESET (0x0003) + #define BLE_HCI_OCF_CB_READ_TX_PWR (0x002D) +struct ble_hci_cb_read_tx_pwr_cp { + uint16_t conn_handle; + uint8_t type; +} __attribute__((packed)); + +struct ble_hci_cb_read_tx_pwr_rp { + uint16_t conn_handle; + int8_t tx_level; +} __attribute__((packed)); + + #define BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC (0x0031) +struct ble_hci_cb_ctlr_to_host_fc_cp { + uint8_t enable; +} __attribute__((packed)); + #define BLE_HCI_OCF_CB_HOST_BUF_SIZE (0x0033) +struct ble_hci_cb_host_buf_size_cp { + uint16_t acl_data_len; + uint16_t sco_data_len; + uint16_t acl_num; + uint16_t sco_num; +} __attribute__((packed)); + #define BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS (0x0035) +struct ble_hci_handle_count { + uint16_t handle; + uint16_t count; +} __packed; +struct ble_hci_cb_host_num_comp_pkts_cp { + uint8_t handles; + struct ble_hci_handle_count h[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_CB_SET_EVENT_MASK2 (0x0063) +struct ble_hci_cb_set_event_mask2_cp { + uint64_t event_mask2; +} __attribute__((packed)); + #define BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO (0x007B) +struct ble_hci_cb_rd_auth_pyld_tmo_cp { + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_cb_rd_auth_pyld_tmo_rp { + uint16_t conn_handle; + uint16_t tmo; +} __attribute__((packed)); + #define BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO (0x007C) +struct ble_hci_cb_wr_auth_pyld_tmo_cp { + uint16_t conn_handle; + uint16_t tmo; +} __attribute__((packed)); +struct ble_hci_cb_wr_auth_pyld_tmo_rp { + uint16_t conn_handle; +} __attribute__((packed)); /* List of OCF for Info Param commands (OGF=0x04) */ #define BLE_HCI_OCF_IP_RD_LOCAL_VER (0x0001) +struct ble_hci_ip_rd_local_ver_rp { + uint8_t hci_ver; + uint16_t hci_rev; + uint8_t lmp_ver; + uint16_t manufacturer; + uint16_t lmp_subver; +} __attribute__((packed)); + #define BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD (0x0002) +struct ble_hci_ip_rd_loc_supp_cmd_rp { + uint8_t commands[64]; +} __attribute__((packed)); + #define BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT (0x0003) +struct ble_hci_ip_rd_loc_supp_feat_rp { + uint64_t features; +} __attribute__((packed)); + #define BLE_HCI_OCF_IP_RD_BUF_SIZE (0x0005) +struct ble_hci_ip_rd_buf_size_rp { + uint16_t acl_data_len; + uint8_t sco_data_len; + uint16_t acl_num; + uint16_t sco_num; +} __attribute__((packed)); + #define BLE_HCI_OCF_IP_RD_BD_ADDR (0x0009) +struct ble_hci_ip_rd_bd_addr_rp { + uint8_t addr[6]; +} __attribute__((packed)); /* List of OCF for Status parameters commands (OGF = 0x05) */ #define BLE_HCI_OCF_RD_RSSI (0x0005) +struct ble_hci_rd_rssi_cp { + uint16_t handle; +} __attribute__((packed)); +struct ble_hci_rd_rssi_rp { + uint16_t handle; + int8_t rssi; +} __attribute__((packed)); /* List of OCF for LE commands (OGF = 0x08) */ #define BLE_HCI_OCF_LE_SET_EVENT_MASK (0x0001) +struct ble_hci_le_set_event_mask_cp { + uint64_t event_mask; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_BUF_SIZE (0x0002) +struct ble_hci_le_rd_buf_size_rp { + uint16_t data_len; + uint8_t data_packets; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT (0x0003) +struct ble_hci_le_rd_loc_supp_feat_rp { + uint64_t features; +} __attribute__((packed)); + /* NOTE: 0x0004 is intentionally left undefined */ #define BLE_HCI_OCF_LE_SET_RAND_ADDR (0x0005) +struct ble_hci_le_set_rand_addr_cp { + uint8_t addr[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_ADV_PARAMS (0x0006) +struct ble_hci_le_set_adv_params_cp { + uint16_t min_interval; + uint16_t max_interval; + uint8_t type; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t chan_map; + uint8_t filter_policy; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR (0x0007) +struct ble_hci_le_rd_adv_chan_txpwr_rp { + int8_t power_level; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_ADV_DATA (0x0008) +#define BLE_HCI_MAX_ADV_DATA_LEN (31) +struct ble_hci_le_set_adv_data_cp { + uint8_t adv_data_len; + uint8_t adv_data[BLE_HCI_MAX_ADV_DATA_LEN]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA (0x0009) +#define BLE_HCI_MAX_SCAN_RSP_DATA_LEN (31) +struct ble_hci_le_set_scan_rsp_data_cp { + uint8_t scan_rsp_len; + uint8_t scan_rsp[BLE_HCI_MAX_SCAN_RSP_DATA_LEN]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_ADV_ENABLE (0x000A) +struct ble_hci_le_set_adv_enable_cp { + uint8_t enable; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_SCAN_PARAMS (0x000B) +struct ble_hci_le_set_scan_params_cp { + uint8_t scan_type; + uint16_t scan_itvl; + uint16_t scan_window; + uint8_t own_addr_type; + uint8_t filter_policy; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_SCAN_ENABLE (0x000C) +struct ble_hci_le_set_scan_enable_cp { + uint8_t enable; + uint8_t filter_duplicates; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CREATE_CONN (0x000D) +struct ble_hci_le_create_conn_cp { + uint16_t scan_itvl; + uint16_t scan_window; + uint8_t filter_policy; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t own_addr_type; + uint16_t min_conn_itvl; + uint16_t max_conn_itvl; + uint16_t conn_latency; + uint16_t tmo; + uint16_t min_ce; + uint16_t max_ce; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CREATE_CONN_CANCEL (0x000E) + #define BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE (0x000F) +struct ble_hci_le_rd_white_list_rp { + uint8_t size; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CLEAR_WHITE_LIST (0x0010) + #define BLE_HCI_OCF_LE_ADD_WHITE_LIST (0x0011) +struct ble_hci_le_add_whte_list_cp { + uint8_t addr_type; + uint8_t addr[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RMV_WHITE_LIST (0x0012) +struct ble_hci_le_rmv_white_list_cp { + uint8_t addr_type; + uint8_t addr[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CONN_UPDATE (0x0013) +struct ble_hci_le_conn_update_cp { + uint16_t conn_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; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS (0x0014) +struct ble_hci_le_set_host_chan_class_cp { + uint8_t chan_map[5]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_CHAN_MAP (0x0015) +struct ble_hci_le_rd_chan_map_cp { + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_le_rd_chan_map_rp { + uint16_t conn_handle; + uint8_t chan_map[5]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_REM_FEAT (0x0016) +struct ble_hci_le_rd_rem_feat_cp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_ENCRYPT (0x0017) +struct ble_hci_le_encrypt_cp { + uint8_t key[16]; + uint8_t data[16]; +} __attribute__((packed)); +struct ble_hci_le_encrypt_rp { + uint8_t data[16]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RAND (0x0018) +struct ble_hci_le_rand_rp { + uint64_t random_number; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_START_ENCRYPT (0x0019) +struct ble_hci_le_start_encrypt_cp { + uint16_t conn_handle; + uint64_t rand; + uint16_t div; + uint8_t ltk[16]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY (0x001A) +struct ble_hci_le_lt_key_req_reply_cp { + uint16_t conn_handle; + uint8_t ltk[16]; +} __attribute__((packed)); +struct ble_hci_le_lt_key_req_reply_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY (0x001B) +struct ble_hci_le_lt_key_req_neg_reply_cp { + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_le_lt_key_req_neg_reply_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_SUPP_STATES (0x001C) +struct ble_hci_le_rd_supp_states_rp { + uint64_t states; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RX_TEST (0x001D) +struct ble_hci_le_rx_test_cp { + uint8_t rx_chan; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_TX_TEST (0x001E) +struct ble_hci_le_tx_test_cp { + uint8_t tx_chan; + uint8_t test_data_len; + uint8_t payload; +} __attribute__((packed)); +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) +struct ble_hci_le_tx_test_ext_cp { + uint8_t tx_chan; + uint8_t test_data_len; + uint8_t payload; + uint16_t interval; + uint16_t pkt_count; +} __attribute__((packed)); +#endif + #define BLE_HCI_OCF_LE_TEST_END (0x001F) +struct ble_hci_le_test_end_rp { + uint16_t num_packets; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_REM_CONN_PARAM_RR (0x0020) +struct ble_hci_le_rem_conn_param_rr_cp { + uint16_t conn_handle; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce; + uint16_t max_ce; +} __attribute__((packed)); +struct ble_hci_le_rem_conn_param_rr_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR (0x0021) +struct ble_hci_le_rem_conn_params_nrr_cp { + uint16_t conn_handle; + uint8_t reason; +} __attribute__((packed)); +struct ble_hci_le_rem_conn_params_nrr_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_DATA_LEN (0x0022) +struct ble_hci_le_set_data_len_cp { + uint16_t conn_handle; + uint16_t tx_octets; + uint16_t tx_time; +} __attribute__((packed)); +struct ble_hci_le_set_data_len_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN (0x0023) +struct ble_hci_le_rd_sugg_def_data_len_rp { + uint16_t max_tx_octets; + uint16_t max_tx_time; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN (0x0024) +struct ble_hci_le_wr_sugg_def_data_len_cp { + uint16_t max_tx_octets; + uint16_t max_tx_time; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_P256_PUBKEY (0x0025) + #define BLE_HCI_OCF_LE_GEN_DHKEY (0x0026) +struct ble_hci_le_gen_dhkey_cp { + uint8_t pkey[64]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_ADD_RESOLV_LIST (0x0027) +struct ble_hci_le_add_resolv_list_cp { + uint8_t peer_addr_type; + uint8_t peer_id_addr[6]; + uint8_t peer_irk[16]; + uint8_t local_irk[16]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RMV_RESOLV_LIST (0x0028) +struct ble_hci_le_rmv_resolve_list_cp { + uint8_t peer_addr_type; + uint8_t peer_id_addr[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CLR_RESOLV_LIST (0x0029) + #define BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE (0x002A) +struct ble_hci_le_rd_resolv_list_size_rp { + uint8_t size; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR (0x002B) +struct ble_hci_le_rd_peer_recolv_addr_cp { + uint8_t peer_addr_type; + uint8_t peer_id_addr[6]; +} __attribute__((packed)); +struct ble_hci_le_rd_peer_recolv_addr_rp { + uint8_t rpa[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR (0x002C) +struct ble_hci_le_rd_local_recolv_addr_cp { + uint8_t peer_addr_type; + uint8_t peer_id_addr[6]; +} __attribute__((packed)); +struct ble_hci_le_rd_local_recolv_addr_rp { + uint8_t rpa[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_ADDR_RES_EN (0x002D) +struct ble_hci_le_set_addr_res_en_cp { + uint8_t enable; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_RPA_TMO (0x002E) +struct ble_hci_le_set_rpa_tmo_cp { + uint16_t rpa_timeout; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_MAX_DATA_LEN (0x002F) +struct ble_hci_le_rd_max_data_len_rp { + uint16_t max_tx_octests; + uint16_t max_tx_time; + uint16_t max_rx_octests; + uint16_t max_rx_time; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_PHY (0x0030) +struct ble_hci_le_rd_phy_cp { + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_le_rd_phy_rp { + uint16_t conn_handle; + uint8_t tx_phy; + uint8_t rx_phy; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_DEFAULT_PHY (0x0031) +struct ble_hci_le_set_default_phy_cp { + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_PHY (0x0032) -#define BLE_HCI_OCF_LE_ENH_RX_TEST (0x0033) -#define BLE_HCI_OCF_LE_ENH_TX_TEST (0x0034) +struct ble_hci_le_set_phy_cp { + uint16_t conn_handle; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + uint16_t phy_options; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_RX_TEST_V2 (0x0033) +struct ble_hci_le_rx_test_v2_cp { + uint8_t rx_chan; + uint8_t phy; + uint8_t index; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_TX_TEST_V2 (0x0034) +struct ble_hci_le_tx_test_v2_cp { + uint8_t tx_chan; + uint8_t test_data_len; + uint8_t payload; + uint8_t phy; +} __attribute__((packed)); +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) +struct ble_hci_le_tx_test_v2_ext_cp { + uint8_t tx_chan; + uint8_t test_data_len; + uint8_t payload; + uint8_t phy; + uint16_t interval; + uint16_t pkt_count; +} __attribute__((packed)); +#endif + #define BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR (0x0035) +struct ble_hci_le_set_adv_set_rnd_addr_cp { + uint8_t adv_handle; + uint8_t addr[6]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM (0x0036) +struct ble_hci_le_set_ext_adv_params_cp { + uint8_t adv_handle; + uint16_t props; + uint8_t pri_itvl_min[3]; + uint8_t pri_itvl_max[3]; + uint8_t pri_chan_map; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t filter_policy; + int8_t tx_power; + uint8_t pri_phy; + uint8_t sec_max_skip; + uint8_t sec_phy; + uint8_t sid; + uint8_t scan_req_notif; +} __attribute__((packed)); +struct ble_hci_le_set_ext_adv_params_rp { + int8_t tx_power; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_EXT_ADV_DATA (0x0037) +struct ble_hci_le_set_ext_adv_data_cp { + uint8_t adv_handle; + uint8_t operation; + uint8_t fragment_pref; + uint8_t adv_data_len; + uint8_t adv_data[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA (0x0038) +struct ble_hci_le_set_ext_scan_rsp_data_cp { + uint8_t adv_handle; + uint8_t operation; + uint8_t fragment_pref; + uint8_t scan_rsp_len; + uint8_t scan_rsp[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE (0x0039) +struct adv_set { + uint8_t adv_handle; + uint16_t duration; + uint8_t max_events; +} __attribute__((packed)); +struct ble_hci_le_set_ext_adv_enable_cp { + uint8_t enable; + uint8_t num_sets; + struct adv_set sets[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN (0x003A) +struct ble_hci_le_rd_max_adv_data_len_rp { + uint16_t max_adv_data_len; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS (0x003B) +struct ble_hci_le_rd_num_of_adv_sets_rp { + uint8_t num_sets; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_REMOVE_ADV_SET (0x003C) +struct ble_hci_le_remove_adv_set_cp { + uint8_t adv_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CLEAR_ADV_SETS (0x003D) + #define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS (0x003E) +struct ble_hci_le_set_periodic_adv_params_cp { + uint8_t adv_handle; + uint16_t min_itvl; + uint16_t max_itvl; + uint16_t props; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA (0x003F) +struct ble_hci_le_set_periodic_adv_data_cp { + uint8_t adv_handle; + uint8_t operation; + uint8_t adv_data_len; + uint8_t adv_data[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE (0x0040) +struct ble_hci_le_set_periodic_adv_enable_cp { + uint8_t enable; + uint8_t adv_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM (0x0041) +struct scan_params { + uint8_t type; + uint16_t itvl; + uint16_t window; +} __attribute__((packed)); +struct ble_hci_le_set_ext_scan_params_cp { + uint8_t own_addr_type; + uint8_t filter_policy; + uint8_t phys; + struct scan_params scans[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE (0x0042) +struct ble_hci_le_set_ext_scan_enable_cp { + uint8_t enable; + uint8_t filter_dup; + uint16_t duration; + uint16_t period; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_EXT_CREATE_CONN (0x0043) +struct conn_params { + uint16_t scan_itvl; + uint16_t scan_window; + uint16_t conn_min_itvl; + uint16_t conn_max_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce; + uint16_t max_ce; +} __attribute__((packed)); +struct ble_hci_le_ext_create_conn_cp { + uint8_t filter_policy; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t init_phy_mask; + struct conn_params conn_params[0]; +} __attribute__((packed)); + +#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER 0x01 + #define BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC (0x0044) +struct ble_hci_le_periodic_adv_create_sync_cp { + uint8_t options; + uint8_t sid; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint16_t skip; + uint16_t sync_timeout; + uint8_t sync_cte_type; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL (0x0045) + #define BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC (0x0046) +struct ble_hci_le_periodic_adv_term_sync_cp { + uint16_t sync_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST (0x0047) +struct ble_hci_le_add_dev_to_periodic_adv_list_cp { + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t sid; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST (0x0048) +struct ble_hci_le_rem_dev_from_periodic_adv_list_cp { + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t sid; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST (0x0049) + #define BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE (0x004A) +struct ble_hci_le_rd_periodic_adv_list_size_rp { + uint8_t list_size; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_TRANSMIT_POWER (0x004B) +struct ble_hci_le_rd_transmit_power_rp { + int8_t min_tx_power; + int8_t max_tx_power; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION (0x004C) +struct ble_hci_le_rd_rf_path_compensation_rp { + int16_t tx_path_compensation; + int16_t rx_path_compensation; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION (0x004D) +struct ble_hci_le_wr_rf_path_compensation_cp { + int16_t tx_path_compensation; + int16_t rx_path_compensation; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_PRIVACY_MODE (0x004E) +struct ble_hci_le_set_privacy_mode_cp { + uint8_t peer_id_addr_type; + uint8_t peer_id_addr[6]; + uint8_t mode; +} __attribute__((packed)); /* Command Specific Definitions */ -#define BLE_HCI_VARIABLE_LEN (0xFF) - -/* --- Disconnect command (OGF 0x01, OCF 0x0006) --- */ -#define BLE_HCI_DISCONNECT_CMD_LEN (3) - -/* --- Set event mask (OGF 0x03, OCF 0x0001 --- */ -#define BLE_HCI_SET_EVENT_MASK_LEN (8) - /* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */ -#define BLE_HCI_CTLR_TO_HOST_FC_LEN (1) - #define BLE_HCI_CTLR_TO_HOST_FC_OFF (0) #define BLE_HCI_CTLR_TO_HOST_FC_ACL (1) #define BLE_HCI_CTLR_TO_HOST_FC_SYNC (2) #define BLE_HCI_CTLR_TO_HOST_FC_BOTH (3) -/* --- Host buffer size (OGF 0x03, OCF 0x0033) --- */ -#define BLE_HCI_HOST_BUF_SIZE_LEN (7) - -/* --- Host number of completed packets (OGF 0x03, OCF 0x0035) --- */ -#define BLE_HCI_HOST_NUM_COMP_PKTS_HDR_LEN (1) -#define BLE_HCI_HOST_NUM_COMP_PKTS_ENT_LEN (4) - -/* --- Read BD_ADDR (OGF 0x04, OCF 0x0009 --- */ -#define BLE_HCI_IP_RD_BD_ADDR_ACK_PARAM_LEN (6) - -/* --- Read buffer size (OGF 0x04, OCF 0x0005) --- */ -#define BLE_HCI_IP_RD_BUF_SIZE_LEN (0) -#define BLE_HCI_IP_RD_BUF_SIZE_RSPLEN (7) /* No status byte. */ - -/* --- Read/Write authenticated payload timeout (ocf 0x007B/0x007C) */ -#define BLE_HCI_RD_AUTH_PYLD_TMO_LEN (4) -#define BLE_HCI_WR_AUTH_PYLD_TMO_LEN (2) - -/* --- Read local version information (OGF 0x04, OCF 0x0001) --- */ -#define BLE_HCI_RD_LOC_VER_INFO_RSPLEN (8) /* No status byte. */ - -/* --- Read local supported command (OGF 0x04, OCF 0x0002) --- */ -#define BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN (64) /* No status byte. */ - -/* --- Read local supported features (OGF 0x04, OCF 0x0003) --- */ -#define BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN (8) /* No status byte. */ - -/* --- Read RSSI (OGF 0x05, OCF 0x0005) --- */ -#define BLE_HCI_READ_RSSI_LEN (2) -#define BLE_HCI_READ_RSSI_ACK_PARAM_LEN (3) /* No status byte. */ - -/* --- LE set event mask (OCF 0x0001) --- */ -#define BLE_HCI_SET_LE_EVENT_MASK_LEN (8) - -/* --- LE read buffer size (OCF 0x0002) --- */ -#define BLE_HCI_RD_BUF_SIZE_LEN (0) -#define BLE_HCI_RD_BUF_SIZE_RSPLEN (3) /* No status byte. */ - -/* --- LE read local supported features (OCF 0x0003) --- */ -#define BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN (8) /* No status byte. */ - -/* --- LE set random address (OCF 0x0005) */ -#define BLE_HCI_SET_RAND_ADDR_LEN (6) - /* --- LE set advertising parameters (OCF 0x0006) */ -#define BLE_HCI_SET_ADV_PARAM_LEN (15) - /* Advertising types */ #define BLE_HCI_ADV_TYPE_ADV_IND (0) #define BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) @@ -263,23 +804,10 @@ extern "C" { #define BLE_HCI_ADV_PEER_ADDR_MAX (1) /* --- LE advertising channel tx power (OCF 0x0007) */ -#define BLE_HCI_ADV_CHAN_TXPWR_ACK_PARAM_LEN (2) /* Includes status byte. */ #define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) #define BLE_HCI_ADV_CHAN_TXPWR_MAX (10) -/* --- LE set advertising data (OCF 0x0008) */ -#define BLE_HCI_MAX_ADV_DATA_LEN (31) -#define BLE_HCI_SET_ADV_DATA_LEN (32) - -/* --- LE set scan response data (OCF 0x0009) */ -#define BLE_HCI_MAX_SCAN_RSP_DATA_LEN (31) -#define BLE_HCI_SET_SCAN_RSP_DATA_LEN (32) - -/* --- LE set advertising enable (OCF 0x000a) */ -#define BLE_HCI_SET_ADV_ENABLE_LEN (1) - /* --- LE set scan enable (OCF 0x000c) */ -#define BLE_HCI_SET_SCAN_ENABLE_LEN (2) /* Connect peer address type */ #define BLE_HCI_CONN_PEER_ADDR_PUBLIC (0) @@ -316,7 +844,6 @@ extern "C" { #define BLE_HCI_ADV_CHANMASK_DEF (0x7) /* all channels */ /* Set scan parameters */ -#define BLE_HCI_SET_SCAN_PARAM_LEN (7) #define BLE_HCI_SCAN_TYPE_PASSIVE (0) #define BLE_HCI_SCAN_TYPE_ACTIVE (1) @@ -378,98 +905,19 @@ extern "C" { #define BLE_HCI_CONN_PEER_ADDR_RAND_ID (3) #define BLE_HCI_CONN_PEER_ADDR_MAX (3) -/* --- LE connection update (OCF 0x0013) */ -#define BLE_HCI_CONN_UPDATE_LEN (14) - -/* --- LE set host channel classification command (OCF 0x0014) */ -#define BLE_HCI_SET_HOST_CHAN_CLASS_LEN (5) - -/* --- LE read channel map command (OCF 0x0015) */ -#define BLE_HCI_RD_CHANMAP_LEN (2) -#define BLE_HCI_RD_CHANMAP_RSP_LEN (7) - -/* --- LE read remote features (OCF 0x0016) */ -#define BLE_HCI_CONN_RD_REM_FEAT_LEN (2) - -/* --- LE encrypt (OCF 0x0017) */ -#define BLE_HCI_LE_ENCRYPT_LEN (32) - -/* --- LE rand (OCF 0x0018) */ -#define BLE_HCI_LE_RAND_LEN (8) - -/* --- LE start encryption (OCF 0x0019) */ -#define BLE_HCI_LE_START_ENCRYPT_LEN (28) - -/* --- LE long term key request reply command (OCF 0x001a) */ -#define BLE_HCI_LT_KEY_REQ_REPLY_LEN (18) -#define BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN (2) /* No status byte. */ - -/* --- LE long term key request negative reply command (OCF 0x001b) */ -#define BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN (2) -#define BLE_HCI_LT_KEY_REQ_NEG_REPLY_ACK_PARAM_LEN (2) - -/* --- LE read supported states (OCF 0x001C) --- */ -#define BLE_HCI_RD_SUPP_STATES_RSPLEN (8) - -/* --- LE receiver test command (OCF 0x001D) --- */ -#define BLE_HCI_RX_TEST_LEN (1) - -/* --- LE transitter test command (OCF 0x001E) --- */ -#define BLE_HCI_TX_TEST_LEN (3) - -/* --- LE remote connection parameter request reply (OCF 0x0020) */ -#define BLE_HCI_CONN_PARAM_REPLY_LEN (14) - -/* --- LE remote connection parameter request negative reply (OCF 0x0021) */ -#define BLE_HCI_CONN_PARAM_NEG_REPLY_LEN (3) /* --- LE set data length (OCF 0x0022) */ -#define BLE_HCI_SET_DATALEN_LEN (6) -#define BLE_HCI_SET_DATALEN_ACK_PARAM_LEN (2) /* No status byte. */ #define BLE_HCI_SET_DATALEN_TX_OCTETS_MIN (0x001b) #define BLE_HCI_SET_DATALEN_TX_OCTETS_MAX (0x00fb) #define BLE_HCI_SET_DATALEN_TX_TIME_MIN (0x0148) #define BLE_HCI_SET_DATALEN_TX_TIME_MAX (0x4290) -/* --- LE read suggested default data length (OCF 0x0023) */ -#define BLE_HCI_RD_SUGG_DATALEN_RSPLEN (4) - -/* --- LE write suggested default data length (OCF 0x0024) */ -#define BLE_HCI_WR_SUGG_DATALEN_LEN (4) - -/* --- LE generate DHKEY command (OCF 0x0026) */ -#define BLE_HCI_GEN_DHKEY_LEN (64) - -/* --- LE add device to resolving list (OCF 0x0027) */ -#define BLE_HCI_ADD_TO_RESOLV_LIST_LEN (39) - -/* --- LE add device to resolving list (OCF 0x0028) */ -#define BLE_HCI_RMV_FROM_RESOLV_LIST_LEN (7) - -/* --- LE read peer resolvable address (OCF 0x002B) */ -#define BLE_HCI_RD_PEER_RESOLV_ADDR_LEN (7) - -/* --- LE read peer resolvable address (OCF 0x002C) */ -#define BLE_HCI_RD_LOC_RESOLV_ADDR_LEN (7) - -/* --- LE set address resolution enable (OCF 0x002D) */ -#define BLE_HCI_SET_ADDR_RESOL_ENA_LEN (1) - -/* --- LE set resolvable private address timeout (OCF 0x002E) */ -#define BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN (2) - -/* --- LE read maximum data length (OCF 0x002F) */ -#define BLE_HCI_RD_MAX_DATALEN_RSPLEN (8) - /* --- LE read maximum default PHY (OCF 0x0030) */ -#define BLE_HCI_LE_RD_PHY_LEN (2) -#define BLE_HCI_LE_RD_PHY_RSPLEN (4) #define BLE_HCI_LE_PHY_1M (1) #define BLE_HCI_LE_PHY_2M (2) #define BLE_HCI_LE_PHY_CODED (3) /* --- LE set default PHY (OCF 0x0031) */ -#define BLE_HCI_LE_SET_DEFAULT_PHY_LEN (3) #define BLE_HCI_LE_PHY_NO_TX_PREF_MASK (0x01) #define BLE_HCI_LE_PHY_NO_RX_PREF_MASK (0x02) #define BLE_HCI_LE_PHY_1M_PREF_MASK (0x01) @@ -481,27 +929,20 @@ extern "C" { BLE_HCI_LE_PHY_CODED_PREF_MASK) /* --- LE set PHY (OCF 0x0032) */ -#define BLE_HCI_LE_SET_PHY_LEN (7) #define BLE_HCI_LE_PHY_CODED_ANY (0x0000) #define BLE_HCI_LE_PHY_CODED_S2_PREF (0x0001) #define BLE_HCI_LE_PHY_CODED_S8_PREF (0x0002) /* --- LE enhanced receiver test (OCF 0x0033) */ -#define BLE_HCI_LE_ENH_RX_TEST_LEN (3) #define BLE_HCI_LE_PHY_1M (1) #define BLE_HCI_LE_PHY_2M (2) #define BLE_HCI_LE_PHY_CODED (3) /* --- LE enhanced transmitter test (OCF 0x0034) */ -#define BLE_HCI_LE_ENH_TX_TEST_LEN (4) #define BLE_HCI_LE_PHY_CODED_S8 (3) #define BLE_HCI_LE_PHY_CODED_S2 (4) -/* --- LE set advertising set random address (OCF 0x0035) */ -#define BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN (7) - /* --- LE set extended advertising parameters (OCF 0x0036) */ -#define BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN (25) #define BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE (0x0001) #define BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE (0x0002) #define BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED (0x0004) @@ -519,9 +960,7 @@ extern "C" { /* --- LE set extended advertising data (OCF 0x0037) */ #define BLE_HCI_MAX_EXT_ADV_DATA_LEN (251) -#define BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN (4) -#define BLE_HCI_LE_SET_EXT_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN #define BLE_HCI_LE_SET_DATA_OPER_INT (0) #define BLE_HCI_LE_SET_DATA_OPER_FIRST (1) #define BLE_HCI_LE_SET_DATA_OPER_LAST (2) @@ -530,69 +969,20 @@ extern "C" { /* --- LE set extended scan response data (OCF 0x0038) */ #define BLE_HCI_MAX_EXT_SCAN_RSP_DATA_LEN (251) -#define BLE_HCI_SET_EXT_SCAN_RSP_DATA_HDR_LEN (4) - -#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_LEN BLE_HCI_VARIABLE_LEN - - -/* --- LE set extended advertising enable (OCF 0x0039) */ -#define BLE_HCI_LE_SET_EXT_ADV_ENABLE_LEN BLE_HCI_VARIABLE_LEN - -/* --- LE remove advertising set (OCF 0x003C) */ -#define BLE_HCI_LE_REMOVE_ADV_SET_LEN (1) - -/* --- LE read maximum advertising data length (OCF 0x003A) */ -#define BLE_HCI_RD_MAX_ADV_DATA_LEN (2) - -/* --- LE read number of supported advertising sets (OCF 0x003B) */ -#define BLE_HCI_RD_NR_SUP_ADV_SETS (1) /* --- LE set periodic advertising parameters (OCF 0x003E) */ -#define BLE_HCI_LE_SET_PERIODIC_ADV_PARAMS_LEN (7) #define BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR (0x0040) #define BLE_HCI_LE_SET_PERIODIC_ADV_PROP_MASK (0x0040) /* --- LE set periodic advertising data (OCF 0x003F) */ -#define BLE_HCI_LE_SET_PERIODIC_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN #define BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN (252) -#define BLE_HCI_SET_PERIODIC_ADV_DATA_HDR_LEN (3) - -/* --- LE periodic advertising enable (OCF 0x0040) */ -#define BLE_HCI_LE_SET_PERIODIC_ADV_ENABLE_LEN (2) - -/* --- LE set extended scan parameters (OCF 0x0041) */ -#define BLE_HCI_LE_SET_EXT_SCAN_PARAM_LEN BLE_HCI_VARIABLE_LEN -#define BLE_HCI_LE_EXT_SCAN_BASE_LEN (3) -#define BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN (5) - -/* --- LE set extended scan enable (OCF 0x0042) */ -#define BLE_HCI_LE_SET_EXT_SCAN_ENABLE_LEN (6) - -/* --- LE extended create connection (OCF 0x0043) */ -#define BLE_HCI_LE_EXT_CREATE_CONN_LEN BLE_HCI_VARIABLE_LEN -#define BLE_HCI_LE_EXT_CREATE_CONN_BASE_LEN (10) - -/* --- LE periodic advertising create sync (OCF 0x0044) */ -#define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_LEN (14) - -/* --- LE periodic advertising terminate (OCF 0x0046) */ -#define BLE_HCI_LE_PERIODIC_ADV_TERM_SYNC_LEN (2) - -/* --- LE add device to periodic advertising list (OCF 0x0047) */ -#define BLE_HCI_LE_ADD_DEV_TO_PERIODIC_ADV_LIST_LEN (8) /* --- LE remove device from periodic advertising list (OCF 0x0048) */ -#define BLE_HCI_LE_REM_DEV_FROM_PERIODIC_ADV_LIST_LEN (8) - #define BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE 0x00 #define BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE 0x01 #define BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED 0x02 -/* --- LE write RF path (OCF 0x004D) */ -#define BLE_HCI_LE_WR_RF_PATH_COMPENSATION_LEN (4) - /* --- LE set privacy mode (OCF 0x004E) */ -#define BLE_HCI_LE_SET_PRIVACY_MODE_LEN (8) #define BLE_HCI_PRIVACY_NETWORK (0) #define BLE_HCI_PRIVACY_DEVICE (1) @@ -602,25 +992,83 @@ extern "C" { #define BLE_HCI_EVCODE_CONN_DONE (0x03) #define BLE_HCI_EVCODE_CONN_REQUEST (0x04) #define BLE_HCI_EVCODE_DISCONN_CMP (0x05) +struct ble_hci_ev_disconn_cmp { + uint8_t status; + uint16_t conn_handle; + uint8_t reason; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_AUTH_CMP (0x06) #define BLE_HCI_EVCODE_REM_NAME_REQ_CMP (0x07) + #define BLE_HCI_EVCODE_ENCRYPT_CHG (0x08) +struct ble_hci_ev_enrypt_chg { + uint8_t status; + uint16_t connection_handle; + uint8_t enabled; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_CHG_LINK_KEY_CMP (0x09) #define BLE_HCI_EVCODE_MASTER_LINK_KEY_CMP (0x0A) #define BLE_HCI_EVCODE_RD_REM_SUPP_FEAT_CMP (0x0B) #define BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP (0x0C) +struct ble_hci_ev_rd_rem_ver_info_cmp { + uint8_t status; + uint16_t conn_handle; + uint8_t version; + uint16_t manufacturer; + uint16_t subversion; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_QOS_SETUP_CMP (0x0D) + #define BLE_HCI_EVCODE_COMMAND_COMPLETE (0x0E) +struct ble_hci_ev_command_complete { + uint8_t num_packets; + uint16_t opcode; + uint8_t status; + uint8_t return_params[0]; +} __attribute__((packed)); +/* NOP is exception and has no return parameters */ +struct ble_hci_ev_command_complete_nop { + uint8_t num_packets; + uint16_t opcode; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_COMMAND_STATUS (0x0F) +struct ble_hci_ev_command_status { + uint8_t status; + uint8_t num_packets; + uint16_t opcode; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_HW_ERROR (0x10) +struct ble_hci_ev_hw_error { + uint8_t hw_code; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_NUM_COMP_PKTS (0x13) +struct comp_pkt { + uint16_t handle; + uint16_t packets; +} __attribute__((packed));; +struct ble_hci_ev_num_comp_pkts { + uint8_t count; + struct comp_pkt completed[0]; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_MODE_CHANGE (0x14) #define BLE_HCI_EVCODE_RETURN_LINK_KEYS (0x15) #define BLE_HCI_EVCODE_PIN_CODE_REQ (0x16) #define BLE_HCI_EVCODE_LINK_KEY_REQ (0x17) #define BLE_HCI_EVCODE_LINK_KEY_NOTIFY (0x18) #define BLE_HCI_EVCODE_LOOPBACK_CMD (0x19) + #define BLE_HCI_EVCODE_DATA_BUF_OVERFLOW (0x1A) +struct ble_hci_ev_data_buf_overflow { + uint8_t link_type; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_MAX_SLOTS_CHG (0x1B) #define BLE_HCI_EVCODE_READ_CLK_OFF_COMP (0x1C) #define BLE_HCI_EVCODE_CONN_PKT_TYPE_CHG (0x1D) @@ -635,7 +1083,13 @@ extern "C" { #define BLE_HCI_EVCODE_SYNCH_CONN_CHG (0x2D) #define BLE_HCI_EVCODE_SNIFF_SUBRATING (0x2E) #define BLE_HCI_EVCODE_EXT_INQ_RESULT (0x2F) + #define BLE_HCI_EVCODE_ENC_KEY_REFRESH (0x30) +struct ble_hci_ev_enc_key_refresh { + uint8_t status; + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_EVOCDE_IO_CAP_REQ (0x31) #define BLE_HCI_EVCODE_IO_CAP_RSP (0x32) #define BLE_HCI_EVCODE_USER_CONFIRM_REQ (0x33) @@ -648,7 +1102,13 @@ extern "C" { #define BLE_HCI_EVCODE_USER_PASSKEY_NOTIFY (0x3B) #define BLE_HCI_EVCODE_KEYPRESS_NOTIFY (0x3C) #define BLE_HCI_EVCODE_REM_HOST_SUPP_FEAT (0x3D) + #define BLE_HCI_EVCODE_LE_META (0x3E) +struct ble_hci_ev_le_meta { + uint8_t subevent; + uint8_t data[0]; +} __attribute__((packed)); + /* NOTE: 0x3F not defined */ #define BLE_HCI_EVCODE_PHYS_LINK_COMP (0x40) #define BLE_HCI_EVCODE_CHAN_SELECTED (0x41) @@ -673,63 +1133,230 @@ extern "C" { #define BLE_HCI_EVCODE_SLAVE_PAGE_RSP_TMO (0x54) #define BLE_HCI_EVCODE_SLAVE_BCAST_CHAN_MAP (0x55) #define BLE_HCI_EVCODE_INQ_RSP_NOTIFY (0x56) + #define BLE_HCI_EVCODE_AUTH_PYLD_TMO (0x57) +struct ble_hci_ev_auth_pyld_tmo { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_EVCODE_VENDOR_DEBUG (0xFF) +struct ble_hci_ev_vendor_debug { + uint8_t id; + uint8_t data[0]; +}__attribute__((packed)); /* LE sub-event codes */ #define BLE_HCI_LE_SUBEV_CONN_COMPLETE (0x01) +struct ble_hci_ev_le_subev_conn_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t role; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint16_t conn_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint8_t mca; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_ADV_RPT (0x02) +struct adv_report { + uint8_t type; + uint8_t addr_type; + uint8_t addr[6]; + uint8_t data_len; + uint8_t data[0]; +} __attribute__((packed)); +struct ble_hci_ev_le_subev_adv_rpt { + uint8_t subev_code; + uint8_t num_reports; + struct adv_report reports[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE (0x03) +struct ble_hci_ev_le_subev_conn_upd_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint16_t conn_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT (0x04) +struct ble_hci_ev_le_subev_rd_rem_used_feat { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t features[8]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_LT_KEY_REQ (0x05) +struct ble_hci_ev_le_subev_lt_key_req { + uint8_t subev_code; + uint16_t conn_handle; + uint64_t rand; + uint16_t div; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ (0x06) +struct ble_hci_ev_le_subev_rem_conn_param_req { + uint8_t subev_code; + uint16_t conn_handle; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t timeout; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_DATA_LEN_CHG (0x07) +struct ble_hci_ev_le_subev_data_len_chg { + uint8_t subev_code; + uint16_t conn_handle; + uint16_t max_tx_octets; + uint16_t max_tx_time; + uint16_t max_rx_octets; + uint16_t max_rx_time; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_RD_LOC_P256_PUBKEY (0x08) +struct ble_hci_ev_le_subev_rd_loc_p256_pubkey { + uint8_t subev_code; + uint8_t status; + uint8_t public_key[64]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_GEN_DHKEY_COMPLETE (0x09) +struct ble_hci_ev_le_subev_gen_dhkey_complete { + uint8_t subev_code; + uint8_t status; + uint8_t dh_key[32]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE (0x0A) +struct ble_hci_ev_le_subev_enh_conn_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t role; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t local_rpa[6]; + uint8_t peer_rpa[6]; + uint16_t conn_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint8_t mca; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT (0x0B) +struct dir_adv_report { + uint8_t type; + uint8_t addr_type; + uint8_t addr[6]; + uint8_t dir_addr_type; + uint8_t dir_addr[6]; + int8_t rssi; +} __attribute__((packed)); +struct ble_hci_ev_le_subev_direct_adv_rpt { + uint8_t subev_code; + uint8_t num_reports; + struct dir_adv_report reports[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE (0x0C) +struct ble_hci_ev_le_subev_phy_update_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t tx_phy; + uint8_t rx_phy; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_EXT_ADV_RPT (0x0D) +struct ext_adv_report { + uint16_t evt_type; + uint8_t addr_type; + uint8_t addr[6]; + uint8_t pri_phy; + uint8_t sec_phy; + uint8_t sid; + int8_t tx_power; + int8_t rssi; + uint16_t periodic_itvl; + uint8_t dir_addr_type; + uint8_t dir_addr[6]; + uint8_t data_len; + uint8_t data[0]; +} __attribute__((packed)); +struct ble_hci_ev_le_subev_ext_adv_rpt { + uint8_t subev_code; + uint8_t num_reports; + struct ext_adv_report reports[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E) +struct ble_hci_ev_le_subev_periodic_adv_sync_estab { + uint8_t subev_code; + uint8_t status; + uint16_t sync_handle; + uint8_t sid; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t phy; + uint16_t interval; + uint8_t aca; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT (0x0F) +struct ble_hci_ev_le_subev_periodic_adv_rpt { + uint8_t subev_code; + uint16_t sync_handle; + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; + uint8_t data_status; + uint8_t data_len; + uint8_t data[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST (0x10) +struct ble_hci_ev_le_subev_periodic_adv_sync_lost { + uint8_t subev_code; + uint16_t sync_handle; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_SCAN_TIMEOUT (0x11) +struct ble_hci_ev_le_subev_scan_timeout { + uint8_t subev_code; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED (0x12) +struct ble_hci_ev_le_subev_adv_set_terminated { + uint8_t subev_code; + uint8_t status; + uint8_t adv_handle; + uint16_t conn_handle; + uint8_t num_events; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD (0x13) +struct ble_hci_ev_le_subev_scan_req_rcvd { + uint8_t subev_code; + uint8_t adv_handle; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CHAN_SEL_ALG (0x14) - -/* Generic event header */ -#define BLE_HCI_EVENT_HDR_LEN (2) - -/* Event specific definitions */ -/* Event disconnect complete */ -#define BLE_HCI_EVENT_DISCONN_COMPLETE_LEN (4) - -/* Event encryption change (code=0x08) */ -#define BLE_HCI_EVENT_ENCRYPT_CHG_LEN (4) - -/* Event hardware error (code=0x10) */ -#define BLE_HCI_EVENT_HW_ERROR_LEN (1) - -/* Event key refresh complete (code=0x30) */ -#define BLE_HCI_EVENT_ENC_KEY_REFRESH_LEN (3) - -/* Event command complete */ -#define BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN (5) -#define BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN (6) - -/* Event command status */ -#define BLE_HCI_EVENT_CMD_STATUS_LEN (6) - -/* Number of completed packets */ -#define BLE_HCI_EVENT_NUM_COMP_PKTS_HDR_LEN (1) -#define BLE_HCI_EVENT_NUM_COMP_PKTS_ENT_LEN (4) - -/* Read remote version informaton */ -#define BLE_HCI_EVENT_RD_RM_VER_LEN (8) +struct ble_hci_ev_le_subev_chan_sel_alg { + uint8_t subev_code; + uint16_t conn_handle; + uint8_t csa; +} __attribute__((packed)); /* Data buffer overflow event */ -#define BLE_HCI_EVENT_DATABUF_OVERFLOW_LEN (1) #define BLE_HCI_EVENT_ACL_BUF_OVERFLOW (0x01) /* Advertising report */ @@ -747,11 +1374,7 @@ extern "C" { #define BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND (0x1b) #define BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_SCAN_IND (0x1a) -/* LE sub-event specific definitions */ -#define BLE_HCI_LE_MIN_LEN (1) /* Not including event hdr. */ - /* LE connection complete event (sub event 0x01) */ -#define BLE_HCI_LE_CONN_COMPLETE_LEN (19) #define BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER (0x00) #define BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE (0x01) @@ -759,53 +1382,9 @@ extern "C" { #define BLE_HCI_LE_CONN_HANDLE_MAX (0x0eff) /* LE advertising report event. (sub event 0x02) */ -#define BLE_HCI_LE_ADV_RPT_MIN_LEN (12) -#define BLE_HCI_LE_ADV_DIRECT_RPT_LEN (18) #define BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN (1) #define BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX (0x19) -/* Length of each record in an LE direct advertising report event. */ -#define BLE_HCI_LE_ADV_DIRECT_RPT_SUB_LEN (16) - -/* LE connection update complete event (sub event 0x03) */ -#define BLE_HCI_LE_CONN_UPD_LEN (10) - -/* LE long term key request event (sub event 0x05) */ -#define BLE_HCI_LE_LT_KEY_REQ_LEN (13) - -/* LE connection update complete event (sub event 0x03) */ -#define BLE_HCI_LE_RD_REM_USED_FEAT_LEN (12) - -/* LE remote connection parameter request event (sub event 0x06) */ -#define BLE_HCI_LE_REM_CONN_PARM_REQ_LEN (11) - -/* LE data length change event (sub event 0x07) */ -#define BLE_HCI_LE_DATA_LEN_CHG_LEN (11) - -/* LE PHY update complete event (sub event 0x0C) */ -#define BLE_HCI_LE_PHY_UPD_LEN (6) - -/* LE Periodic Advertising Sync Established Event (sub event 0x0e) */ -#define BLE_HCI_LE_PERIODIC_ADV_SYNC_ESTAB_LEN (16) - -/* LE Periodic Advertising Report Event (sub event 0x0f) */ -#define BLE_HCI_LE_PERIODIC_ADV_RPT_LEN (8) - -/* LE Periodic Advertising Sync Lost Event (sub event 0x10) */ -#define BLE_HCI_LE_PERIODIC_ADV_SYNC_LOST_LEN (3) - -/* LE Scan Timeout Event (sub event 0x11) */ -#define BLE_HCI_LE_SUBEV_SCAN_TIMEOUT_LEN (1) - -/* LE Advertising Set Terminated Event (sub event 0x12) */ -#define BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED_LEN (6) - -/* LE Scan Request Received event (sub event 0x13) */ -#define BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD_LEN (9) - -/* LE Channel Selection Algorithm event (sub event 0x14) */ -#define BLE_HCI_LE_SUBEV_CHAN_SEL_ALG_LEN (4) - /* Bluetooth Assigned numbers for version information.*/ #define BLE_HCI_VER_BCS_1_0b (0) #define BLE_HCI_VER_BCS_1_1 (1) @@ -829,398 +1408,6 @@ extern "C" { #define BLE_LMP_VER_BCS_4_2 (8) #define BLE_LMP_VER_BCS_5_0 (9) -/* Sub-event 0x0A: enhanced connection complete */ -#define BLE_HCI_LE_ENH_CONN_COMPLETE_LEN (31) - -/*--- Shared data structures ---*/ - -/* Host buffer size (OGF=0x03, OCF=0x0033) */ -struct hci_host_buf_size -{ - uint16_t acl_pkt_len; - uint8_t sync_pkt_len; - uint16_t num_acl_pkts; - uint16_t num_sync_pkts; -}; - -/* Host number of completed packets (OGF=0x03, OCF=0x0035) */ -struct hci_host_num_comp_pkts_entry -{ - uint16_t conn_handle; - uint16_t num_pkts; -}; - -/* Read local version information (OGF=0x0004, OCF=0x0001) */ -struct hci_loc_ver_info -{ - uint8_t status; - uint8_t hci_version; - uint16_t hci_revision; - uint8_t lmp_pal_version; - uint16_t mfrg_name; - uint8_t lmp_pal_subversion; -}; - -/* set random address command (ocf = 0x0005) */ -struct hci_rand_addr -{ - uint8_t addr[6]; -}; - -/* set advertising parameters command (ocf = 0x0006) */ -struct hci_adv_params -{ - uint8_t adv_type; - uint8_t adv_channel_map; - uint8_t own_addr_type; - uint8_t peer_addr_type; - uint8_t adv_filter_policy; - uint16_t adv_itvl_min; - uint16_t adv_itvl_max; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; -}; - -/* LE create connection command (ocf=0x000d). */ -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; -}; - -/* LE Read Local P-256 Public Key Complete Event */ -struct hci_le_subev_rd_loc_p256_pubkey { - uint8_t status; - uint8_t pubkey[64]; -} __attribute__((packed)); - -/* LE Generate DHKey Complete Event */ -struct hci_le_subev_gen_dhkey_complete { - uint8_t status; - uint8_t dhkey[32]; -} __attribute__((packed)); - -/* LE Directed Advertising Report Event */ -struct hci_le_subev_direct_adv_rpt_param { - uint8_t evt_type; - uint8_t addr_type; - uint8_t addr[6]; - uint8_t dir_addr_type; - uint8_t dir_addr[6]; - int8_t rssi; -} __attribute__((packed)); - -struct hci_le_subev_direct_adv_rpt { - uint8_t num_reports; - struct hci_le_subev_direct_adv_rpt_param params[0]; -} __attribute__((packed)); - -#if MYNEWT_VAL(BLE_EXT_ADV) -/* LE create connection command (ocf=0x0043). */ -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]; -}; - -struct hci_ext_adv_report_param { - uint16_t evt_type; - uint8_t addr_type; - uint8_t addr[6]; - uint8_t prim_phy; - uint8_t sec_phy; - uint8_t sid; - int8_t tx_power; - int8_t rssi; - uint16_t per_adv_itvl; - uint8_t dir_addr_type; - uint8_t dir_addr[6]; - uint8_t adv_data_len; - uint8_t adv_data[0]; -} __attribute__((packed)); - -struct hci_ext_adv_report { - /* We support one report per event for now */ - uint8_t subevt; - uint8_t num_reports; - struct hci_ext_adv_report_param params[0]; -} __attribute__((packed)); - -/* Ext Adv Set enable parameters, not in HCI order */ -struct hci_ext_adv_set -{ - uint8_t handle; - uint8_t events; - uint16_t duration; -}; - -/* Ext Advertising Parameters */ -struct hci_ext_adv_params -{ - uint16_t properties; - uint32_t min_interval; - uint32_t max_interval; - uint8_t chan_map; - uint8_t own_addr_type; - uint8_t peer_addr_type; - uint8_t peer_addr[6]; - uint8_t filter_policy; - int8_t tx_power; - uint8_t primary_phy; - uint8_t max_skip; - uint8_t secondary_phy; - uint8_t sid; - uint8_t scan_req_notif; -}; - -/* LE Extended Advertising Report Event */ -struct hci_le_subev_ext_adv_rpt { - uint8_t num_reports; - struct hci_ext_adv_report_param params[0]; -} __attribute__((packed)); - -#if MYNEWT_VAL(BLE_PERIODIC_ADV) -/* LE Periodic Advertising Sync Established Event */ -struct hci_le_subev_periodic_adv_sync_estab { - uint8_t status; - uint16_t sync_handle; - uint8_t sid; - uint8_t adv_addr_type; - uint8_t adv_addr[6]; - uint8_t adv_phy; - uint16_t per_adv_ival; - uint8_t adv_clk_accuracy; -} __attribute__((packed)); - -/* LE Periodic Advertising Report Event */ -struct hci_le_subev_periodic_adv_rpt { - uint16_t sync_handle; - int8_t tx_power; - int8_t rssi; - uint8_t unused; - uint8_t data_status; - uint8_t data_length; - uint8_t data[0]; -} __attribute__((packed)); - -/* LE Periodic Advertising Sync Lost Event */ -struct hci_le_subev_periodic_adv_sync_lost { - uint16_t sync_handle; -} __attribute__((packed)); -#endif - -/* LE Advertising Set Terminated Event */ -struct hci_le_subev_adv_set_terminated { - uint8_t status; - uint8_t adv_handle; - uint16_t conn_handle; - uint8_t num_compl_ext_adv_ev; -} __attribute__((packed)); - -/* LE Scan Request Received Event */ -struct hci_le_subev_scan_req_rcvd { - uint8_t adv_handle; - uint8_t scan_addr_type; - uint8_t scan_addr[6]; -} __attribute__((packed)); - -#endif - -/* LE Channel Selection Algorithm Event */ -struct hci_le_subev_chan_sel_alg { - uint16_t conn_handle; - uint8_t chan_sel_alg; -} __attribute__((packed)); - -/* LE connection update command (ocf=0x0013). */ -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; -}; - -/* LE start encryption command (ocf=0x0019) (note: fields out of order). */ -struct hci_start_encrypt -{ - uint16_t connection_handle; - uint16_t encrypted_diversifier; - uint64_t random_number; - uint8_t long_term_key[16]; -}; - -/* LE long term key request reply command (ocf=0x001a). */ -struct hci_lt_key_req_reply -{ - uint16_t conn_handle; - uint8_t long_term_key[16]; -}; - -/* LE Remote connection parameter request reply command */ -struct hci_conn_param_reply -{ - 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; -}; - -/* LE Remote connection parameter request negative reply command */ -struct hci_conn_param_neg_reply -{ - uint16_t handle; - uint8_t reason; -}; - -/* Encryption change event (code=0x08) (note: fields out of order) */ -struct hci_encrypt_change -{ - uint8_t status; - uint8_t encryption_enabled; - uint16_t connection_handle; -}; - -/* Encryption key refresh complete event (code=0x30) */ -struct hci_encrypt_key_refresh -{ - uint8_t status; - uint16_t connection_handle; -}; - -/* Connection complete LE meta subevent */ -struct hci_le_conn_complete -{ - uint8_t subevent_code; - 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]; -}; - -/* Connection update complete LE meta subevent */ -struct hci_le_conn_upd_complete -{ - uint8_t subevent_code; - uint8_t status; - uint16_t connection_handle; - uint16_t conn_itvl; - uint16_t conn_latency; - uint16_t supervision_timeout; -}; - -/* Remote connection parameter request LE meta subevent */ -struct hci_le_conn_param_req -{ - uint8_t subevent_code; - uint16_t connection_handle; - uint16_t itvl_min; - uint16_t itvl_max; - uint16_t latency; - uint16_t timeout; -}; - -/* Read Remote Supported Features complete LE meta subevent */ -struct hci_le_rd_rem_supp_feat_complete -{ - uint8_t subevent_code; - uint8_t status; - uint16_t connection_handle; - uint8_t features[8]; -}; - -/* LE long term key request event (note: fields out of order). */ -struct hci_le_lt_key_req -{ - uint64_t random_number; - uint16_t connection_handle; - uint16_t encrypted_diversifier; - uint8_t subevent_code; -}; - -/* Disconnection complete event (note: fields out of order). */ -struct hci_disconn_complete -{ - uint16_t connection_handle; - uint8_t status; - uint8_t reason; -}; - -/* Read RSSI command-complete parameters (note: fields out of order). */ -struct hci_read_rssi_ack_params -{ - uint16_t connection_handle; - uint8_t status; - int8_t rssi; -}; - -/* PHY updated completed LE meta subevent */ -struct hci_le_phy_upd_complete -{ - uint8_t subevent_code; - uint8_t status; - uint16_t connection_handle; - uint8_t tx_phy; - uint8_t rx_phy; -}; - -/* LE Advertising Set Terminated subevent*/ -struct hci_le_adv_set_terminated -{ - uint8_t subevent_code; - uint8_t status; - uint8_t adv_handle; - uint16_t conn_handle; - uint8_t completed_events; -}; - -/* LE Scan Request Received subevent */ -struct hci_le_scan_req_rcvd -{ - uint8_t subevent_code; - uint8_t adv_handle; - uint8_t scan_addr_type; - uint8_t scan_addr[BLE_DEV_ADDR_LEN]; -}; - #define BLE_HCI_DATA_HDR_SZ 4 #define BLE_HCI_DATA_HANDLE(handle_pb_bc) (((handle_pb_bc) & 0x0fff) >> 0) #define BLE_HCI_DATA_PB(handle_pb_bc) (((handle_pb_bc) & 0x3000) >> 12) @@ -1237,16 +1424,6 @@ struct hci_data_hdr #define BLE_HCI_PB_FIRST_FLUSH 2 #define BLE_HCI_PB_FULL 3 -struct hci_add_dev_to_resolving_list { - uint8_t addr_type; - uint8_t addr[6]; - uint8_t local_irk[16]; - uint8_t peer_irk[16]; -}; - -/* External data structures */ -extern const uint8_t g_ble_hci_le_cmd_len[BLE_HCI_NUM_LE_CMDS]; - #ifdef __cplusplus } #endif diff --git a/nimble/transport/emspi/src/ble_hci_emspi.c b/nimble/transport/emspi/src/ble_hci_emspi.c index 2c1f951dd..61c0c9cba 100644 --- a/nimble/transport/emspi/src/ble_hci_emspi.c +++ b/nimble/transport/emspi/src/ble_hci_emspi.c @@ -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; } diff --git a/nimble/transport/socket/src/ble_hci_socket.c b/nimble/transport/socket/src/ble_hci_socket.c index e24877b7e..863d0fbb2 100644 --- a/nimble/transport/socket/src/ble_hci_socket.c +++ b/nimble/transport/socket/src/ble_hci_socket.c @@ -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; } diff --git a/nimble/transport/uart/src/ble_hci_uart.c b/nimble/transport/uart/src/ble_hci_uart.c index ff0dbec34..ac6af28e3 100644 --- a/nimble/transport/uart/src/ble_hci_uart.c +++ b/nimble/transport/uart/src/ble_hci_uart.c @@ -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;