From a21974068fc7b60ffb6cfd7d2782e9719d00ef4b Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:24 +0200 Subject: [PATCH 01/27] nimble/controller: Remove few not needed #ifdefs There is no need for special handling of single iteration loop as compiler should catch this. X-Original-Commit: 9878a220f4f9bd0fda1c4f452425cb3475a0a2d9 --- nimble/controller/include/controller/ble_ll_adv.h | 2 -- nimble/controller/src/ble_ll_adv.c | 13 +------------ 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index 635c62ea7..e6994a6bd 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -127,10 +127,8 @@ int ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi); /* Read advertising channel power */ int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen); -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) int ble_ll_adv_multi_adv_cmd(uint8_t *cmd, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); -#endif /*---- API used by BLE LL ----*/ /* Send the connection complete event */ diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 980ca5459..0e91e3f8b 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1638,10 +1638,8 @@ ble_ll_adv_event_done(struct os_event *ev) int ble_ll_adv_can_chg_whitelist(void) { - int rc; struct ble_ll_adv_sm *advsm; - -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) + int rc; int i; rc = 1; @@ -1653,15 +1651,6 @@ ble_ll_adv_can_chg_whitelist(void) break; } } -#else - advsm = &g_ble_ll_adv_sm[0]; - if (advsm->adv_enabled && - (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE)) { - rc = 0; - } else { - rc = 1; - } -#endif return rc; } From 9c5f0deccab68e7ea3b4f9750be774d724b6940d Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 02/27] nimble/controller: Rename BLE_MULTI_ADV_SUPPORT Name it BLE_ANDROID_MULTI_ADV_SUPPORT as it will be used only do enable Android specific vendor commands. X-Original-Commit: 01b9ef9da0e00a45fd270bcdd661b7e4cf5b1fa8 --- nimble/controller/src/ble_ll_adv.c | 20 ++++++++++---------- nimble/controller/src/ble_ll_hci.c | 2 +- nimble/include/nimble/ble.h | 2 +- nimble/syscfg.yml | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 0e91e3f8b..51f62de44 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -103,7 +103,7 @@ struct ble_ll_adv_sm uint8_t *conn_comp_ev; struct os_event adv_txdone_ev; struct ble_ll_sched_item adv_sch; -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; #endif }; @@ -659,7 +659,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) } /* Deal with multi-advertising command specific*/ -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) if (is_multi) { /* Get and check advertising power */ advsm->adv_txpwr = cmd[22]; @@ -741,7 +741,7 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) /* Set to standby if we are no longer advertising */ OS_ENTER_CRITICAL(sr); -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) if (g_ble_ll_cur_adv_sm == advsm) { ble_phy_disable(); ble_ll_wfr_disable(); @@ -805,7 +805,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) * is why I chose command disallowed. */ if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) { -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) if (!ble_ll_is_valid_random_addr(advsm->adv_random_addr)) { return BLE_ERR_CMD_DISALLOWED; } @@ -842,7 +842,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) addr = g_dev_addr; advsm->adv_txadd = 0; } else { -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) addr = advsm->adv_random_addr; #else addr = g_random_addr; @@ -1041,7 +1041,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance) return BLE_ERR_SUCCESS; } -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) int ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance) { @@ -1330,7 +1330,7 @@ int ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok) { int rc; -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) struct ble_mbuf_hdr *rxhdr; #endif @@ -1338,7 +1338,7 @@ ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok) if (rxpdu == NULL) { ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm); } else { -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) rxhdr = BLE_MBUF_HDR_PTR(rxpdu); rxhdr->rxinfo.advsm = g_ble_ll_cur_adv_sm; #endif @@ -1382,7 +1382,7 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) int adv_event_over; struct ble_ll_adv_sm *advsm; -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) advsm = (struct ble_ll_adv_sm *)hdr->rxinfo.advsm; #else advsm = &g_ble_ll_adv_sm[0]; @@ -1667,7 +1667,7 @@ ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, uint8_t *evbuf; struct ble_ll_adv_sm *advsm; -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) advsm = (struct ble_ll_adv_sm *)rxhdr->rxinfo.advsm; evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); if (evbuf) { diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 625647496..90f0175c6 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -647,7 +647,7 @@ ble_ll_hci_vendor_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = BLE_ERR_SUCCESS; } break; -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) case BLE_HCI_OCF_MULTI_ADV: if (cmdlen > 0) { rc = ble_ll_adv_multi_adv_cmd(cmdbuf, cmdlen, rspbuf, rsplen); diff --git a/nimble/include/nimble/ble.h b/nimble/include/nimble/ble.h index 69ac3a384..6db8cd901 100644 --- a/nimble/include/nimble/ble.h +++ b/nimble/include/nimble/ble.h @@ -67,7 +67,7 @@ struct ble_mbuf_hdr_rxinfo uint8_t handle; int8_t rssi; int8_t phy; -#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) void *advsm; /* advertising state machine */ #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) diff --git a/nimble/syscfg.yml b/nimble/syscfg.yml index 7f348b8af..329810701 100644 --- a/nimble/syscfg.yml +++ b/nimble/syscfg.yml @@ -41,8 +41,8 @@ syscfg.defs: Enables the BLE whitelist for controlling who to connect to or accept a connection from. (0/1) value: 1 - BLE_MULTI_ADV_SUPPORT: - description: 'Support for multi-advertisers' + BLE_ANDROID_MULTI_ADV_SUPPORT: + description: 'Support for Android Vendor multi-advertisers HCI commands' value: 0 BLE_MULTI_ADV_INSTANCES: description: > From e45518d3a82c084a35da476130e0e44516adf6d8 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 03/27] nimble/controller: Don't build VS code if Android VS are not enabled There is no need for handling VS commands if none is required. X-Original-Commit: 6b03aa6af9fa21c1d01cdc3fb56218e149da1606 --- nimble/controller/src/ble_ll_hci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 90f0175c6..7446853c0 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -582,6 +582,7 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) return rc; } +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) /** * Returns the vendor specific capabilities * @@ -647,13 +648,11 @@ ble_ll_hci_vendor_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = BLE_ERR_SUCCESS; } break; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) case BLE_HCI_OCF_MULTI_ADV: if (cmdlen > 0) { rc = ble_ll_adv_multi_adv_cmd(cmdbuf, cmdlen, rspbuf, rsplen); } break; -#endif default: rc = BLE_ERR_UNKNOWN_HCI_CMD; break; @@ -662,6 +661,7 @@ ble_ll_hci_vendor_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) /* XXX: for now, all vendor commands return a command complete */ return rc; } +#endif /** * Process a LE command sent from the host to the controller. The HCI command @@ -1122,9 +1122,11 @@ ble_ll_hci_cmd_proc(struct os_event *ev) case BLE_HCI_OGF_LE: rc = ble_ll_hci_le_cmd_proc(cmdbuf, ocf, &rsplen); break; +#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) case BLE_HCI_OGF_VENDOR: rc = ble_ll_hci_vendor_cmd_proc(cmdbuf, ocf, &rsplen); break; +#endif default: /* XXX: Need to support other OGF. For now, return unsupported */ rc = BLE_ERR_UNKNOWN_HCI_CMD; From 96989da35263dbd246a52c03b6304ff932e78355 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 04/27] nimble/controller: Reject le set adv if connectable As defined in Core Specification 5.0 Vol. 2 Part E 7.8.52. X-Original-Commit: e641a9fdc4667ecc742959ee86d701f888c1bdee --- nimble/controller/src/ble_ll_adv.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 51f62de44..515abff1d 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1050,7 +1050,20 @@ ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance) if (instance >= BLE_LL_ADV_INSTANCES) { return BLE_ERR_INV_HCI_CMD_PARMS; } + advsm = &g_ble_ll_adv_sm[instance]; + + /* + * Reject if connectable advertising is on + * Core Spec Vol. 2 Part E 7.8.52 + */ + if (advsm->adv_enabled && + (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD || + advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD || + advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_IND)) { + return BLE_ERR_CMD_DISALLOWED; + } + memcpy(advsm->adv_random_addr, addr, BLE_DEV_ADDR_LEN); return BLE_ERR_SUCCESS; } From 0766c508e916df818c74c876ce203fdb1a3071f4 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 05/27] nimble/controller: Add initial stubs for Ext Advertising HCI commands This adds the necessary boilerplater for new commands. X-Original-Commit: ee960d823a96ff427973c7edacc78a81eb9b3ae2 --- .../include/controller/ble_ll_adv.h | 8 +++ nimble/controller/src/ble_ll_adv.c | 42 +++++++++++ nimble/controller/src/ble_ll_hci.c | 70 +++++++++++++++++++ nimble/include/nimble/hci_common.h | 6 ++ 4 files changed, 126 insertions(+) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index e6994a6bd..de18518eb 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -178,6 +178,14 @@ void ble_ll_adv_halt(struct ble_ll_adv_sm *advsm); /* 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_clear_all(void); +int ble_ll_adv_ext_set_param(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); + #ifdef __cplusplus } #endif diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 515abff1d..1c0f887fe 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1042,6 +1042,34 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance) } #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +int +ble_ll_adv_ext_set_param(uint8_t *rspbuf, uint8_t *rsplen) +{ + /* TODO */ + return BLE_ERR_UNKNOWN_HCI_CMD; +} + +int +ble_ll_adv_ext_set_adv_data(uint8_t *cmdbuf, uint8_t cmdlen) +{ + /* TODO */ + return BLE_ERR_UNKNOWN_HCI_CMD; +} + +int +ble_ll_adv_ext_set_scan_rsp(uint8_t *cmdbuf, uint8_t cmdlen) +{ + /* TODO */ + return BLE_ERR_UNKNOWN_HCI_CMD; +} + +int +ble_ll_adv_ext_set_enable(uint8_t *cmd, uint8_t len) +{ + /* TODO */ + return BLE_ERR_UNKNOWN_HCI_CMD; +} + int ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance) { @@ -1068,6 +1096,20 @@ ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance) return BLE_ERR_SUCCESS; } +int +ble_ll_adv_remove(uint8_t instance) +{ + /* TODO */ + return BLE_ERR_UNKNOWN_HCI_CMD; +} + +int +ble_ll_adv_clear_all(void) +{ + /* TODO */ + return BLE_ERR_UNKNOWN_HCI_CMD; +} + /** * Process the multi-advertising command * diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 7446853c0..7c600a317 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -582,6 +582,47 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) return rc; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/** HCI LE read maximum advertising data length command. Returns the controllers +* max supported advertising data length; +* +* @param rspbuf Pointer to response buffer +* @param rsplen Length of response buffer +* +* @return int BLE error code +*/ +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; + return BLE_ERR_SUCCESS; +} + +/** + * HCI LE read number of supported advertising sets + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_adv_rd_sup_adv_sets(uint8_t *rspbuf, uint8_t *rsplen) +{ + rspbuf[0] = BLE_LL_ADV_INSTANCES; + *rsplen = BLE_HCI_RD_NR_SUP_ADV_SETS; + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_ext_adv_set_remove(uint8_t *cmd) +{ + return ble_ll_adv_remove(cmd[0]); +} + +#endif + #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) /** * Returns the vendor specific capabilities @@ -852,6 +893,35 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN: rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen); break; +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1) + case BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR: + rc = ble_ll_adv_set_random_addr(cmdbuf + 1, cmdbuf[0]); + break; + case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: + rc = ble_ll_adv_ext_set_param(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: + rc = ble_ll_adv_ext_set_adv_data(cmdbuf, cmdlen); + break; + case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA: + rc = ble_ll_adv_ext_set_scan_rsp(cmdbuf, cmdlen); + break; + case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE: + rc = ble_ll_adv_ext_set_enable(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN: + rc = ble_ll_adv_rd_max_adv_data_len(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS: + rc = ble_ll_adv_rd_sup_adv_sets(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_REMOVE_ADV_SET: + rc = ble_ll_ext_adv_set_remove(cmdbuf); + break; + case BLE_HCI_OCF_LE_CLEAR_ADV_SETS: + rc = ble_ll_adv_clear_all(); + break; +#endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) case BLE_HCI_OCF_LE_RD_PHY: rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, rspbuf, rsplen); diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index ee75300a4..36569fae7 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -471,6 +471,12 @@ extern "C" { /* --- 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_PER_ADV_PARAMS_LEN (7) From c8ad2c7ab04edcf2db86d0f5072f35f6d5c3c9cc Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 06/27] nimble/controller: Add LE Set Extended Advertising Enable Command X-Original-Commit: 9709c43814b0fd8fcb9a4fefbb47782f5c614d49 --- .../include/controller/ble_ll_adv.h | 3 +- nimble/controller/src/ble_ll_adv.c | 92 +++++++++++++++++-- nimble/controller/src/ble_ll_hci.c | 2 +- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index de18518eb..3fde40a81 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -113,7 +113,8 @@ 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 *cmd, uint8_t instance); +int ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, + uint8_t event); /* Set advertising data */ int ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 1c0f887fe..bb673e8b1 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -105,6 +105,8 @@ struct ble_ll_adv_sm struct ble_ll_sched_item adv_sch; #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; + uint16_t duration; /* TODO */ + uint8_t events; /* TODO */ #endif }; @@ -947,10 +949,10 @@ ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen) * @return int */ int -ble_ll_adv_set_enable(uint8_t *cmd, uint8_t instance) +ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, + uint8_t events) { int rc; - uint8_t enable; struct ble_ll_adv_sm *advsm; if (instance >= BLE_LL_ADV_INSTANCES) { @@ -960,8 +962,10 @@ ble_ll_adv_set_enable(uint8_t *cmd, uint8_t instance) advsm = &g_ble_ll_adv_sm[instance]; rc = BLE_ERR_SUCCESS; - enable = cmd[0]; if (enable == 1) { + advsm->duration = duration; + advsm->events = events; + /* If already enabled, do nothing */ if (!advsm->adv_enabled) { /* Start the advertising state machine */ @@ -1063,11 +1067,87 @@ ble_ll_adv_ext_set_scan_rsp(uint8_t *cmdbuf, uint8_t cmdlen) return BLE_ERR_UNKNOWN_HCI_CMD; } +struct ext_adv_set { + uint8_t handle; + uint16_t duration; + uint8_t events; +} __attribute__((packed)); + +/** + * HCI LE extended advertising enable command + * + * @param cmd Pointer to command data + * @param len Command data length + * + * @return int BLE error code + */ int ble_ll_adv_ext_set_enable(uint8_t *cmd, uint8_t len) { - /* TODO */ - return BLE_ERR_UNKNOWN_HCI_CMD; + struct ext_adv_set* set; + uint8_t enable; + uint8_t sets; + int i, j, rc; + + if (len < 2) { + 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))) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (sets > BLE_LL_ADV_INSTANCES) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (sets == 0) { + if (enable) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* disable all instances */ + for (i = 0; i < BLE_LL_ADV_INSTANCES; i++) { + ble_ll_adv_set_enable(i, 0, 0, 0); + } + + return BLE_ERR_SUCCESS; + } + + set = (void *) cmd; + /* validate instances */ + for (i = 0; i < sets; i++) { + if (set->handle > BLE_LL_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) { + 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); + if (rc) { + return rc; + } + + set++; + } + + return BLE_ERR_SUCCESS; } int @@ -1156,7 +1236,7 @@ ble_ll_adv_multi_adv_cmd(uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, break; case BLE_HCI_MULTI_ADV_ENABLE: if (cmdlen == BLE_HCI_MULTI_ADV_ENABLE_LEN) { - rc = ble_ll_adv_set_enable(cmdbuf, cmdbuf[1]); + rc = ble_ll_adv_set_enable(cmdbuf[0], cmdbuf[1], 0, 0); } break; default: diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 7c600a317..7fdd11672 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -774,7 +774,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, 0); break; case BLE_HCI_OCF_LE_SET_ADV_ENABLE: - rc = ble_ll_adv_set_enable(cmdbuf, 0); + rc = ble_ll_adv_set_enable(cmdbuf[0], 0, 0, 0); break; case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: rc = ble_ll_scan_set_enable(cmdbuf, 0); From 0fcafef31728670dfb05b45312dbe06eedd3625d Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 07/27] nimble/controller: Add LE Remove Advertising Set Command X-Original-Commit: 89e6b59827993bb085abd9044e1b71d6a8448983 --- nimble/controller/src/ble_ll_adv.c | 61 ++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index bb673e8b1..d5876f8c8 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -115,6 +115,7 @@ struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_LL_ADV_INSTANCES]; struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm; static void ble_ll_adv_done(struct ble_ll_adv_sm *advsm); +static void ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm); #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) /** @@ -1176,11 +1177,35 @@ ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance) return BLE_ERR_SUCCESS; } +/** + * 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) { - /* TODO */ - return BLE_ERR_UNKNOWN_HCI_CMD; + struct ble_ll_adv_sm *advsm; + + /* TODO + * Should we allow any value for instance ID? + */ + + if (instance >= BLE_LL_ADV_INSTANCES) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm = &g_ble_ll_adv_sm[instance]; + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + ble_ll_adv_sm_init(advsm); + + return BLE_ERR_SUCCESS; } int @@ -1904,6 +1929,23 @@ ble_ll_adv_enabled(void) return g_ble_ll_adv_sm[0].adv_enabled; } +static void +ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm) +{ + uint8_t i = advsm->adv_instance; + + memset(advsm, 0, sizeof(struct ble_ll_adv_sm)); + + advsm->adv_instance = i; + advsm->adv_itvl_min = BLE_HCI_ADV_ITVL_DEF; + advsm->adv_itvl_max = BLE_HCI_ADV_ITVL_DEF; + advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF; + + /* Initialize advertising tx done event */ + advsm->adv_txdone_ev.ev_cb = ble_ll_adv_event_done; + advsm->adv_txdone_ev.ev_arg = advsm; +} + /** * Initialize the advertising functionality of a BLE device. This should * be called once on initialization @@ -1912,22 +1954,11 @@ void ble_ll_adv_init(void) { int i; - struct ble_ll_adv_sm *advsm; /* Set default advertising parameters */ for (i = 0; i < BLE_LL_ADV_INSTANCES; ++i) { - advsm = &g_ble_ll_adv_sm[i]; - - memset(advsm, 0, sizeof(struct ble_ll_adv_sm)); - - advsm->adv_instance = i; - advsm->adv_itvl_min = BLE_HCI_ADV_ITVL_DEF; - advsm->adv_itvl_max = BLE_HCI_ADV_ITVL_DEF; - advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF; - - /* Initialize advertising tx done event */ - advsm->adv_txdone_ev.ev_cb = ble_ll_adv_event_done; - advsm->adv_txdone_ev.ev_arg = advsm; + g_ble_ll_adv_sm[i].adv_instance = i; + ble_ll_adv_sm_init(&g_ble_ll_adv_sm[i]); } } From f11c4c5733fa84557c86951367721c727731b671 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 08/27] nimble/controller: Add LE Clear Advertising Sets Command X-Original-Commit: f8e73d261f551b2e27a0640c6a2e78dd7fe8bfb9 --- nimble/controller/src/ble_ll_adv.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index d5876f8c8..e90032032 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1208,11 +1208,25 @@ ble_ll_adv_remove(uint8_t instance) return BLE_ERR_SUCCESS; } +/** + * HCI LE extended advertising clear command + * + * @return int BLE error code + */ int ble_ll_adv_clear_all(void) { - /* TODO */ - return BLE_ERR_UNKNOWN_HCI_CMD; + int i; + + for (i = 0; i < BLE_LL_ADV_INSTANCES; i++) { + if (g_ble_ll_adv_sm[i].adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + } + + ble_ll_adv_reset(); + + return BLE_ERR_SUCCESS; } /** From 92d91a5094ce4e59c06957ae65b93ca53c9a6a3a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 09/27] nimble/controller: Add LE Set Extended Advertising Data Command X-Original-Commit: be4689bb4f1b55cc2ac9d646f86a6b82a273da35 --- .../include/controller/ble_ll_adv.h | 2 +- nimble/controller/src/ble_ll_adv.c | 108 +++++++++++++++--- nimble/controller/src/ble_ll_hci.c | 3 +- nimble/include/nimble/hci_common.h | 5 + 4 files changed, 103 insertions(+), 15 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index 3fde40a81..20c47e9e1 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -117,7 +117,7 @@ int ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, uint8_t event); /* Set advertising data */ -int ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance); +int ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation); /* Set scan response data */ int ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index e90032032..45d5023dc 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -107,6 +107,7 @@ struct ble_ll_adv_sm uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; uint16_t duration; /* TODO */ uint8_t events; /* TODO */ + uint16_t did; /* TODO */ #endif }; @@ -1023,25 +1024,99 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, 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 instance) +ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) { uint8_t datalen; + uint8_t off = 0; struct ble_ll_adv_sm *advsm; - /* Check for valid advertising data length */ - datalen = cmd[0]; - if (datalen > BLE_ADV_DATA_MAX_LEN) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (instance >= BLE_LL_ADV_INSTANCES) { return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Copy the new data into the advertising structure. */ advsm = &g_ble_ll_adv_sm[instance]; - advsm->adv_len = datalen; - memcpy(advsm->adv_data, cmd + 1, datalen); + datalen = cmd[0]; + + /* check if type of advertising support adv data */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } else { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + switch (operation) { + case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (datalen > BLE_ADV_DATA_MAX_LEN) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + break; + case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!advsm->adv_enabled || !advsm->adv_len || datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* update DID only */ + advsm->did = rand() & 0x0fff; + return BLE_ERR_SUCCESS; + case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST: + /* TODO mark adv data as complete? */ + /* fall through */ + case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + off = advsm->adv_len; + break; + case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + break; + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check for valid advertising data length */ + if (datalen + off > BLE_ADV_DATA_MAX_LEN) { + advsm->adv_len = 0; + return BLE_ERR_MEM_CAPACITY; + } + + /* DID shall be updated when host provides new advertising data */ + advsm->did = rand() & 0x0fff; + + /* Copy the new data into the advertising structure. */ + advsm->adv_len = datalen + off; + memcpy(advsm->adv_data + off, cmd + 1, datalen); return BLE_ERR_SUCCESS; } @@ -1057,8 +1132,14 @@ ble_ll_adv_ext_set_param(uint8_t *rspbuf, uint8_t *rsplen) int ble_ll_adv_ext_set_adv_data(uint8_t *cmdbuf, uint8_t cmdlen) { - /* TODO */ - return BLE_ERR_UNKNOWN_HCI_CMD; + /* check if length is correct */ + if (cmdlen < 4) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* TODO fragment preference ignored for now */ + + return ble_ll_adv_set_adv_data(cmdbuf + 3, cmdbuf[0], cmdbuf[1]); } int @@ -1260,7 +1341,8 @@ ble_ll_adv_multi_adv_cmd(uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, break; case BLE_HCI_MULTI_ADV_DATA: if (cmdlen == BLE_HCI_MULTI_ADV_DATA_LEN) { - rc = ble_ll_adv_set_adv_data(cmdbuf, cmdbuf[32]); + rc = ble_ll_adv_set_adv_data(cmdbuf, cmdbuf[32], + BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE); } break; case BLE_HCI_MULTI_ADV_SCAN_RSP_DATA: diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 7fdd11672..643153cc8 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -768,7 +768,8 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = ble_ll_adv_read_txpwr(rspbuf, rsplen); break; case BLE_HCI_OCF_LE_SET_ADV_DATA: - rc = ble_ll_adv_set_adv_data(cmdbuf, 0); + rc = ble_ll_adv_set_adv_data(cmdbuf, 0, + BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE); break; case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, 0); diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 36569fae7..cbf7cfd33 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -461,6 +461,11 @@ extern "C" { /* --- LE set extended advertising data (OCF 0x0037) */ #define BLE_HCI_LE_SET_EXT_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN +#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT (0) +#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST (1) +#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST (2) +#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE (3) +#define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED (4) /* --- LE set extended scan response data (OCF 0x0038) */ #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_LEN BLE_HCI_VARIABLE_LEN From fad18e99286d6976f52fb1aabb6296d999ee9a96 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:25 +0200 Subject: [PATCH 10/27] nimble/controller: Add LE Set Extended Scan Response Data Command X-Original-Commit: ec0f29a1df3cae213be7bf72768cf7420291a798 --- .../include/controller/ble_ll_adv.h | 3 +- nimble/controller/src/ble_ll_adv.c | 89 ++++++++++++++++--- nimble/controller/src/ble_ll_hci.c | 3 +- nimble/include/nimble/hci_common.h | 4 + 4 files changed, 84 insertions(+), 15 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index 20c47e9e1..7ba040a7b 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -120,7 +120,8 @@ int ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, int ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation); /* Set scan response data */ -int ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance); +int ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, + uint8_t operation); /* Set advertising parameters */ int ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 45d5023dc..623044c1a 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -991,25 +991,81 @@ ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, * @return int */ int -ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance) +ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, uint8_t operation) { uint8_t datalen; + uint8_t off = 0; struct ble_ll_adv_sm *advsm; - /* Check for valid scan response data length */ - datalen = cmd[0]; - if (datalen > BLE_SCAN_RSP_DATA_MAX_LEN) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - if (instance >= BLE_LL_ADV_INSTANCES) { return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Copy the new data into the advertising structure. */ advsm = &g_ble_ll_adv_sm[instance]; - advsm->scan_rsp_len = datalen; - memcpy(advsm->scan_rsp_data, cmd + 1, datalen); + datalen = cmd[0]; + + /* check if type of advertising support scan rsp */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + switch (operation) { + case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (datalen > BLE_ADV_DATA_MAX_LEN) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + break; + case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_LAST: + /* TODO mark scan rsp as complete? */ + /* fall through */ + case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + off = advsm->scan_rsp_len; + break; + case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + break; + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check for valid advertising data length */ + if (datalen + off > BLE_SCAN_RSP_DATA_MAX_LEN) { + advsm->scan_rsp_len = 0; + return BLE_ERR_MEM_CAPACITY; + } + + /* DID shall be updated when host provides new scan response data */ + advsm->did = rand() & 0x0fff; + + /* Copy the new data into the advertising structure. */ + advsm->scan_rsp_len = datalen + off; + memcpy(advsm->scan_rsp_data + off, cmd + 1, datalen); return BLE_ERR_SUCCESS; } @@ -1145,8 +1201,14 @@ 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) { - /* TODO */ - return BLE_ERR_UNKNOWN_HCI_CMD; + /* check if length is correct */ + if (cmdlen < 4) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* TODO fragment preference ignored for now */ + + return ble_ll_adv_set_scan_rsp_data(cmdbuf + 3, cmdbuf[0], cmdbuf[1]); } struct ext_adv_set { @@ -1347,7 +1409,8 @@ ble_ll_adv_multi_adv_cmd(uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, break; case BLE_HCI_MULTI_ADV_SCAN_RSP_DATA: if (cmdlen == BLE_HCI_MULTI_ADV_SCAN_RSP_DATA_LEN) { - rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, cmdbuf[32]); + rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, cmdbuf[32], + BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE); } break; case BLE_HCI_MULTI_ADV_SET_RAND_ADDR: diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 643153cc8..d1fdb14ec 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -772,7 +772,8 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE); break; case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: - rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, 0); + rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, 0, + BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE); break; case BLE_HCI_OCF_LE_SET_ADV_ENABLE: rc = ble_ll_adv_set_enable(cmdbuf[0], 0, 0, 0); diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index cbf7cfd33..783fdd1f8 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -469,6 +469,10 @@ extern "C" { /* --- LE set extended scan response data (OCF 0x0038) */ #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_LEN BLE_HCI_VARIABLE_LEN +#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT (0) +#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST (1) +#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_LAST (2) +#define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE (3) /* --- LE set extended advertising enable (OCF 0x0039) */ #define BLE_HCI_LE_SET_EXT_ADV_ENABLE_LEN BLE_HCI_VARIABLE_LEN From 9ff6333f39feda94787695105c69dcee3a17eeab Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:26 +0200 Subject: [PATCH 11/27] nimble/controller: Add LE Set Extended Advertising Parameters Command X-Original-Commit: 42f51756ba2e378c6da895adbdb5e5e26f49621d --- .../include/controller/ble_ll_adv.h | 2 +- nimble/controller/src/ble_ll_adv.c | 174 +++++++++++++++++- nimble/controller/src/ble_ll_hci.c | 2 +- nimble/include/nimble/hci_common.h | 14 ++ 4 files changed, 187 insertions(+), 5 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index 7ba040a7b..b0764c538 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -183,7 +183,7 @@ 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_clear_all(void); -int ble_ll_adv_ext_set_param(uint8_t *rspbuf, uint8_t *rsplen); +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); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 623044c1a..c951e3ce3 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -105,9 +105,14 @@ struct ble_ll_adv_sm struct ble_ll_sched_item adv_sch; #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; + uint16_t props; /* TODO */ uint16_t duration; /* TODO */ uint8_t events; /* TODO */ uint16_t did; /* TODO */ + uint8_t pri_phy; /* TODO */ + uint8_t sec_phy; /* TODO */ + uint8_t sid; /* TODO */ + uint8_t scan_req_notif; /* TODO */ #endif }; @@ -1179,10 +1184,173 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) int -ble_ll_adv_ext_set_param(uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) { - /* TODO */ - return BLE_ERR_UNKNOWN_HCI_CMD; + uint8_t adv_filter_policy; + uint8_t adv_chanmask; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint32_t adv_itvl_min; + uint32_t adv_itvl_max; + uint16_t min_itvl = 0; + 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; + + if (cmdbuf[0] >= BLE_LL_ADV_INSTANCES) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm = &g_ble_ll_adv_sm[cmdbuf[0]]; + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + props = get_le16(&cmdbuf[1]); + + adv_itvl_min = cmdbuf[5] << 16 | cmdbuf[4] << 8 | cmdbuf[3]; + adv_itvl_max = cmdbuf[8] << 16 | cmdbuf[7] << 8 | cmdbuf[6]; + + if (props & ~BLE_HCI_LE_SET_EXT_ADV_PROP_MASK) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (advsm->adv_len > BLE_ADV_DATA_MAX_LEN || + advsm->scan_rsp_len > BLE_SCAN_RSP_DATA_MAX_LEN) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* if legacy bit is set possible values are limited */ + switch (props) { + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN: + break; + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } else { + /* HD directed advertising allowed only on legacy PDUs */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* if ext advertising PDUs are used then it shall not be both + * connectable and scanable + */ + if ((props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) && + (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + min_itvl = BLE_LL_ADV_ITVL_MIN; + } + + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + if (advsm->adv_len || advsm->scan_rsp_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Ignore min/max interval */ + min_itvl = 0; + adv_itvl_min = 0; + adv_itvl_max = 0; + } + + /* Make sure interval minimum is valid for the advertising type + * TODO for now limit those to values from legacy advertising + */ + if ((adv_itvl_min > adv_itvl_max) || (adv_itvl_min < min_itvl) || + (adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) || + (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* 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)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* 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)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + /* Reset RPA timer so we generate a new RPA */ + advsm->adv_rpa_timer = os_time_get(); + } +#else + /* If we dont support privacy some address types wont work */ + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + return BLE_ERR_UNSUPPORTED; + } +#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) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + pri_phy = cmdbuf[20]; + if (pri_phy != BLE_HCI_LE_PHY_1M && pri_phy != BLE_HCI_LE_PHY_CODED) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + sec_phy = cmdbuf[22]; + if (pri_phy != BLE_HCI_LE_PHY_1M && pri_phy != BLE_HCI_LE_PHY_2M && + pri_phy != BLE_HCI_LE_PHY_CODED) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + sid = cmdbuf[23]; + if (sid > 0x0f) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + scan_req_notif = cmdbuf[24]; + if (scan_req_notif > 0x01) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm->adv_directed = props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; + if (advsm->adv_directed) { + memcpy(advsm->peer_addr, &cmdbuf[12], BLE_DEV_ADDR_LEN); + } + + advsm->adv_txpwr = 0; /* TODO rspbuf[21];*/ + advsm->own_addr_type = own_addr_type; + advsm->peer_addr_type = peer_addr_type; + advsm->adv_filter_policy = adv_filter_policy; + advsm->adv_chanmask = adv_chanmask; + 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->sid = sid; + advsm->scan_req_notif = scan_req_notif; + advsm->props = props; + + rspbuf[0] = advsm->adv_txpwr; + *rsplen = 1; + + return 0; } int diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index d1fdb14ec..d313eb3cc 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -900,7 +900,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = ble_ll_adv_set_random_addr(cmdbuf + 1, cmdbuf[0]); break; case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: - rc = ble_ll_adv_ext_set_param(rspbuf, rsplen); + rc = ble_ll_adv_ext_set_param(cmdbuf, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: rc = ble_ll_adv_ext_set_adv_data(cmdbuf, cmdlen); diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 783fdd1f8..66a04de69 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -458,6 +458,20 @@ extern "C" { /* --- 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) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED (0x0008) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY (0x0010) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV (0x0020) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR (0x0040) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_MASK (0x7F) + +#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND (0x0013) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR (0x0015) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR (0x001d) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN (0x0012) +#define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN (0x0010) /* --- LE set extended advertising data (OCF 0x0037) */ #define BLE_HCI_LE_SET_EXT_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN From fff1b2c964d2473f77d5520dfcd9fc1e87c47530 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:26 +0200 Subject: [PATCH 12/27] nimble/controller: Use properties for storing advertising type This is in preparation for handling extended advertising PDUs. Legacy advertising PDUs are mapped as describbed in Core Spec Vol. 2 Part E. 7.8.53 table 7.2. X-Original-Commit: de29d08a03657887b3b24369f64a24e932588f5a --- nimble/controller/src/ble_ll_adv.c | 130 +++++++++++------------------ 1 file changed, 50 insertions(+), 80 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index c951e3ce3..2844190ce 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -73,7 +73,6 @@ struct ble_ll_adv_sm { uint8_t adv_enabled; uint8_t adv_instance; - uint8_t adv_type; uint8_t adv_len; uint8_t adv_chanmask; uint8_t adv_filter_policy; @@ -83,7 +82,6 @@ struct ble_ll_adv_sm uint8_t scan_rsp_len; uint8_t adv_pdu_len; int8_t adv_rpa_index; - uint8_t adv_directed; /* note: can be 1 bit */ uint8_t adv_txadd; /* note: can be 1 bit */ uint8_t adv_rxadd; /* note: can be 1 bit */ int8_t adv_txpwr; @@ -103,9 +101,9 @@ struct ble_ll_adv_sm uint8_t *conn_comp_ev; struct os_event adv_txdone_ev; struct ble_ll_sched_item adv_sch; + uint16_t props; #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; - uint16_t props; /* TODO */ uint16_t duration; /* TODO */ uint8_t events; /* TODO */ uint16_t did; /* TODO */ @@ -152,7 +150,7 @@ ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm) ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, advsm->adva, 1); - if (advsm->adv_directed) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, advsm->initiator_addr, 0); if (ble_ll_is_rpa(advsm->initiator_addr, 1)) { @@ -248,45 +246,29 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) adv_data_len = advsm->adv_len; pdulen = BLE_DEV_ADDR_LEN + adv_data_len; - /* Must be an advertising type! */ - switch (advsm->adv_type) { - case BLE_HCI_ADV_TYPE_ADV_IND: - pdu_type = BLE_ADV_PDU_TYPE_ADV_IND; - -#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1) - pdu_type |= BLE_ADV_PDU_HDR_CHSEL; -#endif - break; - - case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: - pdu_type = BLE_ADV_PDU_TYPE_ADV_NONCONN_IND; - break; - - case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: - pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND; - break; - - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { pdu_type = BLE_ADV_PDU_TYPE_ADV_DIRECT_IND; #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1) pdu_type |= BLE_ADV_PDU_HDR_CHSEL; #endif - adv_data_len = 0; - pdulen = BLE_ADV_DIRECT_IND_LEN; if (advsm->adv_rxadd) { pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; } - break; - /* Set these to avoid compiler warnings */ - default: - pdulen = 0; - pdu_type = 0; - adv_data_len = 0xFF; - break; + adv_data_len = 0; + pdulen = BLE_ADV_DIRECT_IND_LEN; + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + pdu_type = BLE_ADV_PDU_TYPE_ADV_IND; + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1) + pdu_type |= BLE_ADV_PDU_HDR_CHSEL; +#endif + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND; + } else { + pdu_type = BLE_ADV_PDU_TYPE_ADV_NONCONN_IND; } /* An invalid advertising data length indicates a memory overwrite */ @@ -309,7 +291,7 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) dptr += BLE_DEV_ADDR_LEN; /* For ADV_DIRECT_IND add inita */ - if (advsm->adv_directed) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { memcpy(dptr, advsm->initiator_addr, BLE_DEV_ADDR_LEN); } @@ -469,12 +451,13 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) #endif /* Set phy mode based on type of advertisement */ - if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { - end_trans = BLE_PHY_TRANSITION_NONE; - ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); - } else { + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) || + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { end_trans = BLE_PHY_TRANSITION_TX_RX; ble_phy_set_txend_cb(NULL, NULL); + } else { + end_trans = BLE_PHY_TRANSITION_NONE; + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); } /* Get an advertising mbuf (packet header) */ @@ -531,17 +514,10 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) /* Set end time to maximum time this schedule item may take */ max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); - switch (advsm->adv_type) { - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; - break; - case BLE_HCI_ADV_TYPE_ADV_IND: - case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { max_usecs += BLE_LL_SCHED_ADV_MAX_USECS; - break; - default: - break; } /* @@ -592,6 +568,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) uint16_t adv_itvl_max; uint16_t min_itvl; struct ble_ll_adv_sm *advsm; + uint16_t props; /* If already enabled, we return an error */ if (instance >= BLE_LL_ADV_INSTANCES) { @@ -624,31 +601,37 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) /* Assume min interval based on low duty cycle/indirect advertising */ min_itvl = BLE_LL_ADV_ITVL_MIN; - advsm->adv_directed = 0; switch (adv_type) { - /* Fall through intentional */ 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); + /* Ignore min/max interval */ min_itvl = 0; adv_itvl_min = 0; adv_itvl_max = 0; + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR ; + break; case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: adv_filter_policy = BLE_HCI_ADV_FILT_NONE; - advsm->adv_directed = 1; memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN); + + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR ; break; case BLE_HCI_ADV_TYPE_ADV_IND: - /* Nothing to do */ + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND; break; case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: + min_itvl = 0; + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN; + break; case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: min_itvl = 0; + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN; break; default: - /* This will cause an invalid parameter error */ - min_itvl = 0xFFFF; - break; + return BLE_ERR_INV_HCI_CMD_PARMS; } /* Make sure interval minimum is valid for the advertising type */ @@ -727,7 +710,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) advsm->adv_chanmask = adv_chanmask; advsm->adv_itvl_min = adv_itvl_min; advsm->adv_itvl_max = adv_itvl_max; - advsm->adv_type = adv_type; + advsm->props = props; return 0; } @@ -829,10 +812,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) * Get an event with which to send the connection complete event if * this is connectable */ - switch (advsm->adv_type) { - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: - case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: - case BLE_HCI_ADV_TYPE_ADV_IND: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { /* We expect this to be NULL but if not we wont allocate one... */ if (advsm->conn_comp_ev == NULL) { evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); @@ -841,9 +821,6 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) } advsm->conn_comp_ev = evbuf; } - break; - default: - break; } /* Set advertising address */ @@ -860,7 +837,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) } memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN); - if (advsm->adv_directed) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { memcpy(advsm->initiator_addr, advsm->peer_addr, BLE_DEV_ADDR_LEN); if (advsm->peer_addr_type & 1) { advsm->adv_rxadd = 1; @@ -878,7 +855,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) advsm->adv_enabled = 1; /* Determine the advertising interval we will use */ - if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { /* Set it to max. allowed for high duty cycle advertising */ advsm->adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX; } else { @@ -1329,8 +1306,7 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) return BLE_ERR_INV_HCI_CMD_PARMS; } - advsm->adv_directed = props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; - if (advsm->adv_directed) { + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { memcpy(advsm->peer_addr, &cmdbuf[12], BLE_DEV_ADDR_LEN); } @@ -1478,9 +1454,7 @@ ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance) * Core Spec Vol. 2 Part E 7.8.52 */ if (advsm->adv_enabled && - (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD || - advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD || - advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_IND)) { + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE)) { return BLE_ERR_CMD_DISALLOWED; } @@ -1745,8 +1719,7 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, * Only accept connect requests from the desired address if we * are doing directed advertising */ - if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) || - (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { ident_addr = inita; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) @@ -1936,16 +1909,13 @@ ble_ll_adv_rx_isr_start(uint8_t pdu_type) advsm = g_ble_ll_cur_adv_sm; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { /* Only accept scan requests if we are indirect adv or scan adv */ - if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND) || - (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_IND)) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { rc = 1; } } else { /* Only accept connect requests if connectable advertising event */ if (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ) { - if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) || - (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD) || - (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_IND)) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { rc = 0; } } @@ -2012,11 +1982,11 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) * add the random advDelay as the scheduling code will do that. */ itvl = advsm->adv_itvl_usecs; - if (advsm->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + max_delay_ticks = 0; + } else { max_delay_ticks = os_cputime_usecs_to_ticks(BLE_LL_ADV_DELAY_MS_MAX * 1000); - } else { - max_delay_ticks = 0; } tick_itvl = os_cputime_usecs_to_ticks(itvl); advsm->adv_event_start_time += tick_itvl; @@ -2066,7 +2036,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) * Stop high duty cycle directed advertising if we have been doing * it for more than 1.28 seconds */ - if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { if (advsm->adv_pdu_start_time >= advsm->adv_dir_hd_end_time) { /* Disable advertising */ advsm->adv_enabled = 0; From ec76874b4825b08eb2a928a506c6ef831cf13278 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:26 +0200 Subject: [PATCH 13/27] nimble/controller: Add support for non-connectable advertising This allows to advertise with ADV_EXT_IND and AUX_ADV_IND PDUs using supported PHYs. AUX_ADV_IND are scheduled separately and ADV_EXT_IND use its start time for offset calculation. This is initial support and not all options are supported yet. X-Original-Commit: 965fe93735116db042f016bebf969097cd6a2987 --- nimble/controller/include/controller/ble_ll.h | 28 ++ .../include/controller/ble_ll_adv.h | 3 - .../include/controller/ble_ll_sched.h | 5 +- nimble/controller/src/ble_ll_adv.c | 457 +++++++++++++++++- nimble/controller/src/ble_ll_sched.c | 6 +- 5 files changed, 471 insertions(+), 28 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 9bf3bcaaa..155db1c5d 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -270,6 +270,34 @@ struct ble_dev_addr #define BLE_ADV_PDU_TYPE_AUX_SCAN_REQ BLE_ADV_PDU_TYPE_SCAN_REQ #define BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP (8) +#define BLE_ADV_PDU_TYPE_AUX_SCAN_REQ BLE_ADV_PDU_TYPE_SCAN_REQ +#define BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ BLE_ADV_PDU_TYPE_CONNECT_REQ +#define BLE_ADV_PDU_TYPE_ADV_EXT_IND (7) +#define BLE_ADV_PDU_TYPE_AUX_ADV_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_SCAN_RSP BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_SYNC_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_CHAIN_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP (8) + +#define BLE_LL_EXT_ADV_ADVA_BIT (0) +#define BLE_LL_EXT_ADV_TARGETA_BIT (1) +#define BLE_LL_EXT_ADV_RFU_BIT (2) +#define BLE_LL_EXT_ADV_DATA_INFO_BIT (3) +#define BLE_LL_EXT_ADV_AUX_PTR_BIT (4) +#define BLE_LL_EXT_ADV_SYNC_INFO_BIT (5) +#define BLE_LL_EXT_ADV_TX_POWER_BIT (6) + +#define BLE_LL_EXT_ADV_ADVA_SIZE (6) +#define BLE_LL_EXT_ADV_TARGETA_SIZE (6) +#define BLE_LL_EXT_ADV_DATA_INFO_SIZE (2) +#define BLE_LL_EXT_ADV_AUX_PTR_SIZE (3) +#define BLE_LL_EXT_ADV_SYNC_INFO_SIZE (18) +#define BLE_LL_EXT_ADV_TX_POWER_SIZE (1) + +#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00) +#define BLE_LL_EXT_ADV_MODE_CONN (0x01) +#define BLE_LL_EXT_ADV_MODE_SCAN (0x02) + /* If Channel Selection Algorithm #2 is supported */ #define BLE_ADV_PDU_HDR_CHSEL (0x20) diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index b0764c538..ad69232ff 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -165,9 +165,6 @@ void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, /* Boolean function denoting whether or not the whitelist can be changed */ int ble_ll_adv_can_chg_whitelist(void); -/* Called when an advertising event has been scheduled */ -void ble_ll_adv_scheduled(struct ble_ll_adv_sm *, uint32_t sch_start); - /* * Called when an advertising event has been removed from the scheduler * without being run. diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h index 4aade28a7..4b9cb14d0 100644 --- a/nimble/controller/include/controller/ble_ll_sched.h +++ b/nimble/controller/include/controller/ble_ll_sched.h @@ -111,8 +111,11 @@ int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, /* Schedule a new slave connection */ int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm); +struct ble_ll_adv_sm; +typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm, uint32_t sch_start); + /* Schedule a new advertising event */ -int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch); +int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb); /* Reschedule an advertising event */ int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 2844190ce..7f4776acd 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -103,6 +103,11 @@ struct ble_ll_adv_sm struct ble_ll_sched_item adv_sch; uint16_t props; #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) + uint8_t adv_secondary; + uint8_t adv_secondary_chan; + uint32_t adv_secondary_start_time; + struct ble_ll_sched_item adv_secondary_sch; + uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; uint16_t duration; /* TODO */ uint8_t events; /* TODO */ @@ -230,12 +235,12 @@ ble_ll_adv_final_chan(struct ble_ll_adv_sm *advsm) } /** - * Create the advertising PDU + * Create the advertising legacy PDU * * @param advsm Pointer to advertisement state machine */ static void -ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) +ble_ll_adv_legacy_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) { uint8_t adv_data_len; uint8_t *dptr; @@ -301,6 +306,211 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) } } +/* TODO this shouldn't be needed + * + * PDU could be constructed before scheduling and held in mbuf until + * transmission + * + */ +static uint8_t +ble_ll_adv_secondary_pdu_len(struct ble_ll_adv_sm *advsm) +{ + uint8_t pdulen; + + pdulen = 2 + BLE_LL_PDU_HDR_LEN + BLE_LL_EXT_ADV_DATA_INFO_SIZE; + + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) && + advsm->adv_len) { + pdulen += advsm->adv_len; + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { + pdulen += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) || + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE)) { + pdulen += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + return pdulen; +} + +/** + * Create the advertising PDU + */ +static void +ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) +{ + uint8_t *dptr; + uint8_t pdulen; + uint8_t pdu_type; + + bool adva = false; + bool targeta = false; + bool adi = false; + bool aux_ptr = false; + bool tx_power = false; + bool adv_data = false; + uint8_t adv_mode; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint32_t offset; + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return ble_ll_adv_legacy_pdu_make(advsm, m); + } + + pdulen = 1; /* ext hdr len + AdvMode */ + + ext_hdr_len = 0; + + /* TODO for now always add flags */ + ext_hdr_len += 1; + ext_hdr_flags = 0; + + + if (advsm->adv_secondary) { + pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND; + + adi = true; + adva = true; + + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) && + advsm->adv_len) { + adv_data = true; + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { + tx_power = true; + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + targeta = true; + } + + } else { + /* only ADV_EXT_IND goes on primary advertising channels */ + pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND; + + /* TODO in some cases we could avoid auxiliary packet */ + aux_ptr = true; + adi = true; + } + + adv_mode = 0; + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + adv_mode |= BLE_LL_EXT_ADV_MODE_SCAN; + } + + if (adva) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (targeta) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (adi) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + if (aux_ptr) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (tx_power) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + /* TODO ACAD */ + + if (adv_data) { + pdulen += advsm->adv_len; + } + + /* Set TxAdd to random if needed. */ + if (advsm->adv_txadd) { + pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + pdulen += ext_hdr_len; + + /* Set the PDU length in the state machine (includes header) */ + advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN; + + ble_ll_mbuf_init(m, pdulen, pdu_type); + + /* Construct advertisement */ + dptr = m->om_data; + + /* ext hdr len and adv mode */ + dptr[0] = ext_hdr_len | (adv_mode << 6); + dptr += 1; + + /* ext hdr flags */ + dptr[0] = ext_hdr_flags; + dptr += 1; + + if (adva) { + memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (targeta) { + memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE); + dptr += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (adi) { + dptr[0] = advsm->did & 0x00ff; + dptr[1] = advsm->did >> 8; + dptr[1] |= (advsm->sid) << 4; + + dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + if (aux_ptr) { + offset = advsm->adv_secondary_start_time - os_cputime_get32() + 1; + + /* in usecs */ + offset = os_cputime_ticks_to_usecs(offset); + + dptr[0] = advsm->adv_secondary_chan; + + if (offset > 245700) { + dptr[0] |= 0x80; + offset = offset / 300; + } else { + offset = offset / 30; + } + + dptr[1] = (offset & 0x000000ff); + dptr[2] = ((offset >> 8) & 0x0000001f) | (advsm->sec_phy - 1) << 5; //TODO; + + dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (tx_power) { + dptr[0] = advsm->adv_txpwr; + dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + if (adv_data) { + memcpy(dptr, advsm->adv_data, advsm->adv_len); + dptr += advsm->adv_len; + } +} + /** * Create a scan response PDU * @@ -468,10 +678,15 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) goto adv_tx_done; } + advsm->adv_secondary = 0; ble_ll_adv_pdu_make(advsm, adv_pdu); #if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); + } else { + ble_phy_mode_set(advsm->pri_phy, advsm->pri_phy); + } #endif /* Transmit advertisement */ @@ -513,7 +728,12 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) sch->sched_type = BLE_LL_SCHED_TYPE_ADV; /* Set end time to maximum time this schedule item may take */ - max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); + } else { + max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, advsm->pri_phy); + } + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { @@ -532,6 +752,142 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) os_cputime_usecs_to_ticks(max_usecs); } +static int +ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) +{ + int rc; + uint8_t end_trans; + uint32_t txstart; + struct ble_ll_adv_sm *advsm; + struct os_mbuf *adv_pdu; + + /* Get the state machine for the event */ + advsm = (struct ble_ll_adv_sm *)sch->cb_arg; + + /* Set the current advertiser */ + g_ble_ll_cur_adv_sm = advsm; + + /* Set the power */ + ble_phy_txpwr_set(advsm->adv_txpwr); + + /* Set channel */ + rc = ble_phy_setchan(advsm->adv_secondary_chan, BLE_ACCESS_ADDR_ADV, + BLE_LL_CRCINIT_ADV); + assert(rc == 0); + + /* Set transmit start time. */ + txstart = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_tx_set_start_time(txstart, sch->remainder); + if (rc) { + STATS_INC(ble_ll_stats, adv_late_starts); + goto adv_tx_done; + } + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) + /* XXX: automatically do this in the phy based on channel? */ + ble_phy_encrypt_disable(); +#endif + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) + advsm->adv_rpa_index = -1; + if (ble_ll_resolv_enabled()) { + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + + /* Set phy mode based on type of advertisement */ + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) || + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + end_trans = BLE_PHY_TRANSITION_TX_RX; + ble_phy_set_txend_cb(NULL, NULL); + } else { + end_trans = BLE_PHY_TRANSITION_NONE; + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); + } + + /* Get an advertising mbuf (packet header) */ + adv_pdu = os_msys_get_pkthdr(BLE_ADV_MAX_PKT_LEN, + sizeof(struct ble_mbuf_hdr)); + if (!adv_pdu) { + ble_phy_disable(); + goto adv_tx_done; + } + + advsm->adv_secondary = 1; + ble_ll_adv_pdu_make(advsm, adv_pdu); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); +#endif + + /* Transmit advertisement */ + rc = ble_phy_tx(adv_pdu, end_trans); + os_mbuf_free_chain(adv_pdu); + if (rc) { + goto adv_tx_done; + } + + /* Enable/disable whitelisting based on filter policy */ + if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) { + ble_ll_whitelist_enable(); + } else { + ble_ll_whitelist_disable(); + } + + /* Set link layer state to advertising */ + ble_ll_state_set(BLE_LL_STATE_ADV); + + /* Count # of adv. sent */ + STATS_INC(ble_ll_stats, adv_txg); + + return BLE_LL_SCHED_STATE_RUNNING; + +adv_tx_done: + ble_ll_adv_tx_done(advsm); + return BLE_LL_SCHED_STATE_DONE; +} + +static void +ble_ll_adv_secondary_set_sched(struct ble_ll_adv_sm *advsm) +{ + uint32_t max_usecs; + struct ble_ll_sched_item *sch; + + sch = &advsm->adv_secondary_sch; + sch->cb_arg = advsm; + sch->sched_cb = ble_ll_adv_secondary_tx_start_cb; + sch->sched_type = BLE_LL_SCHED_TYPE_ADV; + + /* TODO we could use CSA2 for this + * (will be needed for periodic advertising anyway) + */ + advsm->adv_secondary_chan = rand() % BLE_PHY_NUM_DATA_CHANS; + + /* Set end time to maximum time this schedule item may take */ + max_usecs = ble_ll_pdu_tx_time_get(ble_ll_adv_secondary_pdu_len(advsm), + advsm->sec_phy); + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + max_usecs += BLE_LL_SCHED_ADV_MAX_USECS; + } + + /* + * XXX: For now, just schedule some additional time so we insure we have + * enough time to do everything we want. + */ + max_usecs += XCVR_PROC_DELAY_USECS; + + sch->start_time = advsm->adv_secondary_start_time - g_ble_ll_sched_offset_ticks; + sch->remainder = 0; + sch->end_time = advsm->adv_secondary_start_time + + os_cputime_usecs_to_ticks(max_usecs); +} + + /** * Called when advertising need to be halted. This normally should not be called * and is only called when a scheduled item executes but advertising is still @@ -731,6 +1087,10 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) /* Remove any scheduled advertising items */ ble_ll_sched_rmv_elem(&advsm->adv_sch); + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + ble_ll_sched_rmv_elem(&advsm->adv_secondary_sch); + } + /* Set to standby if we are no longer advertising */ OS_ENTER_CRITICAL(sr); #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) @@ -771,6 +1131,28 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) } } +static void +ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) +{ + /* The event start time is when we start transmission of the adv PDU */ + advsm->adv_event_start_time = sch_start + g_ble_ll_sched_offset_ticks; + advsm->adv_pdu_start_time = advsm->adv_event_start_time; + + /* + * Set the time at which we must end directed, high-duty cycle advertising. + * Does not matter that we calculate this value if we are not doing high + * duty cycle advertising. + */ + advsm->adv_dir_hd_end_time = advsm->adv_event_start_time + + os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000); +} + +static void +ble_ll_adv_secondary_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) +{ + advsm->adv_secondary_start_time = sch_start; +} + /** * Start the advertising state machine. This is called when the host sends * the "enable advertising" command and is not called again while in the @@ -885,28 +1267,22 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) * times to the earliest possible start/end. */ ble_ll_adv_set_sched(advsm); - ble_ll_sched_adv_new(&advsm->adv_sch); + ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled); + + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + /* TODO calculate this 5000 based on ext_adv sched time and channel used */ + advsm->adv_secondary_start_time = advsm->adv_pdu_start_time + + os_cputime_usecs_to_ticks(2000) + + os_cputime_usecs_to_ticks(300); + + ble_ll_adv_secondary_set_sched(advsm); + ble_ll_sched_adv_new(&advsm->adv_secondary_sch, + ble_ll_adv_secondary_scheduled); + } return BLE_ERR_SUCCESS; } -void -ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) -{ - /* The event start time is when we start transmission of the adv PDU */ - advsm->adv_event_start_time = sch_start + g_ble_ll_sched_offset_ticks; - - advsm->adv_pdu_start_time = advsm->adv_event_start_time; - - /* - * Set the time at which we must end directed, high-duty cycle advertising. - * Does not matter that we calculate this value if we are not doing high - * duty cycle advertising. - */ - advsm->adv_dir_hd_end_time = advsm->adv_event_start_time + - os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000); -} - /** * Called when the LE HCI command read advertising channel tx power command * has been received. Returns the current advertising transmit power. @@ -1932,6 +2308,37 @@ ble_ll_adv_rx_isr_start(uint8_t pdu_type) return rc; } +static void +ble_ll_adv_secondary_done(struct ble_ll_adv_sm *advsm) +{ + int rc; + + ble_ll_sched_rmv_elem(&advsm->adv_secondary_sch); + os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + + /* Check if we need to resume scanning */ + ble_ll_scan_chk_resume(); + + /* TODO calculate this 5000 based on ext_adv sched time and channel used */ + advsm->adv_secondary_start_time = advsm->adv_pdu_start_time + + os_cputime_usecs_to_ticks(5000) + + os_cputime_usecs_to_ticks(300); + + ble_ll_adv_secondary_set_sched(advsm); + + /* + * In the unlikely event we cant reschedule this, just post a done + * event and we will reschedule the next advertising event + */ + /* Reschedule advertising event */ + rc = ble_ll_sched_adv_reschedule(&advsm->adv_secondary_sch, + &advsm->adv_secondary_start_time, + os_cputime_usecs_to_ticks(5000)); + if (rc) { + os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + } +} + /** * Called when an advertising event is over. * @@ -1954,8 +2361,14 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) assert(advsm->adv_enabled); + if (advsm->adv_secondary) { + ble_ll_adv_secondary_done(advsm); + return; + } + /* Remove the element from the schedule if it is still there. */ ble_ll_sched_rmv_elem(&advsm->adv_sch); + os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); /* diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 0b7d78dcb..2ffb1cec5 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -595,7 +595,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) } int -ble_ll_sched_adv_new(struct ble_ll_sched_item *sch) +ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb) { int rc; os_sr_t sr; @@ -646,7 +646,9 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch) sch = TAILQ_FIRST(&g_ble_ll_sched_q); } - ble_ll_adv_scheduled((struct ble_ll_adv_sm *)orig->cb_arg, adv_start); + if (cb) { + cb((struct ble_ll_adv_sm *)orig->cb_arg, adv_start); + } #ifdef BLE_XCVR_RFCLK if (orig == sch) { From 80075eb4797481cbde918957a51f39c338e12a1a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:26 +0200 Subject: [PATCH 14/27] nimble/controller: Add support for sending AUX_SCAN_RSP If AUX_SCAN_REQ is received then reply with AUX_SCAN_RSP. X-Original-Commit: bb8d1aab0142d3fe9bb8746548a854ea2ba6131f --- nimble/controller/src/ble_ll_adv.c | 93 ++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 6 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 7f4776acd..7f8f34cb6 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -511,13 +511,8 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) } } -/** - * Create a scan response PDU - * - * @param advsm - */ static struct os_mbuf * -ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm) +ble_ll_adv_scan_rsp_legacy_pdu_make(struct ble_ll_adv_sm *advsm) { uint8_t scan_rsp_len; uint8_t *dptr; @@ -563,6 +558,85 @@ ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm) return m; } +/** + * Create a scan response PDU + * + * @param advsm + */ +static struct os_mbuf * +ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm) +{ + uint8_t *dptr; + uint8_t pdulen; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint8_t hdr; + struct os_mbuf *m; + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return ble_ll_adv_scan_rsp_legacy_pdu_make(advsm); + } + + /* ext hdr len + SCAN_RSP */ + pdulen = 1 + advsm->scan_rsp_len; + + /* flags, adva and optional TX power */ + ext_hdr_len = 1 + BLE_LL_EXT_ADV_ADVA_SIZE; + ext_hdr_flags = (1 << BLE_LL_EXT_ADV_ADVA_BIT); + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { + ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + pdulen += ext_hdr_len; + + /* Obtain scan response buffer */ + m = os_msys_get_pkthdr(pdulen, sizeof(struct ble_mbuf_hdr)); + if (!m) { + return NULL; + } + + /* Set BLE transmit header */ + hdr = BLE_ADV_PDU_TYPE_AUX_SCAN_RSP; + if (advsm->adv_txadd) { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + ble_ll_mbuf_init(m, pdulen, hdr); + + /* Construct scan response */ + dptr = m->om_data; + + /* ext hdr len and adv mode (00b) */ + dptr[0] = ext_hdr_len; + dptr += 1; + + /* ext hdr flags */ + dptr[0] = ext_hdr_flags; + dptr += 1; + + /* + * The adva in this packet will be the same one that was being advertised + * and is based on the peer identity address in the set advertising + * parameters. If a different peer sends us a scan request (for some reason) + * we will reply with an adva that was not generated based on the local irk + * of the peer sending the scan request. + */ + memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { + dptr[0] = advsm->adv_txpwr; + dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + memcpy(dptr, advsm->scan_rsp_data, advsm->scan_rsp_len); + dptr += advsm->scan_rsp_len; + + return m; +} + /** * Called to indicate the advertising event is over. * @@ -2076,6 +2150,13 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, uint8_t *inita; uint8_t *ident_addr; + /* Don't create connection if AUX_CONNECT_RSP was not send */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { + return 0; + } + } + /* Check filter policy. */ valid = 0; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) From 79e2ff47724f4920f71d653cbfd6b20f872a8981 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:26 +0200 Subject: [PATCH 15/27] nimble/controller: Send LE Scan Request Received Event Notify host about SCAN_REQ received if event is enabled. X-Original-Commit: 5524d9bca54e9fc83d68be314fe39c020546d17e --- .../include/controller/ble_ll_ctrl.h | 2 ++ nimble/controller/src/ble_ll_adv.c | 6 +++++ nimble/controller/src/ble_ll_hci_ev.c | 24 +++++++++++++++++++ nimble/include/nimble/hci_common.h | 3 +++ 4 files changed, 35 insertions(+) diff --git a/nimble/controller/include/controller/ble_ll_ctrl.h b/nimble/controller/include/controller/ble_ll_ctrl.h index 14d570925..8f1618996 100644 --- a/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/nimble/controller/include/controller/ble_ll_ctrl.h @@ -270,6 +270,8 @@ int ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm); int ble_ll_hci_ev_hw_err(uint8_t hw_err); void ble_ll_hci_ev_databuf_overflow(void); void ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm); +void ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, + uint8_t peer_addr_type); 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); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 7f8f34cb6..28c7c1d57 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -2027,6 +2027,7 @@ ble_ll_adv_multi_adv_cmd(uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, } #endif + /** * Called when the LL receives a scan request or connection request * @@ -2112,6 +2113,11 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) /* Setup to transmit the scan response if appropriate */ rc = -1; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { + if (advsm->scan_req_notif) { + ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer, + peer_addr_type); + } + scan_rsp = ble_ll_adv_scan_rsp_pdu_make(advsm); if (scan_rsp) { /* XXX TODO: assume we do not need to change phy mode */ diff --git a/nimble/controller/src/ble_ll_hci_ev.c b/nimble/controller/src/ble_ll_hci_ev.c index bd7b8ad2a..9ee374215 100644 --- a/nimble/controller/src/ble_ll_hci_ev.c +++ b/nimble/controller/src/ble_ll_hci_ev.c @@ -293,6 +293,30 @@ ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm) } #endif +/** + * Sends the LE Scan Request Received event + * + */ +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; + + 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); + } + } +} + /** * Send a PHY update complete event * diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 66a04de69..02be9e29d 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -723,6 +723,9 @@ extern "C" { /* LE PHY update complete event (sub event 0x0C) */ #define BLE_HCI_LE_PHY_UPD_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) From acc80719988d8704bc156f77452c8bf100ba1382 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 9 Jun 2017 12:51:26 +0200 Subject: [PATCH 16/27] nimble/controller: Reply with AUX_CONN_RSP for connection request This allows to create connection while advertising using Extended Advertising PDUs. CSA2 is mandatory for this type of connection so ChSel bit is RFU and is not used. X-Original-Commit: 3f280f04d8e45985796ba2f8868b2f43b2e3627d --- nimble/controller/src/ble_ll_adv.c | 114 +++++++++++++++++++++-- nimble/controller/src/ble_ll_conn.c | 7 +- nimble/controller/src/ble_ll_conn_priv.h | 2 +- 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 28c7c1d57..4e78ca320 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -116,6 +116,7 @@ struct ble_ll_adv_sm uint8_t sec_phy; /* TODO */ uint8_t sid; /* TODO */ uint8_t scan_req_notif; /* TODO */ + uint8_t conn_rsp_tx; #endif }; @@ -637,6 +638,66 @@ ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm) return m; } +/** + * Create a AUX connect response PDU + * + * @param advsm + */ +static struct os_mbuf * +ble_ll_adv_aux_conn_rsp_pdu_make(struct ble_ll_adv_sm *advsm, uint8_t *peer, + uint8_t rxadd) +{ + uint8_t *dptr; + uint8_t pdulen; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint8_t hdr; + struct os_mbuf *m; + + /* ext hdr len */ + pdulen = 1; + + /* flags,AdvA and TargetA */ + ext_hdr_len = 1 + BLE_LL_EXT_ADV_ADVA_SIZE + BLE_LL_EXT_ADV_TARGETA_SIZE; + ext_hdr_flags = (1 << BLE_LL_EXT_ADV_ADVA_BIT); + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); + + pdulen += ext_hdr_len; + + /* Obtain scan response buffer */ + m = os_msys_get_pkthdr(pdulen, sizeof(struct ble_mbuf_hdr)); + if (!m) { + return NULL; + } + + /* Set BLE transmit header */ + hdr = BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP | rxadd; + if (advsm->adv_txadd) { + hdr |= BLE_ADV_PDU_HDR_TXADD_MASK; + } + + ble_ll_mbuf_init(m, pdulen, hdr); + + /* Construct connect response */ + dptr = m->om_data; + + /* ext hdr len and adv mode (00b) */ + dptr[0] = ext_hdr_len; + dptr += 1; + + /* ext hdr flags */ + dptr[0] = ext_hdr_flags; + dptr += 1; + + memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + + memcpy(dptr, peer, BLE_LL_EXT_ADV_TARGETA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + + return m; +} + /** * Called to indicate the advertising event is over. * @@ -2052,7 +2113,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) uint8_t *peer; struct ble_mbuf_hdr *ble_hdr; struct ble_ll_adv_sm *advsm; - struct os_mbuf *scan_rsp; + struct os_mbuf *rsp; /* See if adva in the request (scan or connect) matches what we sent */ advsm = g_ble_ll_cur_adv_sm; @@ -2112,22 +2173,51 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) /* Setup to transmit the scan response if appropriate */ rc = -1; + if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { if (advsm->scan_req_notif) { ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer, peer_addr_type); } - scan_rsp = ble_ll_adv_scan_rsp_pdu_make(advsm); - if (scan_rsp) { + rsp = ble_ll_adv_scan_rsp_pdu_make(advsm); + if (rsp) { /* XXX TODO: assume we do not need to change phy mode */ ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); - rc = ble_phy_tx(scan_rsp, BLE_PHY_TRANSITION_NONE); + rc = ble_phy_tx(rsp, BLE_PHY_TRANSITION_NONE); if (!rc) { ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; STATS_INC(ble_ll_stats, scan_rsp_txg); } - os_mbuf_free_chain(scan_rsp); + os_mbuf_free_chain(rsp); + } + } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ) { + /* + * Only accept connect requests from the desired address if we + * are doing directed advertising + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + if (memcmp(advsm->peer_addr, peer, BLE_DEV_ADDR_LEN)) { + return -1; + } + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return -1; + } + + /* use remote address used over the air */ + rsp = ble_ll_adv_aux_conn_rsp_pdu_make(advsm, + rxbuf + BLE_LL_PDU_HDR_LEN, + rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); + if (rsp) { + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); + rc = ble_phy_tx(rsp, BLE_PHY_TRANSITION_NONE); + if (!rc) { + advsm->conn_rsp_tx = 1; + //STATS_INC(ble_ll_stats, scan_rsp_txg); TODO + } + os_mbuf_free_chain(rsp); } } @@ -2219,9 +2309,13 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, #endif /* Try to start slave connection. If successful, stop advertising */ - valid = ble_ll_conn_slave_start(rxbuf, addr_type, hdr); + valid = ble_ll_conn_slave_start(rxbuf, addr_type, hdr, + !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); if (valid) { - ble_ll_adv_sm_stop(advsm); + /* stop advertising only if not transmitting connection response */ + if (!advsm->conn_rsp_tx) { + ble_ll_adv_sm_stop(advsm); + } } } @@ -2448,6 +2542,12 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) assert(advsm->adv_enabled); + /* stop advertising this was due to transmitting connection response */ + if (advsm->conn_rsp_tx) { + ble_ll_adv_sm_stop(advsm); + return; + } + if (advsm->adv_secondary) { ble_ll_adv_secondary_done(advsm); return; diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 67a8f209a..438484495 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -3714,7 +3714,8 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap) * @return 0: connection not started; 1 connecton started */ int -ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr) +ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr, + bool force_csa2) { int rc; uint32_t temp; @@ -3804,7 +3805,9 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr) /* Start the connection state machine */ connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE; ble_ll_conn_sm_new(connsm); - ble_ll_conn_set_csa(connsm, rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK); + + ble_ll_conn_set_csa(connsm, + force_csa2 || (rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK)); /* Set initial schedule callback */ connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index 1e169fc67..60f7aa273 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -112,7 +112,7 @@ void ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm, /* Advertising interface */ int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, - struct ble_mbuf_hdr *rxhdr); + struct ble_mbuf_hdr *rxhdr, bool force_csa2); /* Link Layer interface */ void ble_ll_conn_module_init(void); From 4bb1e1d25a5f9d1cc5ad24a28327bbe26c4b91e0 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 13 Jun 2017 17:36:15 +0200 Subject: [PATCH 17/27] nimble/controller: Add support for sending Set Terminated event Currently this is done only for connection complete. X-Original-Commit: e2eb1a0fdd7948b854ad4c341d3cad0f94ede25a --- .../include/controller/ble_ll_ctrl.h | 2 + nimble/controller/src/ble_ll_adv.c | 40 ++++++++++++++++++- nimble/controller/src/ble_ll_hci_ev.c | 25 ++++++++++++ nimble/include/nimble/ble.h | 3 ++ nimble/include/nimble/hci_common.h | 3 ++ 5 files changed, 71 insertions(+), 2 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_ctrl.h b/nimble/controller/include/controller/ble_ll_ctrl.h index 8f1618996..3a9a8c7b7 100644 --- a/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/nimble/controller/include/controller/ble_ll_ctrl.h @@ -272,6 +272,8 @@ void ble_ll_hci_ev_databuf_overflow(void); void ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm); void ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, uint8_t peer_addr_type); +void ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, + uint16_t conn_handle, uint8_t events); 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); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 4e78ca320..ce2fed8bb 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -110,7 +110,8 @@ struct ble_ll_adv_sm uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; uint16_t duration; /* TODO */ - uint8_t events; /* TODO */ + uint8_t events_max; + uint8_t events; uint16_t did; /* TODO */ uint8_t pri_phy; /* TODO */ uint8_t sec_phy; /* TODO */ @@ -1459,7 +1460,8 @@ ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, rc = BLE_ERR_SUCCESS; if (enable == 1) { advsm->duration = duration; - advsm->events = events; + advsm->events_max = events; + advsm->events = 0; /* If already enabled, do nothing */ if (!advsm->adv_enabled) { @@ -2500,6 +2502,16 @@ ble_ll_adv_secondary_done(struct ble_ll_adv_sm *advsm) /* Check if we need to resume scanning */ ble_ll_scan_chk_resume(); + if (advsm->events_max && (advsm->events >= advsm->events_max)) { + ble_ll_hci_ev_send_adv_set_terminated(BLE_RR_LIMIT_REACHED, + advsm->adv_instance, 0, + advsm->events); + /* Disable advertising */ + advsm->adv_enabled = 0; + ble_ll_scan_chk_resume(); + return; + } + /* TODO calculate this 5000 based on ext_adv sched time and channel used */ advsm->adv_secondary_start_time = advsm->adv_pdu_start_time + os_cputime_usecs_to_ticks(5000) + @@ -2566,6 +2578,10 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) final_adv_chan = ble_ll_adv_final_chan(advsm); if (advsm->adv_chan == final_adv_chan) { + if (advsm->events_max) { + advsm->events++; + } + /* Check if we need to resume scanning */ ble_ll_scan_chk_resume(); @@ -2648,6 +2664,23 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) } } + if (advsm->events_max && (advsm->events >= advsm->events_max)) { + /* Legacy PDUs need to be stop here, for ext adv it will be stopped when + * AUX is done. + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + ble_ll_hci_ev_send_adv_set_terminated(BLE_RR_LIMIT_REACHED, + advsm->adv_instance, 0, + advsm->events); + + /* Disable advertising */ + advsm->adv_enabled = 0; + ble_ll_scan_chk_resume(); + } + + return; + } + /* We need to regenerate our RPA's if we have passed timeout */ #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) ble_ll_adv_chk_rpa_timeout(advsm); @@ -2746,6 +2779,9 @@ ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, advsm); + ble_ll_hci_ev_send_adv_set_terminated(0, advsm->adv_instance, + connsm->conn_handle, advsm->events); + #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1) ble_ll_hci_ev_le_csa(connsm); #endif diff --git a/nimble/controller/src/ble_ll_hci_ev.c b/nimble/controller/src/ble_ll_hci_ev.c index 9ee374215..37e7d23b0 100644 --- a/nimble/controller/src/ble_ll_hci_ev.c +++ b/nimble/controller/src/ble_ll_hci_ev.c @@ -317,6 +317,31 @@ ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, } } +/** + * Sends the LE Advertising Set Terminated event + * + */ +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; + + 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); + } + } +} + /** * Send a PHY update complete event * diff --git a/nimble/include/nimble/ble.h b/nimble/include/nimble/ble.h index 6db8cd901..5d674e3fd 100644 --- a/nimble/include/nimble/ble.h +++ b/nimble/include/nimble/ble.h @@ -208,6 +208,9 @@ enum ble_error_codes BLE_ERR_CONN_ESTABLISHMENT = 62, BLE_ERR_MAC_CONN_FAIL = 63, BLE_ERR_COARSE_CLK_ADJ = 64, + BLE_ERR_TYPE0_SUBMAP_NDEF = 65, + BLE_ERR_UNK_ADV_INDENT = 66, + BLE_RR_LIMIT_REACHED = 67, BLE_ERR_MAX = 255 }; diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 02be9e29d..4b8e4bfc9 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -723,6 +723,9 @@ extern "C" { /* LE PHY update complete event (sub event 0x0C) */ #define BLE_HCI_LE_PHY_UPD_LEN (6) +/* 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) From ff5d9601e02d447bc903ec5d186e85f6fce2b978 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 14 Jun 2017 15:21:28 +0200 Subject: [PATCH 18/27] nimble/controller: Remove leftover TODOs Those parameters are already handled. X-Original-Commit: 0aa5b8b5d1c799373a2567dfa9ab33f8a96f91d1 --- nimble/controller/src/ble_ll_adv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index ce2fed8bb..827b77431 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -112,11 +112,11 @@ struct ble_ll_adv_sm uint16_t duration; /* TODO */ uint8_t events_max; uint8_t events; - uint16_t did; /* TODO */ - uint8_t pri_phy; /* TODO */ - uint8_t sec_phy; /* TODO */ - uint8_t sid; /* TODO */ - uint8_t scan_req_notif; /* TODO */ + uint16_t did; + uint8_t pri_phy; + uint8_t sec_phy; + uint8_t sid; + uint8_t scan_req_notif; uint8_t conn_rsp_tx; #endif }; From 0f41b34a7c8c42fefce69fc24e11bf613524774c Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 20 Jun 2017 21:45:27 +0200 Subject: [PATCH 19/27] nimble/controller: Use flags for storing flag-like values RxAdd, TxAdd, Scan Request Notifications and Connection Response Sent are single bit values and can be stored as flags in common byte. X-Original-Commit: f9ad82d9311965da122d5c2e3d1e53dc019002d1 --- nimble/controller/src/ble_ll_adv.c | 61 +++++++++++++++++------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 827b77431..dffcce297 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -82,8 +82,7 @@ struct ble_ll_adv_sm uint8_t scan_rsp_len; uint8_t adv_pdu_len; int8_t adv_rpa_index; - uint8_t adv_txadd; /* note: can be 1 bit */ - uint8_t adv_rxadd; /* note: can be 1 bit */ + uint8_t flags; int8_t adv_txpwr; uint16_t adv_itvl_min; uint16_t adv_itvl_max; @@ -116,11 +115,14 @@ struct ble_ll_adv_sm uint8_t pri_phy; uint8_t sec_phy; uint8_t sid; - uint8_t scan_req_notif; - uint8_t conn_rsp_tx; #endif }; +#define BLE_LL_ADV_SM_FLAG_TX_ADD 0x01 +#define BLE_LL_ADV_SM_FLAG_RX_ADD 0x02 +#define BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF 0x04 +#define BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD 0x08 + /* The advertising state machine global object */ struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_LL_ADV_INSTANCES]; struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm; @@ -161,12 +163,12 @@ ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm) ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, advsm->initiator_addr, 0); if (ble_ll_is_rpa(advsm->initiator_addr, 1)) { - advsm->adv_rxadd = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD; } else { if (advsm->own_addr_type & 1) { - advsm->adv_rxadd = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD; } else { - advsm->adv_rxadd = 0; + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_RX_ADD; } } } @@ -174,12 +176,12 @@ ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm) /* May have to reset txadd bit */ if (ble_ll_is_rpa(advsm->adva, 1)) { - advsm->adv_txadd = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD; } else { if (advsm->own_addr_type & 1) { - advsm->adv_txadd = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD; } else { - advsm->adv_txadd = 0; + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_TX_ADD; } } } @@ -260,7 +262,7 @@ ble_ll_adv_legacy_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) pdu_type |= BLE_ADV_PDU_HDR_CHSEL; #endif - if (advsm->adv_rxadd) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; } @@ -285,7 +287,7 @@ ble_ll_adv_legacy_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN; /* Set TxAdd to random if needed. */ - if (advsm->adv_txadd) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; } @@ -441,7 +443,7 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) } /* Set TxAdd to random if needed. */ - if (advsm->adv_txadd) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; } @@ -536,7 +538,7 @@ ble_ll_adv_scan_rsp_legacy_pdu_make(struct ble_ll_adv_sm *advsm) /* Set BLE transmit header */ pdulen = BLE_DEV_ADDR_LEN + scan_rsp_len; hdr = BLE_ADV_PDU_TYPE_SCAN_RSP; - if (advsm->adv_txadd) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; } @@ -601,7 +603,7 @@ ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm) /* Set BLE transmit header */ hdr = BLE_ADV_PDU_TYPE_AUX_SCAN_RSP; - if (advsm->adv_txadd) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; } @@ -673,7 +675,7 @@ ble_ll_adv_aux_conn_rsp_pdu_make(struct ble_ll_adv_sm *advsm, uint8_t *peer, /* Set BLE transmit header */ hdr = BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP | rxadd; - if (advsm->adv_txadd) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { hdr |= BLE_ADV_PDU_HDR_TXADD_MASK; } @@ -1307,6 +1309,11 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) uint8_t *addr; uint8_t *evbuf; + /* only clear flags that are not set from HCI */ + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_TX_ADD; + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_RX_ADD; + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD; + /* * This is not in the specification. I will reject the command with a * command disallowed error if no random address has been sent by the @@ -1344,23 +1351,20 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) /* Set advertising address */ if ((advsm->own_addr_type & 1) == 0) { addr = g_dev_addr; - advsm->adv_txadd = 0; } else { #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) addr = advsm->adv_random_addr; #else addr = g_random_addr; #endif - advsm->adv_txadd = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD; } memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN); if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { memcpy(advsm->initiator_addr, advsm->peer_addr, BLE_DEV_ADDR_LEN); if (advsm->peer_addr_type & 1) { - advsm->adv_rxadd = 1; - } else { - advsm->adv_rxadd = 0; + advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD; } } @@ -1833,9 +1837,14 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) advsm->pri_phy = pri_phy; advsm->sec_phy = sec_phy; advsm->sid = sid; - advsm->scan_req_notif = scan_req_notif; advsm->props = props; + if (scan_req_notif) { + advsm->flags |= BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF; + } else { + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF; + } + rspbuf[0] = advsm->adv_txpwr; *rsplen = 1; @@ -2177,7 +2186,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) rc = -1; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { - if (advsm->scan_req_notif) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF) { ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer, peer_addr_type); } @@ -2216,7 +2225,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); rc = ble_phy_tx(rsp, BLE_PHY_TRANSITION_NONE); if (!rc) { - advsm->conn_rsp_tx = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD; //STATS_INC(ble_ll_stats, scan_rsp_txg); TODO } os_mbuf_free_chain(rsp); @@ -2315,7 +2324,7 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); if (valid) { /* stop advertising only if not transmitting connection response */ - if (!advsm->conn_rsp_tx) { + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { ble_ll_adv_sm_stop(advsm); } } @@ -2555,7 +2564,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) assert(advsm->adv_enabled); /* stop advertising this was due to transmitting connection response */ - if (advsm->conn_rsp_tx) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { ble_ll_adv_sm_stop(advsm); return; } From 1f616d3bc1bc75bce31d2d2010d34acf59dce8b7 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 20 Jun 2017 21:51:20 +0200 Subject: [PATCH 20/27] nimble/controller: Adjust slave anchor point based on PHY used Anchor point depends on PHY used and should be adjusted accordingly. X-Original-Commit: 7915aef02c5cd496a37401a52e53902c9ba79d70 --- nimble/controller/src/ble_ll_conn.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 438484495..e9e010492 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -2291,9 +2291,24 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) connsm->last_anchor_point = rxhdr->beg_cputime; usecs = rxhdr->rem_usecs + 1250 + - (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) + - ble_ll_pdu_tx_time_get(BLE_CONNECT_REQ_LEN, - connsm->phy_data.tx_phy_mode); + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) + + ble_ll_pdu_tx_time_get(BLE_CONNECT_REQ_LEN, + connsm->phy_data.rx_phy_mode); + + if (rxhdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { + switch (rxhdr->rxinfo.phy) { + case BLE_PHY_1M: + usecs += 1250; + break; + case BLE_PHY_CODED: + usecs += 2500; + break; + case BLE_PHY_2M: + default: + assert(0); + break; + } + } /* Anchor point is cputime. */ endtime = os_cputime_usecs_to_ticks(usecs); From 580c0dde9395e6e95c1b7b19a647c07dead53a53 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 26 Jun 2017 15:07:34 +0200 Subject: [PATCH 21/27] nimble/controller: Schedule AUX_ADV_IND based ADV_EXT_IND channel mask This gets rid of artificial delays in scheduling of AUX_ADV_IND. X-Original-Commit: 52314320d6bad451a6dcee304e4ebb7b96ca71d7 --- nimble/controller/include/controller/ble_ll.h | 1 + nimble/controller/src/ble_ll_adv.c | 36 +++++++++++++------ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 155db1c5d..051a8c840 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -203,6 +203,7 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; /* LL timing */ #define BLE_LL_IFS (150) /* usecs */ +#define BLE_LL_MAFS (300) /* usecs */ /* * BLE LL device address. Note that element 0 of the array is the LSB and diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index dffcce297..9f0722178 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1285,6 +1285,26 @@ ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000); } +static void +ble_ll_set_adv_secondary_start_time(struct ble_ll_adv_sm *advsm) +{ + static const uint8_t bits[8] = {0, 1, 1, 2, 1, 2, 2, 3}; + struct ble_ll_sched_item *sched = &advsm->adv_sch; + uint32_t ext_duration; + uint8_t chans; + + assert(advsm->adv_chanmask <= BLE_HCI_ADV_CHANMASK_DEF); + + chans = bits[advsm->adv_chanmask]; + + ext_duration = (int32_t)(sched->end_time - sched->start_time); + ext_duration += os_cputime_usecs_to_ticks(BLE_LL_IFS) * (chans -1); + + advsm->adv_secondary_start_time = advsm->adv_event_start_time + + ext_duration + + os_cputime_usecs_to_ticks(BLE_LL_MAFS); +} + static void ble_ll_adv_secondary_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) { @@ -1410,11 +1430,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled); if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - /* TODO calculate this 5000 based on ext_adv sched time and channel used */ - advsm->adv_secondary_start_time = advsm->adv_pdu_start_time + - os_cputime_usecs_to_ticks(2000) + - os_cputime_usecs_to_ticks(300); - + ble_ll_set_adv_secondary_start_time(advsm); ble_ll_adv_secondary_set_sched(advsm); ble_ll_sched_adv_new(&advsm->adv_secondary_sch, ble_ll_adv_secondary_scheduled); @@ -2521,21 +2537,19 @@ ble_ll_adv_secondary_done(struct ble_ll_adv_sm *advsm) return; } - /* TODO calculate this 5000 based on ext_adv sched time and channel used */ - advsm->adv_secondary_start_time = advsm->adv_pdu_start_time + - os_cputime_usecs_to_ticks(5000) + - os_cputime_usecs_to_ticks(300); - + ble_ll_set_adv_secondary_start_time(advsm); ble_ll_adv_secondary_set_sched(advsm); /* * In the unlikely event we cant reschedule this, just post a done * event and we will reschedule the next advertising event + * + * TODO should we give scheduler more flexibility with delay? */ /* Reschedule advertising event */ rc = ble_ll_sched_adv_reschedule(&advsm->adv_secondary_sch, &advsm->adv_secondary_start_time, - os_cputime_usecs_to_ticks(5000)); + os_cputime_usecs_to_ticks(0)); if (rc) { os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); } From 3ac3f417ac2c4793663cede47f1964543d0485f7 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 26 Jun 2017 16:07:16 +0200 Subject: [PATCH 22/27] nimble/controller: Add support for setting advertising TX power This allows host to set prefered TX power for advertising instance. Controller is allowed to ignore or adjust this value. X-Original-Commit: b6d919375838e6b03748725d47bb59aee94ece2f --- .../controller/include/controller/ble_phy.h | 3 +++ nimble/controller/src/ble_ll_adv.c | 10 +++++++- nimble/drivers/native/src/ble_phy.c | 23 +++++++++++++++++++ nimble/drivers/nrf51/src/ble_phy.c | 23 +++++++++++++++++++ nimble/drivers/nrf52/src/ble_phy.c | 23 +++++++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) diff --git a/nimble/controller/include/controller/ble_phy.h b/nimble/controller/include/controller/ble_phy.h index 734f9e940..e5267e4d5 100644 --- a/nimble/controller/include/controller/ble_phy.h +++ b/nimble/controller/include/controller/ble_phy.h @@ -121,6 +121,9 @@ int ble_phy_rssi_get(void); /* Set the transmit power */ int ble_phy_txpwr_set(int dbm); +/* Get highest allowed power from range */ +int ble_phy_txpower_round(int dbm); + /* Get the transmit power */ int ble_phy_txpwr_get(void); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 9f0722178..77f16ddd3 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1709,6 +1709,7 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) uint8_t sec_phy; uint8_t sid; uint8_t scan_req_notif; + int8_t tx_power; if (cmdbuf[0] >= BLE_LL_ADV_INSTANCES) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -1843,7 +1844,14 @@ 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); } - advsm->adv_txpwr = 0; /* TODO rspbuf[21];*/ + tx_power = (int8_t) rspbuf[21]; + if (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->own_addr_type = own_addr_type; advsm->peer_addr_type = peer_addr_type; advsm->adv_filter_policy = adv_filter_policy; diff --git a/nimble/drivers/native/src/ble_phy.c b/nimble/drivers/native/src/ble_phy.c index a8fd9f54d..6a39346c7 100644 --- a/nimble/drivers/native/src/ble_phy.c +++ b/nimble/drivers/native/src/ble_phy.c @@ -497,6 +497,29 @@ ble_phy_txpwr_set(int dbm) return 0; } +/** + * ble phy txpwr round + * + * Get the rounded transmit output power (in dBm). + * + * @param dbm Power output in dBm. + * + * @return int Rounded power in dBm + */ +int ble_phy_txpower_round(int dbm) +{ + /* "Rail" power level if outside supported range */ + if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) { + dbm = BLE_XCVR_TX_PWR_MAX_DBM; + } else { + if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) { + dbm = BLE_XCVR_TX_PWR_MIN_DBM; + } + } + + return dbm; +} + /** * ble phy txpwr get * diff --git a/nimble/drivers/nrf51/src/ble_phy.c b/nimble/drivers/nrf51/src/ble_phy.c index 84d61d6a1..b74e7831b 100644 --- a/nimble/drivers/nrf51/src/ble_phy.c +++ b/nimble/drivers/nrf51/src/ble_phy.c @@ -1212,6 +1212,29 @@ ble_phy_txpwr_set(int dbm) return 0; } +/** + * ble phy txpwr round + * + * Get the rounded transmit output power (in dBm). + * + * @param dbm Power output in dBm. + * + * @return int Rounded power in dBm + */ +int ble_phy_txpower_round(int dbm) +{ + /* "Rail" power level if outside supported range */ + if (dbm > NRF_TX_PWR_MAX_DBM) { + dbm = NRF_TX_PWR_MAX_DBM; + } else { + if (dbm < NRF_TX_PWR_MIN_DBM) { + dbm = NRF_TX_PWR_MIN_DBM; + } + } + + return dbm; +} + /** * ble phy txpwr get * diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index 81becf955..f14831448 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -1294,6 +1294,29 @@ ble_phy_txpwr_set(int dbm) return 0; } +/** + * ble phy txpwr round + * + * Get the rounded transmit output power (in dBm). + * + * @param dbm Power output in dBm. + * + * @return int Rounded power in dBm + */ +int ble_phy_txpower_round(int dbm) +{ + /* "Rail" power level if outside supported range */ + if (dbm > NRF_TX_PWR_MAX_DBM) { + dbm = NRF_TX_PWR_MAX_DBM; + } else { + if (dbm < NRF_TX_PWR_MIN_DBM) { + dbm = NRF_TX_PWR_MIN_DBM; + } + } + + return dbm; +} + /** * ble phy set access addr * From 2b5c570ab362237d0463c7a3b4e1569ca2ac7ef2 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 26 Jun 2017 16:51:21 +0200 Subject: [PATCH 23/27] nimble/controller: Reduce padding in ble_ll_adv_sm Move some fields around to minimize padding. X-Original-Commit: fca1b8a5c110f6a2c15d34e0d1730b36adc9ea3a --- nimble/controller/src/ble_ll_adv.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 77f16ddd3..a1c7c3aef 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -84,6 +84,7 @@ struct ble_ll_adv_sm int8_t adv_rpa_index; uint8_t flags; int8_t adv_txpwr; + uint16_t props; uint16_t adv_itvl_min; uint16_t adv_itvl_max; uint32_t adv_itvl_usecs; @@ -100,18 +101,16 @@ struct ble_ll_adv_sm uint8_t *conn_comp_ev; struct os_event adv_txdone_ev; struct ble_ll_sched_item adv_sch; - uint16_t props; #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) - uint8_t adv_secondary; - uint8_t adv_secondary_chan; uint32_t adv_secondary_start_time; struct ble_ll_sched_item adv_secondary_sch; - - uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; uint16_t duration; /* TODO */ + uint16_t did; + uint8_t adv_secondary; + uint8_t adv_secondary_chan; + uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; uint8_t events_max; uint8_t events; - uint16_t did; uint8_t pri_phy; uint8_t sec_phy; uint8_t sid; From 85ff7e4bb7ef9962415f8aaaefd9d57934691c08 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 27 Jun 2017 11:54:08 +0200 Subject: [PATCH 24/27] nimble/controller: Remove support for Android specific HCI commands All functionality provided by those commands is available via standard HCI commands introduced in Bluetooth 5 specification. Also events generated but Android commands were not implemented correctly as vendor events. This resulted in spurious events being sent to host. X-Original-Commit: 4f5ffa33991588da657bd0b1f9651879bb3b9870 --- .../include/controller/ble_ll_adv.h | 5 +- nimble/controller/src/ble_ll_adv.c | 150 ++---------------- nimble/controller/src/ble_ll_hci.c | 89 +---------- nimble/include/nimble/ble.h | 5 +- nimble/include/nimble/hci_vendor.h | 112 ------------- nimble/syscfg.yml | 3 - 6 files changed, 20 insertions(+), 344 deletions(-) delete mode 100644 nimble/include/nimble/hci_vendor.h diff --git a/nimble/controller/include/controller/ble_ll_adv.h b/nimble/controller/include/controller/ble_ll_adv.h index ad69232ff..259006a7a 100644 --- a/nimble/controller/include/controller/ble_ll_adv.h +++ b/nimble/controller/include/controller/ble_ll_adv.h @@ -124,14 +124,11 @@ int ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, uint8_t operation); /* Set advertising parameters */ -int ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi); +int ble_ll_adv_set_adv_params(uint8_t *cmd); /* Read advertising channel power */ int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_adv_multi_adv_cmd(uint8_t *cmd, uint8_t cmdlen, uint8_t *rspbuf, - uint8_t *rsplen); - /*---- API used by BLE LL ----*/ /* Send the connection complete event */ void ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index a1c7c3aef..6145320a6 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -27,7 +27,6 @@ #include "nimble/ble.h" #include "nimble/nimble_opt.h" #include "nimble/hci_common.h" -#include "nimble/hci_vendor.h" #include "nimble/ble_hci_trans.h" #include "controller/ble_phy.h" #include "controller/ble_hw.h" @@ -101,7 +100,7 @@ struct ble_ll_adv_sm uint8_t *conn_comp_ev; struct os_event adv_txdone_ev; struct ble_ll_sched_item adv_sch; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) uint32_t adv_secondary_start_time; struct ble_ll_sched_item adv_secondary_sch; uint16_t duration; /* TODO */ @@ -1049,37 +1048,24 @@ ble_ll_adv_halt(struct ble_ll_adv_sm *advsm) * @return int */ int -ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) +ble_ll_adv_set_adv_params(uint8_t *cmd) { uint8_t adv_type; uint8_t adv_filter_policy; uint8_t adv_chanmask; uint8_t own_addr_type; uint8_t peer_addr_type; - uint8_t offset; uint16_t adv_itvl_min; uint16_t adv_itvl_max; uint16_t min_itvl; struct ble_ll_adv_sm *advsm; uint16_t props; - /* If already enabled, we return an error */ - if (instance >= BLE_LL_ADV_INSTANCES) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - advsm = &g_ble_ll_adv_sm[instance]; + advsm = &g_ble_ll_adv_sm[0]; if (advsm->adv_enabled) { return BLE_ERR_CMD_DISALLOWED; } - /* Add offset if this is a multi-advertising command */ - if (is_multi) { - offset = 6; - } else { - offset = 0; - } - /* Make sure intervals are OK (along with advertising type */ adv_itvl_min = get_le16(cmd); adv_itvl_max = get_le16(cmd + 2); @@ -1089,7 +1075,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) * Get the filter policy now since we will ignore it if we are doing * directed advertising */ - adv_filter_policy = cmd[14 + offset]; + adv_filter_policy = cmd[14]; /* Assume min interval based on low duty cycle/indirect advertising */ min_itvl = BLE_LL_ADV_ITVL_MIN; @@ -1136,44 +1122,19 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) /* Check own and peer address type */ own_addr_type = cmd[5]; - peer_addr_type = cmd[6 + offset]; + peer_addr_type = cmd[6]; if ((own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) || (peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Deal with multi-advertising command specific*/ -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) - if (is_multi) { - /* Get and check advertising power */ - advsm->adv_txpwr = cmd[22]; - if (advsm->adv_txpwr > 20) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Get own address if it is there. */ - if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } else { - if (own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) { - /* Use this random address if set in own address */ - if (ble_ll_is_valid_random_addr(cmd + 6)) { - memcpy(advsm->adv_random_addr, cmd + 6, BLE_DEV_ADDR_LEN); - } - } - } - } else { - advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); - } -#else advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); -#endif #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { /* Copy peer address */ - memcpy(advsm->peer_addr, cmd + 7 + offset, BLE_DEV_ADDR_LEN); + memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN); /* Reset RPA timer so we generate a new RPA */ advsm->adv_rpa_timer = os_time_get(); @@ -1186,7 +1147,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd, uint8_t instance, int is_multi) #endif /* There are only three adv channels, so check for any outside the range */ - adv_chanmask = cmd[13 + offset]; + adv_chanmask = cmd[13]; if (((adv_chanmask & 0xF8) != 0) || (adv_chanmask == 0)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -1230,7 +1191,7 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) /* Set to standby if we are no longer advertising */ OS_ENTER_CRITICAL(sr); -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (g_ble_ll_cur_adv_sm == advsm) { ble_phy_disable(); ble_ll_wfr_disable(); @@ -1333,17 +1294,10 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) advsm->flags &= ~BLE_LL_ADV_SM_FLAG_RX_ADD; advsm->flags &= ~BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD; - /* - * This is not in the specification. I will reject the command with a - * command disallowed error if no random address has been sent by the - * host. All the parameter errors refer to the command - * parameter (which in this case is just enable or disable) so that - * is why I chose command disallowed. - */ if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) { -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (!ble_ll_is_valid_random_addr(advsm->adv_random_addr)) { - return BLE_ERR_CMD_DISALLOWED; + return BLE_ERR_INV_HCI_CMD_PARMS; } #else if (!ble_ll_is_valid_random_addr(g_random_addr)) { @@ -1371,7 +1325,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) if ((advsm->own_addr_type & 1) == 0) { addr = g_dev_addr; } else { -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) addr = advsm->adv_random_addr; #else addr = g_random_addr; @@ -1691,7 +1645,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) return BLE_ERR_SUCCESS; } -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) int ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) { @@ -2058,68 +2012,6 @@ ble_ll_adv_clear_all(void) return BLE_ERR_SUCCESS; } - -/** - * Process the multi-advertising command - * - * NOTE: the command length was already checked to make sure it is non-zero. - * - * @param cmdbuf Pointer to command buffer - * @param cmdlen The length of the command data - * @param rspbuf Pointer to response buffer - * @param rsplen Pointer to response length - * - * @return int - */ -int -ble_ll_adv_multi_adv_cmd(uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, - uint8_t *rsplen) -{ - int rc; - uint8_t subcmd; - - /* NOTE: the command length includes the sub command byte */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - subcmd = cmdbuf[0]; - ++cmdbuf; - switch (subcmd) { - case BLE_HCI_MULTI_ADV_PARAMS: - if (cmdlen == BLE_HCI_MULTI_ADV_PARAMS_LEN) { - rc = ble_ll_adv_set_adv_params(cmdbuf, cmdbuf[21], 1); - } - break; - case BLE_HCI_MULTI_ADV_DATA: - if (cmdlen == BLE_HCI_MULTI_ADV_DATA_LEN) { - rc = ble_ll_adv_set_adv_data(cmdbuf, cmdbuf[32], - BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE); - } - break; - case BLE_HCI_MULTI_ADV_SCAN_RSP_DATA: - if (cmdlen == BLE_HCI_MULTI_ADV_SCAN_RSP_DATA_LEN) { - rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, cmdbuf[32], - BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE); - } - break; - case BLE_HCI_MULTI_ADV_SET_RAND_ADDR: - if (cmdlen == BLE_HCI_MULTI_ADV_SET_RAND_ADDR_LEN) { - rc = ble_ll_adv_set_random_addr(cmdbuf, cmdbuf[6]); - } - break; - case BLE_HCI_MULTI_ADV_ENABLE: - if (cmdlen == BLE_HCI_MULTI_ADV_ENABLE_LEN) { - rc = ble_ll_adv_set_enable(cmdbuf[0], cmdbuf[1], 0, 0); - } - break; - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - rspbuf[0] = subcmd; - *rsplen = 1; - - return rc; -} #endif @@ -2381,7 +2273,7 @@ int ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok) { int rc; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) struct ble_mbuf_hdr *rxhdr; #endif @@ -2389,7 +2281,7 @@ ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok) if (rxpdu == NULL) { ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm); } else { -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) rxhdr = BLE_MBUF_HDR_PTR(rxpdu); rxhdr->rxinfo.advsm = g_ble_ll_cur_adv_sm; #endif @@ -2433,7 +2325,7 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) int adv_event_over; struct ble_ll_adv_sm *advsm; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) advsm = (struct ble_ll_adv_sm *)hdr->rxinfo.advsm; #else advsm = &g_ble_ll_adv_sm[0]; @@ -2787,18 +2679,8 @@ ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, uint8_t *evbuf; struct ble_ll_adv_sm *advsm; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) advsm = (struct ble_ll_adv_sm *)rxhdr->rxinfo.advsm; - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (evbuf) { - evbuf[0] = BLE_HCI_EVCODE_LE_META; - evbuf[1] = 5; /* Length of event, including sub-event code */ - evbuf[2] = BLE_HCI_LE_SUBEV_ADV_STATE_CHG; - evbuf[3] = advsm->adv_instance; - evbuf[4] = 0x00; /* status code */ - put_le16(evbuf + 5, connsm->conn_handle); - ble_ll_hci_event_send(evbuf); - } #else advsm = &g_ble_ll_adv_sm[0]; #endif diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index d313eb3cc..fa41ca6b2 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -24,7 +24,6 @@ #include "nimble/ble.h" #include "nimble/nimble_opt.h" #include "nimble/hci_common.h" -#include "nimble/hci_vendor.h" #include "nimble/ble_hci_trans.h" #include "controller/ble_hw.h" #include "controller/ble_ll_adv.h" @@ -623,87 +622,6 @@ ble_ll_ext_adv_set_remove(uint8_t *cmd) #endif -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) -/** - * Returns the vendor specific capabilities - * - * @param rspbuf Pointer to response buffer - * @param rsplen Length of response buffer - * - * @return int BLE error code - */ -static int -ble_ll_hci_vendor_caps(uint8_t *rspbuf, uint8_t *rsplen) -{ - /* Clear all bytes */ - memset(rspbuf, 0, 14); - - /* Fill out the ones we support */ - rspbuf[0] = BLE_LL_ADV_INSTANCES; - rspbuf[9] = 0x60; - *rsplen = 14; - return BLE_ERR_SUCCESS; -} - -/** - * Process a vendor command sent from the host to the controller. The HCI - * command has a 3 byte command header followed by data. The header is: - * -> opcode (2 bytes) - * -> Length of parameters (1 byte; does include command header bytes). - * - * @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_vendor_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) -{ - int rc; - uint8_t cmdlen; - uint8_t *rspbuf; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - - /* Get length from command */ - cmdlen = 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_VENDOR_CAPS: - if (cmdlen == 0) { - ble_ll_hci_vendor_caps(rspbuf, rsplen); - rc = BLE_ERR_SUCCESS; - } - break; - case BLE_HCI_OCF_MULTI_ADV: - if (cmdlen > 0) { - rc = ble_ll_adv_multi_adv_cmd(cmdbuf, cmdlen, rspbuf, rsplen); - } - break; - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - /* XXX: for now, all vendor commands return a command complete */ - return rc; -} -#endif - /** * Process a LE command sent from the host to the controller. The HCI command * has a 3 byte command header followed by data. The header is: @@ -762,7 +680,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = ble_ll_set_random_addr(cmdbuf); break; case BLE_HCI_OCF_LE_SET_ADV_PARAMS: - rc = ble_ll_adv_set_adv_params(cmdbuf, 0, 0); + rc = ble_ll_adv_set_adv_params(cmdbuf); break; case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR: rc = ble_ll_adv_read_txpwr(rspbuf, rsplen); @@ -1194,11 +1112,6 @@ ble_ll_hci_cmd_proc(struct os_event *ev) case BLE_HCI_OGF_LE: rc = ble_ll_hci_le_cmd_proc(cmdbuf, ocf, &rsplen); break; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) - case BLE_HCI_OGF_VENDOR: - rc = ble_ll_hci_vendor_cmd_proc(cmdbuf, ocf, &rsplen); - break; -#endif default: /* XXX: Need to support other OGF. For now, return unsupported */ rc = BLE_ERR_UNKNOWN_HCI_CMD; diff --git a/nimble/include/nimble/ble.h b/nimble/include/nimble/ble.h index 5d674e3fd..d8e019942 100644 --- a/nimble/include/nimble/ble.h +++ b/nimble/include/nimble/ble.h @@ -67,10 +67,9 @@ struct ble_mbuf_hdr_rxinfo uint8_t handle; int8_t rssi; int8_t phy; -#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT) - void *advsm; /* advertising state machine */ -#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* TODO this could be just one user-data pointer */ + void *advsm; /* advertising state machine */ void *aux_data; #endif }; diff --git a/nimble/include/nimble/hci_vendor.h b/nimble/include/nimble/hci_vendor.h deleted file mode 100644 index 2ef3190c3..000000000 --- a/nimble/include/nimble/hci_vendor.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HCI_VENDOR_ -#define H_BLE_HCI_VENDOR_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Here is a list of the vendor specific OCFs */ -#define BLE_HCI_OCF_VENDOR_CAPS (0x153) -#define BLE_HCI_OCF_MULTI_ADV (0x154) - -/* Multi-advertiser sub-commands */ -#define BLE_HCI_MULTI_ADV_PARAMS (0x01) -#define BLE_HCI_MULTI_ADV_DATA (0x02) -#define BLE_HCI_MULTI_ADV_SCAN_RSP_DATA (0x03) -#define BLE_HCI_MULTI_ADV_SET_RAND_ADDR (0x04) -#define BLE_HCI_MULTI_ADV_ENABLE (0x05) - -/* Command lengths. Includes sub-command opcode */ -#define BLE_HCI_MULTI_ADV_PARAMS_LEN (24) -#define BLE_HCI_MULTI_ADV_DATA_LEN (34) -#define BLE_HCI_MULTI_ADV_SCAN_RSP_DATA_LEN (34) -#define BLE_HCI_MULTI_ADV_SET_RAND_ADDR_LEN (8) -#define BLE_HCI_MULTI_ADV_ENABLE_LEN (3) - -/* Vendor specific events (LE meta events) */ -#define BLE_HCI_LE_SUBEV_ADV_STATE_CHG (0x55) - -/* Data structures associated with vendor specific commands */ -struct hci_vendor_capabilities -{ - uint8_t max_advt_instances; - uint8_t offloaded_resolution_of_priv_addr; - uint16_t total_scan_results_bytes; - uint8_t max_irk_list_sz; - uint8_t filtering_support; - uint8_t max_filters; - uint8_t activity_energy_info_support; - uint16_t version_supported; - uint16_t total_adv_tracked; - uint8_t extended_scan_support; - uint8_t debug_logging_supported; -}; - -/* NOTE: these are not in command order */ -struct hci_multi_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; - int8_t adv_tx_pwr; /* -70 to +20 */ - uint8_t adv_instance; - uint16_t adv_itvl_min; - uint16_t adv_itvl_max; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - uint8_t own_addr[BLE_DEV_ADDR_LEN]; -}; - -/* - * NOTE: structures are not defined for the following sub commands. - * The format of these commands is: - * - * Multi-adv Set Advertising Data: - * - Advertising data length (1) - * - Advertising data (31) - * - Advertising Instance (1) - * - * Multi-adv Set Scan Response Data: - * - Scan response data length (1) - * - Scan response data (31) - * - Advertising Instance (1) - * - * Multi-adv Set Random Address: - * - Random Address (6) - * - Advertising Instance (1) - * - * Multi-adv Set Advertising Enable: - * - Random Address (6) - * - Advertising Instance (1) - * - * All of these commands generate a Command Complete with this format: - * - Status (1) - * - Multi-adv opcode (1) - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_HCI_VENDOR_ */ diff --git a/nimble/syscfg.yml b/nimble/syscfg.yml index 329810701..f29c52790 100644 --- a/nimble/syscfg.yml +++ b/nimble/syscfg.yml @@ -41,9 +41,6 @@ syscfg.defs: Enables the BLE whitelist for controlling who to connect to or accept a connection from. (0/1) value: 1 - BLE_ANDROID_MULTI_ADV_SUPPORT: - description: 'Support for Android Vendor multi-advertisers HCI commands' - value: 0 BLE_MULTI_ADV_INSTANCES: description: > This is the number of multi-advertising instances. This is NOT the From 6aa48e00a3597350a6cd818137328d41127c3a70 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 27 Jun 2017 13:54:36 +0200 Subject: [PATCH 25/27] nimble/controller: Fix build with extended advertising disabled X-Original-Commit: cf1aa4deb5050d299a6a9f7175d49de15405b2ee --- nimble/controller/src/ble_ll_adv.c | 50 ++++++++++++++++++++++++++- nimble/controller/src/ble_ll_hci_ev.c | 4 +++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 6145320a6..91b5b8e5b 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -308,6 +308,7 @@ ble_ll_adv_legacy_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) } } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* TODO this shouldn't be needed * * PDU could be constructed before scheduling and held in mbuf until @@ -512,6 +513,7 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) dptr += advsm->adv_len; } } +#endif static struct os_mbuf * ble_ll_adv_scan_rsp_legacy_pdu_make(struct ble_ll_adv_sm *advsm) @@ -560,6 +562,7 @@ ble_ll_adv_scan_rsp_legacy_pdu_make(struct ble_ll_adv_sm *advsm) return m; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /** * Create a scan response PDU * @@ -698,6 +701,7 @@ ble_ll_adv_aux_conn_rsp_pdu_make(struct ble_ll_adv_sm *advsm, uint8_t *peer, return m; } +#endif /** * Called to indicate the advertising event is over. @@ -814,6 +818,7 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) goto adv_tx_done; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) advsm->adv_secondary = 0; ble_ll_adv_pdu_make(advsm, adv_pdu); @@ -823,6 +828,12 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) } else { ble_phy_mode_set(advsm->pri_phy, advsm->pri_phy); } +#endif +#else + ble_ll_adv_legacy_pdu_make(advsm, adv_pdu); +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); +#endif #endif /* Transmit advertisement */ @@ -864,11 +875,15 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) sch->sched_type = BLE_LL_SCHED_TYPE_ADV; /* Set end time to maximum time this schedule item may take */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); } else { max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, advsm->pri_phy); } +#else + max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); +#endif if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; @@ -888,6 +903,7 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) os_cputime_usecs_to_ticks(max_usecs); } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static int ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) { @@ -1022,7 +1038,7 @@ ble_ll_adv_secondary_set_sched(struct ble_ll_adv_sm *advsm) sch->end_time = advsm->adv_secondary_start_time + os_cputime_usecs_to_ticks(max_usecs); } - +#endif /** * Called when advertising need to be halted. This normally should not be called @@ -1185,9 +1201,11 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) /* Remove any scheduled advertising items */ ble_ll_sched_rmv_elem(&advsm->adv_sch); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { ble_ll_sched_rmv_elem(&advsm->adv_secondary_sch); } +#endif /* Set to standby if we are no longer advertising */ OS_ENTER_CRITICAL(sr); @@ -1245,6 +1263,7 @@ ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000); } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static void ble_ll_set_adv_secondary_start_time(struct ble_ll_adv_sm *advsm) { @@ -1270,6 +1289,7 @@ ble_ll_adv_secondary_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start) { advsm->adv_secondary_start_time = sch_start; } +#endif /** * Start the advertising state machine. This is called when the host sends @@ -1382,12 +1402,14 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) ble_ll_adv_set_sched(advsm); ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { ble_ll_set_adv_secondary_start_time(advsm); ble_ll_adv_secondary_set_sched(advsm); ble_ll_sched_adv_new(&advsm->adv_secondary_sch, ble_ll_adv_secondary_scheduled); } +#endif return BLE_ERR_SUCCESS; } @@ -1432,9 +1454,11 @@ ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, uint16_t duration, rc = BLE_ERR_SUCCESS; if (enable == 1) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) advsm->duration = duration; advsm->events_max = events; advsm->events = 0; +#endif /* If already enabled, do nothing */ if (!advsm->adv_enabled) { @@ -1486,6 +1510,7 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, uint8_t operation) } break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_LAST: /* TODO mark scan rsp as complete? */ /* fall through */ @@ -1518,6 +1543,7 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, uint8_t operation) } break; +#endif default: return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -1528,8 +1554,10 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, uint8_t operation) return BLE_ERR_MEM_CAPACITY; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* DID shall be updated when host provides new scan response data */ advsm->did = rand() & 0x0fff; +#endif /* Copy the new data into the advertising structure. */ advsm->scan_rsp_len = datalen + off; @@ -1581,6 +1609,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) } break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED: if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -1625,6 +1654,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) } break; +#endif default: return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -1635,8 +1665,10 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) return BLE_ERR_MEM_CAPACITY; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* DID shall be updated when host provides new advertising data */ advsm->did = rand() & 0x0fff; +#endif /* Copy the new data into the advertising structure. */ advsm->adv_len = datalen + off; @@ -2101,12 +2133,16 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) rc = -1; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->flags & BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF) { ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer, peer_addr_type); } rsp = ble_ll_adv_scan_rsp_pdu_make(advsm); +#else + rsp = ble_ll_adv_scan_rsp_legacy_pdu_make(advsm); +#endif if (rsp) { /* XXX TODO: assume we do not need to change phy mode */ ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); @@ -2128,6 +2164,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) } } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { return -1; } @@ -2145,6 +2182,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) } os_mbuf_free_chain(rsp); } +#endif } return rc; @@ -2415,6 +2453,7 @@ ble_ll_adv_rx_isr_start(uint8_t pdu_type) return rc; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static void ble_ll_adv_secondary_done(struct ble_ll_adv_sm *advsm) { @@ -2453,6 +2492,7 @@ ble_ll_adv_secondary_done(struct ble_ll_adv_sm *advsm) os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); } } +#endif /** * Called when an advertising event is over. @@ -2476,6 +2516,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) assert(advsm->adv_enabled); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* stop advertising this was due to transmitting connection response */ if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { ble_ll_adv_sm_stop(advsm); @@ -2486,6 +2527,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) ble_ll_adv_secondary_done(advsm); return; } +#endif /* Remove the element from the schedule if it is still there. */ ble_ll_sched_rmv_elem(&advsm->adv_sch); @@ -2500,9 +2542,11 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) final_adv_chan = ble_ll_adv_final_chan(advsm); if (advsm->adv_chan == final_adv_chan) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->events_max) { advsm->events++; } +#endif /* Check if we need to resume scanning */ ble_ll_scan_chk_resume(); @@ -2586,6 +2630,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) } } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->events_max && (advsm->events >= advsm->events_max)) { /* Legacy PDUs need to be stop here, for ext adv it will be stopped when * AUX is done. @@ -2602,6 +2647,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) return; } +#endif /* We need to regenerate our RPA's if we have passed timeout */ #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) @@ -2691,8 +2737,10 @@ ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, advsm); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) ble_ll_hci_ev_send_adv_set_terminated(0, advsm->adv_instance, connsm->conn_handle, advsm->events); +#endif #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1) ble_ll_hci_ev_le_csa(connsm); diff --git a/nimble/controller/src/ble_ll_hci_ev.c b/nimble/controller/src/ble_ll_hci_ev.c index 37e7d23b0..70ba68f9c 100644 --- a/nimble/controller/src/ble_ll_hci_ev.c +++ b/nimble/controller/src/ble_ll_hci_ev.c @@ -297,6 +297,7 @@ ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm) * Sends the LE Scan Request Received event * */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) void ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, uint8_t peer_addr_type) @@ -316,11 +317,13 @@ ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, } } } +#endif /** * Sends the LE Advertising Set Terminated event * */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) void ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, uint16_t conn_handle, uint8_t events) @@ -341,6 +344,7 @@ ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, } } } +#endif /** * Send a PHY update complete event From 5b0eb584cb1e584586341216126e14f45766d667 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 27 Jun 2017 15:48:37 +0200 Subject: [PATCH 26/27] nimble/controller: Store DID and SID in single variable SID and DID are always transmitted together in ADI field. There is no need to keep them separated as ADI can be constructed when setting it from HCI. This saves both memory and computing X-Original-Commit: 8934c5387d2ea9f10a30cbf11a56b88a81b254eb --- nimble/controller/src/ble_ll_adv.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 91b5b8e5b..9498b99fd 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -104,7 +104,7 @@ struct ble_ll_adv_sm uint32_t adv_secondary_start_time; struct ble_ll_sched_item adv_secondary_sch; uint16_t duration; /* TODO */ - uint16_t did; + uint16_t adi; uint8_t adv_secondary; uint8_t adv_secondary_chan; uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; @@ -112,7 +112,6 @@ struct ble_ll_adv_sm uint8_t events; uint8_t pri_phy; uint8_t sec_phy; - uint8_t sid; #endif }; @@ -475,10 +474,8 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) } if (adi) { - dptr[0] = advsm->did & 0x00ff; - dptr[1] = advsm->did >> 8; - dptr[1] |= (advsm->sid) << 4; - + dptr[0] = advsm->adi & 0x00ff; + dptr[1] = advsm->adi >> 8; dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; } @@ -1556,7 +1553,7 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t instance, uint8_t operation) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* DID shall be updated when host provides new scan response data */ - advsm->did = rand() & 0x0fff; + advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff); #endif /* Copy the new data into the advertising structure. */ @@ -1620,7 +1617,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) } /* update DID only */ - advsm->did = rand() & 0x0fff; + advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff); return BLE_ERR_SUCCESS; case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST: /* TODO mark adv data as complete? */ @@ -1667,7 +1664,7 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t instance, uint8_t operation) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* DID shall be updated when host provides new advertising data */ - advsm->did = rand() & 0x0fff; + advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff); #endif /* Copy the new data into the advertising structure. */ @@ -1845,7 +1842,9 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen) advsm->adv_itvl_max = adv_itvl_max; advsm->pri_phy = pri_phy; advsm->sec_phy = sec_phy; - advsm->sid = sid; + /* Update SID only */ + advsm->adi = (advsm->adi & 0x0fff) | ((sid << 12)); + advsm->props = props; if (scan_req_notif) { From 7d331060ab202efb3966ec2e1141b9219b9b29bb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 29 Jun 2017 15:28:11 +0200 Subject: [PATCH 27/27] nimble/controller: Use flag for marking advertising on data channel There is no need for adding additional bytes to advertising state machine structure. X-Original-Commit: ccc75ea7cec2ba4a64864c03508fae366b4ebccc --- nimble/controller/src/ble_ll_adv.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 9498b99fd..506e0ea74 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -105,7 +105,6 @@ struct ble_ll_adv_sm struct ble_ll_sched_item adv_secondary_sch; uint16_t duration; /* TODO */ uint16_t adi; - uint8_t adv_secondary; uint8_t adv_secondary_chan; uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; uint8_t events_max; @@ -119,6 +118,7 @@ struct ble_ll_adv_sm #define BLE_LL_ADV_SM_FLAG_RX_ADD 0x02 #define BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF 0x04 #define BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD 0x08 +#define BLE_LL_ADV_SM_FLAG_SECONDARY 0x10 /* The advertising state machine global object */ struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_LL_ADV_INSTANCES]; @@ -372,7 +372,7 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) ext_hdr_flags = 0; - if (advsm->adv_secondary) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_SECONDARY) { pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND; adi = true; @@ -816,7 +816,7 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - advsm->adv_secondary = 0; + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_SECONDARY; ble_ll_adv_pdu_make(advsm, adv_pdu); #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -964,7 +964,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) goto adv_tx_done; } - advsm->adv_secondary = 1; + advsm->flags |= BLE_LL_ADV_SM_FLAG_SECONDARY; ble_ll_adv_pdu_make(advsm, adv_pdu); #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -1310,6 +1310,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) advsm->flags &= ~BLE_LL_ADV_SM_FLAG_TX_ADD; advsm->flags &= ~BLE_LL_ADV_SM_FLAG_RX_ADD; advsm->flags &= ~BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD; + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_SECONDARY; if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) @@ -2522,7 +2523,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) return; } - if (advsm->adv_secondary) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_SECONDARY) { ble_ll_adv_secondary_done(advsm); return; }