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.
This commit is contained in:
Andrzej Kaczmarek
2019-10-01 11:21:39 +02:00
parent 323aee97a2
commit fb7651b773
12 changed files with 98 additions and 32 deletions
@@ -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
@@ -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
@@ -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
+8 -8
View File
@@ -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
+57 -5
View File
@@ -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;
}
+1 -1
View File
@@ -24,7 +24,7 @@
#include <stdbool.h>
#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);
+4 -8
View File
@@ -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)
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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)
+18
View File
@@ -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: >
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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) */