From fb7651b773734a075c47ff10210b92e6d55ef55b Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 27 Sep 2019 22:10:30 +0200 Subject: [PATCH] nimble/ll: Add support for custom DTM extensions This allows to enable custom extensions for DTM which currently allow to override interval between test packets and number of packets to be transmitted. See description of new syscfg setting for details. This is not enabled by default since it extends HCI command defined by Core specification so we need to be compliant by default. However even if extensions are enabled, NimBLE still accepts HCI command as defined in Core specification but also accepts extended one. --- nimble/controller/include/controller/ble_ll.h | 2 +- .../include/controller/ble_ll_sched.h | 2 +- .../controller/include/controller/ble_phy.h | 2 +- nimble/controller/src/ble_ll.c | 16 ++--- nimble/controller/src/ble_ll_dtm.c | 62 +++++++++++++++++-- nimble/controller/src/ble_ll_dtm_priv.h | 2 +- nimble/controller/src/ble_ll_hci.c | 12 ++-- nimble/controller/src/ble_ll_sched.c | 2 +- nimble/controller/src/ble_ll_supp_cmd.c | 6 +- nimble/controller/syscfg.yml | 18 ++++++ nimble/drivers/nrf52/src/ble_phy.c | 2 +- porting/npl/riot/include/syscfg/syscfg.h | 4 +- 12 files changed, 98 insertions(+), 32 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 6d5dac950..5fe808410 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -567,7 +567,7 @@ extern uint32_t g_bletest_IVm; extern uint32_t g_bletest_IVs; #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) void ble_ll_dtm_init(void); #endif diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h index 39955eb0b..4ad306ddc 100644 --- a/nimble/controller/include/controller/ble_ll_sched.h +++ b/nimble/controller/include/controller/ble_ll_sched.h @@ -214,7 +214,7 @@ void ble_ll_sched_stop(void); void ble_ll_sched_rfclk_chk_restart(void); #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) int ble_ll_sched_dtm(struct ble_ll_sched_item *sch); #endif diff --git a/nimble/controller/include/controller/ble_phy.h b/nimble/controller/include/controller/ble_phy.h index 463816250..dd5250cef 100644 --- a/nimble/controller/include/controller/ble_phy.h +++ b/nimble/controller/include/controller/ble_phy.h @@ -243,7 +243,7 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options) return phy_mode; } -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) void ble_phy_enable_dtm(void); void ble_phy_disable_dtm(void); #endif diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 79921758f..36c7619cb 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -45,7 +45,7 @@ #include "controller/ble_ll_sync.h" #include "ble_ll_conn_priv.h" -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) #include "ble_ll_dtm_priv.h" #endif @@ -617,7 +617,7 @@ ble_ll_wfr_timer_exp(void *arg) case BLE_LL_STATE_INITIATING: ble_ll_conn_init_wfr_timer_exp(); break; -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) case BLE_LL_STATE_DTM: ble_ll_dtm_wfr_timer_exp(); break; @@ -717,7 +717,7 @@ ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type) crcok = BLE_MBUF_HDR_CRC_OK(hdr); connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_CONNECTION); -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) /* Reuse connection stats for DTM */ connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_DTM); #endif @@ -794,7 +794,7 @@ ble_ll_rx_pkt_in(void) case BLE_LL_STATE_INITIATING: ble_ll_init_rx_pkt_in(pdu_type, rxbuf, ble_hdr); break; -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) case BLE_LL_STATE_DTM: ble_ll_dtm_rx_pkt_in(m, ble_hdr); break; @@ -930,7 +930,7 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) case BLE_LL_STATE_SCANNING: rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags); break; -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) case BLE_LL_STATE_DTM: rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get()); break; @@ -983,7 +983,7 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) ble_ll_trace_u32x3(BLE_LL_TRACE_ID_RX_END, pdu_type, len, rxhdr->rxinfo.flags); -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_DTM) { rc = ble_ll_dtm_rx_isr_end(rxbuf, rxhdr); return rc; @@ -1318,7 +1318,7 @@ ble_ll_reset(void) /* Stop any advertising */ ble_ll_adv_reset(); -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) ble_ll_dtm_reset(); #endif @@ -1628,7 +1628,7 @@ ble_ll_init(void) "ble_ll"); SYSINIT_PANIC_ASSERT(rc == 0); -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) ble_ll_dtm_init(); #endif diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c index 4a92d8efa..0599aab6d 100644 --- a/nimble/controller/src/ble_ll_dtm.c +++ b/nimble/controller/src/ble_ll_dtm.c @@ -49,6 +49,9 @@ struct dtm_ctx { uint8_t itvl_rem_usec; uint16_t num_of_packets; uint32_t itvl_ticks; +#if MYNEWT_VAL(BLE_DTM_CLI_EXTENSIONS_ENABLE) + uint16_t num_of_packets_max; +#endif int active; uint8_t rf_channel; uint8_t phy_mode; @@ -140,6 +143,8 @@ static const uint8_t channel_rf_to_index[] = { #define BLE_DTM_SYNC_WORD (0x71764129) #define BLE_DTM_CRC (0x555555) +static void ble_ll_dtm_ctx_free(struct dtm_ctx * ctx); + static void ble_ll_dtm_set_next(struct dtm_ctx *ctx) { @@ -169,6 +174,18 @@ ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) { } OS_EXIT_CRITICAL(sr); +#if MYNEWT_VAL(BLE_DTM_CLI_EXTENSIONS_ENABLE) + if (g_ble_ll_dtm_ctx.num_of_packets_max && + (g_ble_ll_dtm_ctx.num_of_packets == g_ble_ll_dtm_ctx.num_of_packets_max)) { + /* + * XXX do not send more packets, but also do not stop DTM - it shall be + * stopped as usual by HCI command since there is no standard way to + * signal end of test to host. + */ + return; + } +#endif + ble_ll_dtm_set_next(ctx); rc = ble_ll_sched_dtm(&ctx->sch); BLE_LL_ASSERT(rc == 0); @@ -194,6 +211,8 @@ ble_ll_dtm_tx_done(void *arg) return; } + g_ble_ll_dtm_ctx.num_of_packets++; + /* Reschedule event in LL context */ ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); @@ -249,7 +268,8 @@ resched: } static void -ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, int phy_mode) +ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, + uint16_t cmd_interval, int phy_mode) { uint32_t l; uint32_t itvl_usec; @@ -259,6 +279,12 @@ ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, int phy_mode) l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode); itvl_usec = ((l + 249 + 624) / 625) * 625; +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS_ENABLE) + if (cmd_interval > itvl_usec) { + itvl_usec = cmd_interval; + } +#endif + itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec); ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks)); if (ctx->itvl_rem_usec == 31) { @@ -270,7 +296,8 @@ ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, int phy_mode) static int ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, - uint8_t rf_channel, uint8_t phy_mode) + uint8_t rf_channel, uint8_t phy_mode, + uint16_t cmd_interval, uint16_t cmd_pkt_count) { int rc = 0; uint8_t byte_pattern; @@ -285,6 +312,10 @@ ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, g_ble_ll_dtm_ctx.phy_mode = phy_mode; g_ble_ll_dtm_ctx.rf_channel = rf_channel; + g_ble_ll_dtm_ctx.num_of_packets = 0; +#if MYNEWT_VAL(BLE_DTM_CLI_EXTENSIONS_ENABLE) + g_ble_ll_dtm_ctx.num_of_packets_max = cmd_pkt_count; +#endif /* Set BLE transmit header */ ble_hdr = BLE_MBUF_HDR_PTR(m); @@ -344,7 +375,7 @@ schedule: ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_tx_resched_cb, &g_ble_ll_dtm_ctx); - ble_ll_dtm_calculate_itvl(&g_ble_ll_dtm_ctx, len, phy_mode); + ble_ll_dtm_calculate_itvl(&g_ble_ll_dtm_ctx, len, cmd_interval, phy_mode); /* Set some start point for TX packets */ rc = ble_ll_sched_dtm(sch); @@ -440,17 +471,28 @@ ble_ll_dtm_ctx_free(struct dtm_ctx * ctx) } int -ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced) +ble_ll_dtm_tx_test(uint8_t *cmdbuf, uint8_t cmdlen, bool enhanced) { + uint8_t cmdlen_valid; uint8_t tx_chan = cmdbuf[0]; uint8_t len = cmdbuf[1]; uint8_t packet_payload = cmdbuf[2]; uint8_t phy_mode = BLE_PHY_MODE_1M; + uint16_t interval = 0; + uint16_t pkt_count = 0; if (g_ble_ll_dtm_ctx.active) { return BLE_ERR_CTLR_BUSY; } + cmdlen_valid = enhanced ? BLE_HCI_LE_ENH_TX_TEST_LEN : BLE_HCI_TX_TEST_LEN; + +#if !MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS_ENABLE) + if (cmdlen != cmdlen_valid) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } +#endif + if (enhanced) { switch (cmdbuf[3]) { case BLE_HCI_LE_PHY_1M: @@ -478,7 +520,17 @@ ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced) return BLE_ERR_INV_HCI_CMD_PARMS; } - if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode)) { +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS_ENABLE) + if (cmdlen == cmdlen_valid + 4) { + interval = get_le16(cmdbuf + cmdlen_valid ); + pkt_count = get_le16(cmdbuf + cmdlen_valid + 2); + } else if (cmdlen != cmdlen_valid) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } +#endif + + if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode, + interval, pkt_count)) { return BLE_ERR_UNSPECIFIED; } diff --git a/nimble/controller/src/ble_ll_dtm_priv.h b/nimble/controller/src/ble_ll_dtm_priv.h index 5341cd28d..d6633f158 100644 --- a/nimble/controller/src/ble_ll_dtm_priv.h +++ b/nimble/controller/src/ble_ll_dtm_priv.h @@ -24,7 +24,7 @@ #include #include "nimble/ble.h" -int ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced); +int ble_ll_dtm_tx_test(uint8_t *cmdbuf, uint8_t cmdlen, bool enhanced); int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced); int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen); diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index c809a5ac5..817d8631c 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -38,7 +38,7 @@ #include "hal/hal_gpio.h" #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) #include "ble_ll_dtm_priv.h" #endif @@ -982,9 +982,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, break; #if MYNEWT_VAL(BLE_LL_DTM) case BLE_HCI_OCF_LE_TX_TEST: - if (len == BLE_HCI_TX_TEST_LEN) { - rc = ble_ll_dtm_tx_test(cmdbuf, false); - } + rc = ble_ll_dtm_tx_test(cmdbuf, len, false); break; case BLE_HCI_OCF_LE_RX_TEST: if (len == BLE_HCI_RX_TEST_LEN) { @@ -1090,16 +1088,14 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen, } break; #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) case BLE_HCI_OCF_LE_ENH_RX_TEST: if (len == BLE_HCI_LE_ENH_RX_TEST_LEN) { rc = ble_ll_dtm_rx_test(cmdbuf, true); } break; case BLE_HCI_OCF_LE_ENH_TX_TEST: - if (len == BLE_HCI_LE_ENH_TX_TEST_LEN) { - rc = ble_ll_dtm_tx_test(cmdbuf, true); - } + rc = ble_ll_dtm_tx_test(cmdbuf, len, true); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index fa9b013f3..29742c277 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -1793,7 +1793,7 @@ done: } #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) int ble_ll_sched_dtm(struct ble_ll_sched_item *sch) { int rc; diff --git a/nimble/controller/src/ble_ll_supp_cmd.c b/nimble/controller/src/ble_ll_supp_cmd.c index 74ad601cc..8f62ed30b 100644 --- a/nimble/controller/src/ble_ll_supp_cmd.c +++ b/nimble/controller/src/ble_ll_supp_cmd.c @@ -137,7 +137,7 @@ #endif #define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3) -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) #define BLE_SUPP_CMD_LE_RX_TEST (1 << 4) #define BLE_SUPP_CMD_LE_TX_TEST (1 << 5) #define BLE_SUPP_CMD_LE_TEST_END (1 << 6) @@ -233,7 +233,7 @@ #define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) #define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7) #else #define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7) @@ -252,7 +252,7 @@ ) /* Octet 36 */ -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) #define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (1 << 0) #else #define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0) diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 91b4bdc8a..e3c6b76ca 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -296,6 +296,24 @@ syscfg.defs: description: > Enables HCI Test commands needed for Bluetooth SIG certification value: MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) + BLE_LL_DTM_EXTENSIONS_ENABLE: + description: > + Enables non-standard extensions to HCI test commands. Once enabled, + HCI_LE_Transmitter_Test accepts extra parameters in addition to + those defined in Core specification + interval (2 octets) interval between packets (usecs), overrides + standard interval + pkt_count (2 octets) number of packets to transmit, controller + will automatically stop sending packets + after given number of packets was sent + Setting either of these parameters to 0 will configure for default + behavior, as per Core specification. + If specified interval is shorter then allowed by specification it + will be ignored. + Extended parameters shall immediately follow standard parameters. + Controller can accept both standard and extended version of command + depending on specified HCI command length. + value: 0 BLE_LL_VND_EVENT_ON_ASSERT: description: > diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index a08ca883f..3b62660a1 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -2061,7 +2061,7 @@ ble_phy_resolv_list_disable(void) } #endif -#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) +#if MYNEWT_VAL(BLE_LL_DTM) void ble_phy_enable_dtm(void) { /* When DTM is enabled we need to disable whitening as per diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index 8fb670067..4fde49794 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -517,8 +517,8 @@ #define MYNEWT_VAL_BLE_LL_DBG_HCI_EV_PIN (-1) #endif -#ifndef MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE -#define MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE (0) +#ifndef MYNEWT_VAL_BLE_LL_DTM +#define MYNEWT_VAL_BLE_LL_DTM (0) #endif /* Overridden by nimble/controller (defined by nimble/controller) */