You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/01/18 13:01:16 UTC

[GitHub] rymanluk closed pull request #742: nimble/ble_ll: Add support for HCI Test commands

rymanluk closed pull request #742: nimble/ble_ll: Add support for HCI Test commands
URL: https://github.com/apache/mynewt-core/pull/742
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/hw/drivers/nimble/nrf52/src/ble_phy.c b/hw/drivers/nimble/nrf52/src/ble_phy.c
index 690bbd79f..010b744dc 100644
--- a/hw/drivers/nimble/nrf52/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf52/src/ble_phy.c
@@ -1824,6 +1824,19 @@ ble_phy_resolv_list_disable(void)
 }
 #endif
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+void ble_phy_enable_dtm(void)
+{
+    /* Disable whitening as per Bluetooth v5.0 Vol 6. Part F. 4.1.1*/
+    NRF_RADIO->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk;
+}
+
+void ble_phy_disable_dtm(void)
+{
+    /* Enable whitening */
+    NRF_RADIO->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk;
+}
+#endif
 #ifdef BLE_XCVR_RFCLK
 void
 ble_phy_rfclk_enable(void)
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index 3e3d2e517..12b978653 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -187,6 +187,7 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
 #define BLE_LL_STATE_SCANNING       (2)
 #define BLE_LL_STATE_INITIATING     (3)
 #define BLE_LL_STATE_CONNECTION     (4)
+#define BLE_LL_STATE_DTM            (5)
 
 /* LL Features */
 #define BLE_LL_FEAT_LE_ENCRYPTION    (0x00000001)
diff --git a/net/nimble/controller/include/controller/ble_ll_sched.h b/net/nimble/controller/include/controller/ble_ll_sched.h
index 2a971c554..3545a4008 100644
--- a/net/nimble/controller/include/controller/ble_ll_sched.h
+++ b/net/nimble/controller/include/controller/ble_ll_sched.h
@@ -73,6 +73,7 @@ extern uint8_t g_ble_ll_sched_offset_ticks;
 #define BLE_LL_SCHED_TYPE_SCAN      (2)
 #define BLE_LL_SCHED_TYPE_CONN      (3)
 #define BLE_LL_SCHED_TYPE_AUX_SCAN  (4)
+#define BLE_LL_SCHED_TYPE_DTM       (5)
 
 /* Return values for schedule callback. */
 #define BLE_LL_SCHED_STATE_RUNNING  (0)
@@ -196,6 +197,10 @@ void ble_ll_sched_stop(void);
 void ble_ll_sched_rfclk_chk_restart(void);
 #endif
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+int ble_ll_sched_dtm(struct ble_ll_sched_item *sch);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/net/nimble/controller/include/controller/ble_phy.h b/net/nimble/controller/include/controller/ble_phy.h
index b459f548c..3887a2a3e 100644
--- a/net/nimble/controller/include/controller/ble_phy.h
+++ b/net/nimble/controller/include/controller/ble_phy.h
@@ -240,6 +240,11 @@ 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)
+void ble_phy_enable_dtm(void);
+void ble_phy_disable_dtm(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index 81fccc778..3674a19b1 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -42,6 +42,10 @@
 #include "controller/ble_ll_xcvr.h"
 #include "ble_ll_conn_priv.h"
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+#include <ble_ll_dtm_priv.h>
+#endif
+
 /* XXX:
  *
  * 1) use the sanity task!
@@ -569,6 +573,11 @@ 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) == 1
+        case BLE_LL_STATE_DTM:
+            ble_ll_dtm_wfr_timer_exp();
+            break;
+#endif
         default:
             break;
         }
@@ -658,6 +667,12 @@ 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) == 1
+    /* Reuse connection stats for DTM */
+    connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_DTM);
+#endif
+
     if (crcok) {
         if (connection_data) {
             STATS_INC(ble_ll_stats, rx_data_pdu_crc_ok);
@@ -730,6 +745,11 @@ 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) == 1
+        case BLE_LL_STATE_DTM:
+            ble_ll_dtm_rx_pkt_in(m, ble_hdr);
+            break;
+#endif
         default:
             /* Any other state should never occur */
             STATS_INC(ble_ll_stats, bad_ll_state);
@@ -856,6 +876,11 @@ 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) == 1
+    case BLE_LL_STATE_DTM:
+        rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get());
+        break;
+#endif
     default:
         /* Should not be in this state! */
         rc = -1;
@@ -896,6 +921,13 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
                ((uint16_t)rxhdr->rxinfo.flags << 8) | rxbuf[1],
                rxhdr->beg_cputime);
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+    if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_DTM) {
+        rc = ble_ll_dtm_rx_isr_end(rxbuf, rxhdr);
+        return rc;
+    }
+#endif
+
     if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_CONNECTION) {
         rc = ble_ll_conn_rx_isr_end(rxbuf, rxhdr);
         return rc;
@@ -1179,6 +1211,10 @@ ble_ll_reset(void)
     /* Stop any advertising */
     ble_ll_adv_reset();
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE)
+    ble_ll_dtm_reset();
+#endif
+
     /* FLush all packets from Link layer queues */
     ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_tx_pkt_q);
     ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_rx_pkt_q);
diff --git a/net/nimble/controller/src/ble_ll_dtm.c b/net/nimble/controller/src/ble_ll_dtm.c
new file mode 100644
index 000000000..f893f7680
--- /dev/null
+++ b/net/nimble/controller/src/ble_ll_dtm.c
@@ -0,0 +1,494 @@
+/*
+ * 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.
+ */
+
+#include <syscfg/syscfg.h>
+
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+
+#include "assert.h"
+#include "os/os.h"
+#include "controller/ble_ll.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll_sched.h"
+#include "ble_ll_dtm_priv.h"
+
+struct dtm_ctx {
+    uint8_t payload_packet;
+    uint8_t itvl_rem_usec;
+    uint16_t num_of_packets;
+    uint32_t itvl_ticks;
+    int active;
+    int chan;
+    int phy_mode;
+    struct os_mbuf *om;
+    struct os_event evt;
+    struct ble_ll_sched_item sch;
+};
+
+static struct dtm_ctx g_ble_ll_dtm_ctx;
+
+static const uint8_t g_ble_ll_dtm_prbs9_data[] =
+{
+    0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b,
+    0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23,
+    0x02, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b,
+    0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca,
+    0x0c, 0x18, 0x53, 0x2c, 0xfd, 0x45, 0xe3, 0x9a,
+    0xe6, 0xf1, 0x5d, 0xb0, 0xb6, 0x1b, 0xb4, 0xbe,
+    0x2a, 0x50, 0xea, 0xe9, 0x0e, 0x9c, 0x4b, 0x5e,
+    0x57, 0x24, 0xcc, 0xa1, 0xb7, 0x59, 0xb8, 0x87,
+    0xff, 0xe0, 0x7d, 0x74, 0x26, 0x48, 0xb9, 0xc5,
+    0xf3, 0xd9, 0xa8, 0xc4, 0xb1, 0xd5, 0x91, 0x11,
+    0x01, 0x42, 0x0c, 0x39, 0xd5, 0xb0, 0x97, 0x9d,
+    0x28, 0xd4, 0xf2, 0x9b, 0xa4, 0xfd, 0x64, 0x65,
+    0x06, 0x8c, 0x29, 0x96, 0xfe, 0xa2, 0x71, 0x4d,
+    0xf3, 0xf8, 0x2e, 0x58, 0xdb, 0x0d, 0x5a, 0x5f,
+    0x15, 0x28, 0xf5, 0x74, 0x07, 0xce, 0x25, 0xaf,
+    0x2b, 0x12, 0xe6, 0xd0, 0xdb, 0x2c, 0xdc, 0xc3,
+    0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, 0xe2,
+    0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, 0x88,
+    0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, 0x4e,
+    0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, 0x32,
+    0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, 0xa6,
+    0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, 0xaf,
+    0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, 0xd7,
+    0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, 0xe1,
+    0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, 0xf1,
+    0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, 0x44,
+    0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, 0x27,
+    0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, 0x99,
+    0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, 0xd3,
+    0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, 0x57,
+    0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, 0xeb,
+    0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7
+};
+
+static const uint8_t g_ble_ll_dtm_prbs15_data[] =
+{
+    0xff, 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc,
+    0xe2, 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8,
+    0x88, 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb,
+    0x4e, 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2,
+    0x32, 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8,
+    0xa6, 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad,
+    0xaf, 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92,
+    0xd7, 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee,
+    0xe1, 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e,
+    0xf1, 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64,
+    0x44, 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65,
+    0x27, 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59,
+    0x99, 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c,
+    0xd3, 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6,
+    0x57, 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9,
+    0xeb, 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7,
+    0xf0, 0x1f, 0xbc, 0x8f, 0xce, 0x04, 0x29, 0xb7,
+    0x78, 0x3e, 0x1b, 0x95, 0x38, 0xb6, 0x3a, 0x32,
+    0x22, 0x40, 0x88, 0x21, 0xa7, 0x1a, 0xf6, 0xb2,
+    0x13, 0x85, 0x5a, 0x7e, 0x93, 0xb4, 0x9f, 0xac,
+    0xcc, 0x80, 0x31, 0xc5, 0xd2, 0x5f, 0x34, 0xae,
+    0x69, 0x1e, 0xdf, 0x05, 0x6b, 0xbb, 0x41, 0xeb,
+    0xab, 0x02, 0xa5, 0x9e, 0xee, 0xc0, 0xb9, 0xe4,
+    0x75, 0x45, 0xc2, 0x1c, 0x7a, 0x9b, 0x85, 0x7b,
+    0xf8, 0x0f, 0xde, 0x47, 0x67, 0x82, 0x94, 0x5b,
+    0x3c, 0x9f, 0x8d, 0x4a, 0x1c, 0x5b, 0x1d, 0x19,
+    0x11, 0x20, 0xc4, 0x90, 0x53, 0x0d, 0x7b, 0xd9,
+    0x89, 0x42, 0x2d, 0xbf, 0x49, 0xda, 0x4f, 0x56,
+    0x66, 0xc0, 0x98, 0x62, 0xe9, 0x2f, 0x1a, 0xd7,
+    0x34, 0x8f, 0xef, 0x82, 0xb5, 0xdd, 0xa0, 0xf5,
+    0x55, 0x81, 0x52, 0x4f, 0x77, 0xe0, 0x5c, 0xf2,
+    0xba, 0x22, 0x61, 0x0e, 0xbd, 0xcd, 0xc2
+};
+
+#define BLE_DTM_SYNC_WORD          (0x71764129)
+#define BLE_DTM_CRC                (0x555555)
+
+static void
+ble_ll_dtm_set_next(struct dtm_ctx *ctx)
+{
+    struct ble_ll_sched_item *sch = &ctx->sch;
+
+    sch->start_time += ctx->itvl_ticks;
+    sch->remainder += ctx->itvl_rem_usec;
+    if (sch->remainder > 30) {
+       sch->start_time++;
+       sch->remainder -= 30;
+    }
+
+    sch->start_time -= g_ble_ll_sched_offset_ticks;
+}
+
+static void
+ble_ll_dtm_event(struct os_event *evt) {
+    /* It is called in LL context */
+    struct dtm_ctx *ctx = evt->ev_arg;
+    int rc;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    if (!ctx->active || !ctx->om) {
+        OS_EXIT_CRITICAL(sr);
+        return;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    ble_ll_dtm_set_next(ctx);
+    rc = ble_ll_sched_dtm(&ctx->sch);
+    assert(rc == 0);
+}
+
+static void
+ble_ll_dtm_tx_done(void *arg)
+{
+    struct dtm_ctx *ctx;
+
+    ctx = arg;
+    if (!ctx->evt.ev_cb) {
+        return;
+    }
+    ctx->num_of_packets++;
+    /* Reschedule event in LL context */
+    os_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
+
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
+}
+
+static int
+ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch)
+{
+    struct dtm_ctx *ctx = sch->cb_arg;
+    int rc;
+
+    if (!ctx->active) {
+        return BLE_LL_SCHED_STATE_DONE;
+    }
+
+    rc = ble_phy_setchan(ctx->chan, BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
+    if (rc != 0) {
+        assert(0);
+        return BLE_LL_SCHED_STATE_DONE;
+    }
+
+    ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode);
+    ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx);
+    ble_phy_txpwr_set(0);
+
+    sch->start_time += g_ble_ll_sched_offset_ticks;
+
+    /*XXX Maybe reschedule if too late */
+    rc = ble_phy_tx_set_start_time(sch->start_time, sch->remainder);
+    assert(rc == 0);
+
+    rc = ble_phy_tx(ctx->om, BLE_PHY_TRANSITION_NONE);
+    assert(rc == 0);
+
+    ble_ll_state_set(BLE_LL_STATE_DTM);
+
+    return BLE_LL_SCHED_STATE_DONE;
+}
+
+static void
+ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, int phy_mode)
+{
+    uint32_t l;
+    uint32_t itvl_usec;
+    uint32_t itvl_ticks;
+
+    /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */
+    l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode);
+    itvl_usec = ((l + 249 + 624) / 625) * 625;
+
+    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) {
+        ctx->itvl_rem_usec = 0;
+        ++itvl_ticks;
+    }
+    ctx->itvl_ticks = itvl_ticks;
+}
+
+static int
+ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, int chan,
+                         int phy_mode)
+{
+    int rc = 0;
+    uint8_t byte_pattern;
+    struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch;
+
+    /* MSYS is big enough to get continues memory */
+    g_ble_ll_dtm_ctx.om = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr));
+    assert(g_ble_ll_dtm_ctx.om);
+
+    g_ble_ll_dtm_ctx.phy_mode = phy_mode;
+    g_ble_ll_dtm_ctx.chan = chan;
+
+    /* Set BLE transmit header */
+    ble_ll_mbuf_init(g_ble_ll_dtm_ctx.om, len, packet_payload);
+
+    switch(packet_payload) {
+    case 0x00:
+        memcpy(g_ble_ll_dtm_ctx.om->om_data, &g_ble_ll_dtm_prbs9_data, len);
+        goto schedule;
+    case 0x01:
+        byte_pattern = 0x0F;
+        break;
+    case 0x02:
+        byte_pattern = 0x55;
+        break;
+    case 0x03:
+        memcpy(g_ble_ll_dtm_ctx.om->om_data, &g_ble_ll_dtm_prbs15_data, len);
+        goto schedule;
+    case 0x04:
+        byte_pattern = 0xFF;
+        break;
+    case 0x05:
+        byte_pattern = 0x00;
+        break;
+    case 0x06:
+        byte_pattern = 0xF0;
+        break;
+    case 0x07:
+        byte_pattern = 0xAA;
+        break;
+    default:
+        return 1;
+    }
+
+    memset(g_ble_ll_dtm_ctx.om->om_data, byte_pattern, len);
+
+schedule:
+
+    sch->sched_cb = ble_ll_dtm_tx_sched_cb;
+    sch->cb_arg = &g_ble_ll_dtm_ctx;
+    sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
+    sch->start_time =  os_cputime_get32() +
+                                       os_cputime_usecs_to_ticks(5000);
+
+    /* Prepare os_event */
+    g_ble_ll_dtm_ctx.evt.ev_cb = ble_ll_dtm_event;
+    g_ble_ll_dtm_ctx.evt.ev_arg = &g_ble_ll_dtm_ctx;
+
+    ble_ll_dtm_calculate_itvl(&g_ble_ll_dtm_ctx, len, phy_mode);
+
+    /* Set some start point for TX packets */
+    rc = ble_ll_sched_dtm(sch);
+    assert(rc == 0);
+
+    g_ble_ll_dtm_ctx.active = 1;
+    return 0;
+}
+
+static int
+ble_ll_dtm_rx_start(void)
+{
+    int rc;
+
+    rc = ble_phy_setchan(g_ble_ll_dtm_ctx.chan, BLE_DTM_SYNC_WORD,
+                         BLE_DTM_CRC);
+    assert(rc == 0);
+
+    ble_phy_mode_set(g_ble_ll_dtm_ctx.phy_mode, g_ble_ll_dtm_ctx.phy_mode);
+
+    rc = ble_phy_rx_set_start_time(os_cputime_get32() +
+                                   g_ble_ll_sched_offset_ticks, 0);
+    assert(rc == 0);
+
+    ble_ll_state_set(BLE_LL_STATE_DTM);
+
+    return 0;
+}
+
+static int
+ble_ll_dtm_rx_create_ctx(int chan, int phy_mode)
+{
+    g_ble_ll_dtm_ctx.phy_mode = phy_mode;
+    g_ble_ll_dtm_ctx.chan = chan;
+    g_ble_ll_dtm_ctx.active = 1;
+
+    if (ble_ll_dtm_rx_start() != 0) {
+        assert(0);
+        return 1;
+    }
+
+    return 0;
+}
+
+static void
+ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)
+{
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    if (!ctx->active) {
+        OS_EXIT_CRITICAL(sr);
+        return;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    ble_phy_disable();
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
+#ifdef BLE_XCVR_RFCLK
+    ble_ll_xcvr_rfclk_stop();
+#endif
+
+    ble_ll_sched_rmv_elem(&ctx->sch);
+    os_mbuf_free_chain(ctx->om);
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+int
+ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced)
+{
+    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;
+
+    if (g_ble_ll_dtm_ctx.active) {
+        return BLE_ERR_CTLR_BUSY;
+    }
+
+    if (enhanced) {
+        switch (cmdbuf[3]) {
+        case BLE_HCI_LE_PHY_1M:
+            phy_mode = BLE_PHY_MODE_1M;
+            break;
+        case BLE_HCI_LE_PHY_2M:
+            phy_mode = BLE_PHY_MODE_2M;
+            break;
+        case BLE_HCI_LE_PHY_CODED_S8:
+            phy_mode = BLE_PHY_MODE_CODED_125KBPS;
+            break;
+        case BLE_HCI_LE_PHY_CODED_S2:
+            phy_mode = BLE_PHY_MODE_CODED_500KBPS;
+            break;
+        default:
+            return BLE_ERR_INV_HCI_CMD_PARMS;
+        }
+    }
+
+    if (tx_chan > 0x27 || packet_payload > 0x07) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode)) {
+        return BLE_ERR_UNSPECIFIED;
+    }
+
+    return BLE_ERR_SUCCESS;
+}
+
+int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced)
+{
+    uint8_t rx_chan = cmdbuf[0];
+    uint8_t phy_mode = BLE_PHY_MODE_1M;
+
+    if (g_ble_ll_dtm_ctx.active) {
+        return BLE_ERR_CTLR_BUSY;
+    }
+
+    /*XXX What to do with modulation cmdbuf[2]? */
+
+    if (enhanced) {
+        switch (cmdbuf[1]) {
+        case BLE_HCI_LE_PHY_1M:
+            phy_mode = BLE_PHY_MODE_1M;
+            break;
+        case BLE_HCI_LE_PHY_2M:
+            phy_mode = BLE_PHY_MODE_2M;
+            break;
+        case BLE_HCI_LE_PHY_CODED:
+            phy_mode = BLE_PHY_MODE_CODED_500KBPS;
+            break;
+        default:
+            return BLE_ERR_INV_HCI_CMD_PARMS;
+        }
+    }
+
+    if (rx_chan > 0x27) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (ble_ll_dtm_rx_create_ctx(rx_chan, phy_mode)) {
+        return BLE_ERR_UNSPECIFIED;
+    }
+
+    return BLE_ERR_SUCCESS;
+}
+
+int ble_ll_dtm_end_test(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
+{
+    put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets);
+    *rsplen = 2;
+
+    ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
+    return BLE_ERR_SUCCESS;
+}
+
+int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa)
+{
+    return 0;
+}
+
+void
+ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
+{
+    if (BLE_MBUF_HDR_CRC_OK(hdr)) {
+        /* XXX Compare data. */
+        g_ble_ll_dtm_ctx.num_of_packets++;
+    }
+
+    if (ble_ll_dtm_rx_start() != 0) {
+        assert(0);
+    }
+}
+
+int
+ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
+{
+    struct os_mbuf *rxpdu;
+
+    if (!g_ble_ll_dtm_ctx.active) {
+        return -1;
+    }
+
+    rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN);
+
+    /* Copy the received pdu and hand it up */
+    if (rxpdu) {
+        ble_phy_rxpdu_copy(rxbuf, rxpdu);
+        ble_ll_rx_pdu_in(rxpdu);
+    }
+
+    return 0;
+}
+
+void
+ble_ll_dtm_wfr_timer_exp(void)
+{
+    /* Should not be needed */
+    assert(0);
+}
+
+
+void
+ble_ll_dtm_reset(void)
+{
+    ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
+}
+#endif
diff --git a/net/nimble/controller/src/ble_ll_dtm_priv.h b/net/nimble/controller/src/ble_ll_dtm_priv.h
new file mode 100644
index 000000000..4f21a9ca9
--- /dev/null
+++ b/net/nimble/controller/src/ble_ll_dtm_priv.h
@@ -0,0 +1,36 @@
+/*
+ * 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_LL_TEST_PRIV_
+#define H_BLE_LL_TEST_PRIV_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "nimble/ble.h"
+
+int ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced);
+int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced);
+int ble_ll_dtm_end_test(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen);
+
+int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa);
+int ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
+void ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr);
+void ble_ll_dtm_wfr_timer_exp(void);
+void ble_ll_dtm_reset(void);
+#endif
diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c
index 07e89a0b1..6e29df078 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -34,6 +34,10 @@
 #include "controller/ble_ll_resolv.h"
 #include "ble_ll_conn_priv.h"
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+#include <ble_ll_dtm_priv.h>
+#endif
+
 static void ble_ll_hci_cmd_proc(struct os_event *ev);
 
 /* OS event to enqueue command */
@@ -859,6 +863,23 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
     case BLE_HCI_OCF_LE_SET_PHY:
         rc = ble_ll_conn_hci_le_set_phy(cmdbuf);
         break;
+#endif
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+    case BLE_HCI_OCF_LE_TX_TEST:
+        rc = ble_ll_dtm_tx_test(cmdbuf, false);
+        break;
+    case BLE_HCI_OCF_LE_RX_TEST:
+        rc = ble_ll_dtm_rx_test(cmdbuf, false);
+        break;
+    case BLE_HCI_OCF_LE_TEST_END:
+        rc = ble_ll_dtm_end_test(cmdbuf, rspbuf, rsplen);
+        break;
+    case BLE_HCI_OCF_LE_ENH_RX_TEST:
+        rc = ble_ll_dtm_rx_test(cmdbuf, true);
+        break;
+    case BLE_HCI_OCF_LE_ENH_TX_TEST:
+        rc = ble_ll_dtm_tx_test(cmdbuf, true);
+        break;
 #endif
     default:
         rc = BLE_ERR_UNKNOWN_HCI_CMD;
diff --git a/net/nimble/controller/src/ble_ll_sched.c b/net/nimble/controller/src/ble_ll_sched.c
index 8db9ced02..9530d906b 100644
--- a/net/nimble/controller/src/ble_ll_sched.c
+++ b/net/nimble/controller/src/ble_ll_sched.c
@@ -1432,6 +1432,66 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
 }
 #endif
 
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
+int ble_ll_sched_dtm(struct ble_ll_sched_item *sch)
+{
+    int rc;
+    os_sr_t sr;
+    struct ble_ll_sched_item *entry;
+
+    OS_ENTER_CRITICAL(sr);
+
+    if (!ble_ll_sched_insert_if_empty(sch)) {
+        /* Nothing in schedule. Schedule as soon as possible
+         * If we are here it means sch has been added to the scheduler */
+        rc = 0;
+        goto done;
+    }
+
+    /* Try to find slot for test. */
+    os_cputime_timer_stop(&g_ble_ll_sched_timer);
+    TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
+        /* We can insert if before entry in list */
+        if (sch->end_time <= entry->start_time) {
+            rc = 0;
+            TAILQ_INSERT_BEFORE(entry, sch, link);
+            sch->enqueued = 1;
+            break;
+        }
+
+        /* Check for overlapping events. For now drop if it overlaps with
+         * anything. We can make it smarter later on
+         */
+        if (ble_ll_sched_is_overlap(sch, entry)) {
+            OS_EXIT_CRITICAL(sr);
+            return -1;
+        }
+    }
+
+    if (!entry) {
+        rc = 0;
+        TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link);
+        sch->enqueued = 1;
+    }
+
+done:
+
+    /* Get head of list to restart timer */
+    sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+
+#ifdef BLE_XCVR_RFCLK
+        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+#endif
+
+    OS_EXIT_CRITICAL(sr);
+
+    /* Restart timer */
+    assert(sch != NULL);
+    os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
+
+    return rc;
+}
+#endif
 /**
  * Stop the scheduler
  *
diff --git a/net/nimble/controller/src/ble_ll_supp_cmd.c b/net/nimble/controller/src/ble_ll_supp_cmd.c
index 7383a66c2..64de46679 100644
--- a/net/nimble/controller/src/ble_ll_supp_cmd.c
+++ b/net/nimble/controller/src/ble_ll_supp_cmd.c
@@ -136,9 +136,16 @@
 #define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY   (0 << 2)
 #endif
 #define BLE_SUPP_CMD_LE_READ_SUPP_STATES    (1 << 3)
+
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 0
 #define BLE_SUPP_CMD_LE_RX_TEST             (0 << 4)
 #define BLE_SUPP_CMD_LE_TX_TEST             (0 << 5)
 #define BLE_SUPP_CMD_LE_TEST_END            (0 << 6)
+#else
+#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)
+#endif
 
 #define BLE_LL_SUPP_CMD_OCTET_28            \
 (                                           \
@@ -224,7 +231,12 @@
 #define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY     (0 << 5)
 #define BLE_SUPP_CMD_LE_SET_PHY             (0 << 6)
 #endif
+
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 0
 #define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST    (0 << 7)
+#else
+#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST    (1 << 7)
+#endif
 
 #define BLE_LL_SUPP_CMD_OCTET_35            \
 (                                           \
@@ -239,7 +251,12 @@
 )
 
 /* Octet 36 */
+#if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 0
 #define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST    (0 << 0)
+#else
+#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST    (1 << 0)
+#endif
+
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1)
 #define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR  (1 << 1)
 #define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM   (1 << 2)
diff --git a/net/nimble/controller/syscfg.yml b/net/nimble/controller/syscfg.yml
index 07c2d1b3c..00cb1e8cc 100644
--- a/net/nimble/controller/syscfg.yml
+++ b/net/nimble/controller/syscfg.yml
@@ -283,6 +283,11 @@ syscfg.defs:
             be used.
         value: "(uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}"
 
+    BLE_LL_DIRECT_TEST_MODE:
+        description: >
+             Enables HCI Test commands needed for Bluetooth SIG certification
+        value: 0
+
 syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV:
     BLE_LL_CFG_FEAT_LE_CSA2: 1
     BLE_HW_WHITELIST_ENABLE: 0
diff --git a/net/nimble/host/src/ble_hs_hci_cmd.c b/net/nimble/host/src/ble_hs_hci_cmd.c
index 7f062c48c..fa9814677 100644
--- a/net/nimble/host/src/ble_hs_hci_cmd.c
+++ b/net/nimble/host/src/ble_hs_hci_cmd.c
@@ -1179,7 +1179,7 @@ ble_hs_hci_cmd_build_le_enh_recv_test(uint8_t rx_chan, uint8_t phy,
                                       uint8_t mod_idx,
                                       uint8_t *dst, uint16_t dst_len)
 {
-    BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_RCVR_TEST_LEN);
+    BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_RX_TEST_LEN);
 
     return ble_hs_hci_cmd_body_le_enhanced_recv_test(rx_chan, phy, mod_idx, dst);
 }
@@ -1214,7 +1214,7 @@ ble_hs_hci_cmd_build_le_enh_trans_test(uint8_t tx_chan, uint8_t test_data_len,
                                        uint8_t packet_payload_idx, uint8_t phy,
                                        uint8_t *dst, uint16_t dst_len)
 {
-    BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_TRANS_TEST_LEN);
+    BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_TX_TEST_LEN);
 
     return ble_hs_hci_cmd_body_le_enhanced_trans_test(tx_chan, test_data_len,
                                                       packet_payload_idx,
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index 1907bf0d5..4dd779b44 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -138,8 +138,8 @@ extern "C" {
 #define BLE_HCI_OCF_LE_RD_PHY                       (0x0030)
 #define BLE_HCI_OCF_LE_SET_DEFAULT_PHY              (0x0031)
 #define BLE_HCI_OCF_LE_SET_PHY                      (0x0032)
-#define BLE_HCI_OCF_LE_ENH_RCVR_TEST                (0x0033)
-#define BLE_HCI_OCF_LE_ENH_TRANS_TEST               (0x0034)
+#define BLE_HCI_OCF_LE_ENH_RX_TEST                  (0x0033)
+#define BLE_HCI_OCF_LE_ENH_TX_TEST                  (0x0034)
 #define BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR         (0x0035)
 #define BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM            (0x0036)
 #define BLE_HCI_OCF_LE_SET_EXT_ADV_DATA             (0x0037)
@@ -478,13 +478,13 @@ extern "C" {
 #define BLE_HCI_LE_PHY_CODED_S8_PREF                (0x0002)
 
 /* --- LE enhanced receiver test (OCF 0x0033) */
-#define BLE_HCI_LE_ENH_RCVR_TEST_LEN                (3)
+#define BLE_HCI_LE_ENH_RX_TEST_LEN                  (3)
 #define BLE_HCI_LE_PHY_1M                           (1)
 #define BLE_HCI_LE_PHY_2M                           (2)
 #define BLE_HCI_LE_PHY_CODED                        (3)
 
 /* --- LE enhanced transmitter test (OCF 0x0034) */
-#define BLE_HCI_LE_ENH_TRANS_TEST_LEN               (4)
+#define BLE_HCI_LE_ENH_TX_TEST_LEN                  (4)
 #define BLE_HCI_LE_PHY_CODED_S8                     (3)
 #define BLE_HCI_LE_PHY_CODED_S2                     (4)
 
diff --git a/net/nimble/src/hci_common.c b/net/nimble/src/hci_common.c
index a09271457..2216e9f49 100644
--- a/net/nimble/src/hci_common.c
+++ b/net/nimble/src/hci_common.c
@@ -78,8 +78,8 @@ const uint8_t g_ble_hci_le_cmd_len[BLE_HCI_NUM_LE_CMDS] =
     BLE_HCI_LE_RD_PHY_LEN,              /* 0x0030: read maximum default PHY */
     BLE_HCI_LE_SET_DEFAULT_PHY_LEN,     /* 0x0031: set default PHY */
     BLE_HCI_LE_SET_PHY_LEN,             /* 0x0032: set PHY */
-    BLE_HCI_LE_ENH_RCVR_TEST_LEN,       /* 0x0033: enhanced receiver test */
-    BLE_HCI_LE_ENH_TRANS_TEST_LEN,      /* 0x0034: enhanced transmitter test */
+    BLE_HCI_LE_ENH_RX_TEST_LEN,       /* 0x0033: enhanced receiver test */
+    BLE_HCI_LE_ENH_TX_TEST_LEN,      /* 0x0034: enhanced transmitter test */
     BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN,/* 0x0035: set adv. set random address */
     BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN,   /* 0x0036: set ext. adv params */
     BLE_HCI_LE_SET_EXT_ADV_DATA_LEN,    /* 0x0037: set ext. adv. data */


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services