You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2020/06/01 06:38:35 UTC

[mynewt-nimble] branch master updated (7f7b49a -> e99e394)

This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git.


    from 7f7b49a  apps/bttester: Disable connection retry by default
     new c5d0ffc  nimble/transport: Add transport for USB
     new e99e394  nimble/transport: Add 'usb' to transport choices

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 nimble/transport/pkg.yml                    |   3 +
 nimble/transport/syscfg.yml                 |   1 +
 nimble/transport/{uart => usb}/pkg.yml      |   7 +-
 nimble/transport/usb/src/ble_hci_usb.c      | 422 ++++++++++++++++++++++++++++
 nimble/transport/{socket => usb}/syscfg.yml |  34 +--
 5 files changed, 436 insertions(+), 31 deletions(-)
 copy nimble/transport/{uart => usb}/pkg.yml (87%)
 create mode 100644 nimble/transport/usb/src/ble_hci_usb.c
 copy nimble/transport/{socket => usb}/syscfg.yml (72%)


[mynewt-nimble] 01/02: nimble/transport: Add transport for USB

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit c5d0ffc2f759dbb1af68ffdf7922d731b6d67f73
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue May 19 13:14:03 2020 +0200

    nimble/transport: Add transport for USB
    
    NimBLE controller can now be used with USB transport.
---
 nimble/transport/usb/pkg.yml           |  39 +++
 nimble/transport/usb/src/ble_hci_usb.c | 422 +++++++++++++++++++++++++++++++++
 nimble/transport/usb/syscfg.yml        |  57 +++++
 3 files changed, 518 insertions(+)

diff --git a/nimble/transport/usb/pkg.yml b/nimble/transport/usb/pkg.yml
new file mode 100644
index 0000000..49317c9
--- /dev/null
+++ b/nimble/transport/usb/pkg.yml
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+
+pkg.name: nimble/transport/usb
+pkg.description: Provides HCI transport over USB interface
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+    - usb
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/util/mem"
+    - nimble
+
+pkg.apis:
+    - ble_transport
+
+pkg.init:
+    ble_hci_usb_init: 'MYNEWT_VAL(BLE_TRANS_USB_SYSINIT_STAGE)'
diff --git a/nimble/transport/usb/src/ble_hci_usb.c b/nimble/transport/usb/src/ble_hci_usb.c
new file mode 100644
index 0000000..31e62ed
--- /dev/null
+++ b/nimble/transport/usb/src/ble_hci_usb.c
@@ -0,0 +1,422 @@
+/*
+ * 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 <assert.h>
+#include <stddef.h>
+#include "syscfg/syscfg.h"
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "mem/mem.h"
+
+#include "nimble/ble.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+
+#include <class/bth/bth_device.h>
+
+/*
+ * The MBUF payload size must accommodate the HCI data header size plus the
+ * maximum ACL data packet length. The ACL block size is the size of the
+ * mbufs we will allocate.
+ */
+#define ACL_BLOCK_SIZE  OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
+                                 + BLE_MBUF_MEMBLOCK_OVERHEAD \
+                                 + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+struct usb_ble_hci_pool_cmd {
+    uint8_t cmd[BLE_HCI_TRANS_CMD_SZ];
+    bool allocated;
+};
+
+/* (Pseudo)pool for HCI commands */
+static struct usb_ble_hci_pool_cmd usb_ble_hci_pool_cmd;
+
+static ble_hci_trans_rx_cmd_fn *ble_hci_usb_rx_cmd_ll_cb;
+static void *ble_hci_usb_rx_cmd_ll_arg;
+
+static ble_hci_trans_rx_acl_fn *ble_hci_usb_rx_acl_ll_cb;
+static void *ble_hci_usb_rx_acl_ll_arg;
+
+static struct os_mempool ble_hci_usb_evt_hi_pool;
+static os_membuf_t ble_hci_usb_evt_hi_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                    MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+static struct os_mempool ble_hci_usb_evt_lo_pool;
+static os_membuf_t ble_hci_usb_evt_lo_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                    MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+static uint8_t ble_hci_pool_acl_mempool_buf[
+    OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                     ACL_BLOCK_SIZE)];
+static struct os_mempool ble_hci_pool_acl_mempool;
+static struct os_mbuf_pool ble_hci_pool_acl_mbuf_pool;
+
+static struct os_mbuf *incoming_acl_data;
+
+static struct os_mbuf *
+ble_hci_trans_acl_buf_alloc(void)
+{
+    struct os_mbuf *m;
+
+    m = os_mbuf_get_pkthdr(&ble_hci_pool_acl_mbuf_pool,
+                           sizeof(struct ble_mbuf_hdr));
+    return m;
+}
+
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+                     void *cmd_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb,
+                     void *acl_arg)
+{
+    ble_hci_usb_rx_cmd_ll_cb = cmd_cb;
+    ble_hci_usb_rx_cmd_ll_arg = cmd_arg;
+    ble_hci_usb_rx_acl_ll_cb = acl_cb;
+    ble_hci_usb_rx_acl_ll_arg = acl_arg;
+}
+
+int
+ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
+{
+    int rc;
+
+    assert(ble_hci_usb_rx_acl_ll_cb != NULL);
+
+    rc = ble_hci_usb_rx_acl_ll_cb(om, ble_hci_usb_rx_acl_ll_arg);
+
+    return rc;
+}
+
+#define BLE_HCI_USB_EVT_COUNT  \
+    (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
+
+/**
+ * A packet to be sent over the USB.  This can be a command, an event, or ACL
+ * data.
+ */
+struct ble_hci_pkt {
+    STAILQ_ENTRY(ble_hci_pkt) next;
+    void *data;
+};
+
+static struct os_mempool ble_hci_pkt_pool;
+static os_membuf_t ble_hci_pkt_buf[
+    OS_MEMPOOL_SIZE(BLE_HCI_USB_EVT_COUNT + 1 +
+                    MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+                    sizeof(struct ble_hci_pkt))];
+
+struct tx_queue {
+    STAILQ_HEAD(, ble_hci_pkt) queue;
+};
+
+static struct tx_queue ble_hci_tx_acl_queue = {STAILQ_HEAD_INITIALIZER(ble_hci_tx_acl_queue.queue)};
+static struct tx_queue ble_hci_tx_evt_queue = { STAILQ_HEAD_INITIALIZER(ble_hci_tx_evt_queue.queue) };
+
+/*
+ * TinyUSB callbacks.
+ */
+void
+tud_bt_acl_data_sent_cb(uint16_t sent_bytes)
+{
+    struct os_mbuf *om;
+    struct ble_hci_pkt *curr_acl;
+    struct ble_hci_pkt *next_acl;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    curr_acl = STAILQ_FIRST(&ble_hci_tx_acl_queue.queue);
+    OS_EXIT_CRITICAL(sr);
+
+    assert(curr_acl != NULL);
+    om = curr_acl->data;
+    assert(om != NULL && om->om_len >= sent_bytes);
+    os_mbuf_adj(om, sent_bytes);
+
+    while (om != NULL && om->om_len == 0) {
+        curr_acl->data = SLIST_NEXT(om, om_next);
+        os_mbuf_free(om);
+        om = curr_acl->data;
+    }
+
+    if (om == NULL) {
+        OS_ENTER_CRITICAL(sr);
+        STAILQ_REMOVE_HEAD(&ble_hci_tx_acl_queue.queue, next);
+        next_acl = STAILQ_FIRST(&ble_hci_tx_acl_queue.queue);
+        OS_EXIT_CRITICAL(sr);
+        os_memblock_put(&ble_hci_pkt_pool, curr_acl);
+        if (next_acl != NULL) {
+            om = next_acl->data;
+        }
+    }
+
+    if (om != NULL) {
+        tud_bt_acl_data_send(om->om_data, om->om_len);
+    }
+}
+
+void
+tud_bt_event_sent_cb(uint16_t sent_bytes)
+{
+    struct ble_hci_pkt *curr_evt;
+    struct ble_hci_pkt *next_evt;
+    uint8_t *hci_ev;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    curr_evt = STAILQ_FIRST(&ble_hci_tx_evt_queue.queue);
+    OS_EXIT_CRITICAL(sr);
+    assert(curr_evt != NULL);
+    hci_ev = curr_evt->data;
+
+    assert(hci_ev != NULL && hci_ev[1] + sizeof(struct ble_hci_ev) == sent_bytes);
+
+    ble_hci_trans_buf_free(hci_ev);
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_REMOVE_HEAD(&ble_hci_tx_evt_queue.queue, next);
+    next_evt = STAILQ_FIRST(&ble_hci_tx_evt_queue.queue);
+    OS_EXIT_CRITICAL(sr);
+    os_memblock_put(&ble_hci_pkt_pool, curr_evt);
+
+    if (next_evt != NULL) {
+        hci_ev = next_evt->data;
+        tud_bt_event_send(hci_ev, hci_ev[1] + sizeof(struct ble_hci_ev));
+    }
+}
+
+void
+tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len)
+{
+    uint8_t *data;
+    uint32_t len;
+    struct os_mbuf *om = incoming_acl_data;
+    int rc;
+
+    if (om == NULL) {
+        om = ble_hci_trans_acl_buf_alloc();
+        assert(om != NULL);
+    }
+    assert(om->om_len + data_len <= MYNEWT_VAL(BLE_ACL_BUF_SIZE) + BLE_HCI_DATA_HDR_SZ);
+
+    os_mbuf_append(om, acl_data, data_len);
+    incoming_acl_data = om;
+    if (om->om_len > BLE_HCI_DATA_HDR_SZ) {
+        data = incoming_acl_data->om_data;
+        len = data[2] + (data[3] << 8) + BLE_HCI_DATA_HDR_SZ;
+        if (len >= incoming_acl_data->om_len) {
+            incoming_acl_data = NULL;
+            rc = ble_hci_usb_rx_acl_ll_cb(om, ble_hci_usb_rx_acl_ll_arg);
+            (void)rc;
+        }
+    }
+}
+
+void
+tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len)
+{
+    uint8_t *buf;
+    int rc = -1;
+
+    assert(ble_hci_usb_rx_cmd_ll_cb);
+    if (ble_hci_usb_rx_cmd_ll_cb) {
+        buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+        assert(buf != NULL);
+        memcpy(buf, hci_cmd, cmd_len);
+
+        rc = ble_hci_usb_rx_cmd_ll_cb(buf, ble_hci_usb_rx_cmd_ll_arg);
+    }
+
+    if (rc != 0) {
+        ble_hci_trans_buf_free(buf);
+    }
+}
+
+static int
+ble_hci_trans_ll_tx(struct tx_queue *queue, struct os_mbuf *om)
+{
+    struct ble_hci_pkt *pkt;
+    os_sr_t sr;
+    bool first;
+
+    /* If this packet is zero length, just free it */
+    if (OS_MBUF_PKTLEN(om) == 0) {
+        os_mbuf_free_chain(om);
+        return 0;
+    }
+
+    pkt = os_memblock_get(&ble_hci_pkt_pool);
+    if (pkt == NULL) {
+        os_mbuf_free_chain(om);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    pkt->data = om;
+    OS_ENTER_CRITICAL(sr);
+    first = STAILQ_EMPTY(&queue->queue);
+    STAILQ_INSERT_TAIL(&queue->queue, pkt, next);
+    OS_EXIT_CRITICAL(sr);
+    if (first) {
+        tud_bt_acl_data_send(om->om_data, om->om_len);
+    }
+
+    return 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+    return ble_hci_trans_ll_tx(&ble_hci_tx_acl_queue, om);
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
+{
+    struct ble_hci_pkt *pkt;
+    os_sr_t sr;
+    bool first;
+
+    assert(hci_ev != NULL);
+
+    pkt = os_memblock_get(&ble_hci_pkt_pool);
+    if (pkt == NULL) {
+        ble_hci_trans_buf_free(hci_ev);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    pkt->data = hci_ev;
+    OS_ENTER_CRITICAL(sr);
+    first = STAILQ_EMPTY(&ble_hci_tx_evt_queue.queue);
+    STAILQ_INSERT_TAIL(&ble_hci_tx_evt_queue.queue, pkt, next);
+    OS_EXIT_CRITICAL(sr);
+    if (first) {
+        tud_bt_event_send(hci_ev, hci_ev[1] + sizeof(struct ble_hci_ev));
+    }
+
+    return 0;
+}
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+    uint8_t *buf;
+
+    switch (type) {
+    case BLE_HCI_TRANS_BUF_CMD:
+        assert(!usb_ble_hci_pool_cmd.allocated);
+        usb_ble_hci_pool_cmd.allocated = 1;
+        buf = usb_ble_hci_pool_cmd.cmd;
+        break;
+
+    case BLE_HCI_TRANS_BUF_EVT_HI:
+        buf = os_memblock_get(&ble_hci_usb_evt_hi_pool);
+        if (buf == NULL) {
+            /* If no high-priority event buffers remain, try to grab a
+             * low-priority one.
+             */
+            buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+        }
+        break;
+
+    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&ble_hci_usb_evt_lo_pool);
+        break;
+
+    default:
+        assert(0);
+        buf = NULL;
+    }
+
+    return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+    int rc;
+
+    /* XXX: this may look a bit odd, but the controller uses the command
+     * buffer to send back the command complete/status as an immediate
+     * response to the command. This was done to insure that the controller
+     * could always send back one of these events when a command was received.
+     * Thus, we check to see which pool the buffer came from so we can free
+     * it to the appropriate pool
+     */
+    if (os_memblock_from(&ble_hci_usb_evt_hi_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_usb_evt_hi_pool, buf);
+        assert(rc == 0);
+    } else if (os_memblock_from(&ble_hci_usb_evt_lo_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_usb_evt_lo_pool, buf);
+        assert(rc == 0);
+    } else {
+        assert(usb_ble_hci_pool_cmd.allocated);
+        usb_ble_hci_pool_cmd.allocated = 0;
+    }
+    (void)rc;
+}
+
+int
+ble_hci_trans_reset(void)
+{
+    return 0;
+}
+
+void
+ble_hci_usb_init(void)
+{
+    int rc;
+
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = mem_init_mbuf_pool(ble_hci_pool_acl_mempool_buf, &ble_hci_pool_acl_mempool, &ble_hci_pool_acl_mbuf_pool,
+                            MYNEWT_VAL(BLE_ACL_BUF_COUNT), ACL_BLOCK_SIZE, "ble_hci_acl");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_usb_evt_hi_pool,
+                         MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_usb_evt_hi_buf,
+                         "ble_hci_usb_evt_hi_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_usb_evt_lo_pool,
+                         MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_usb_evt_lo_buf,
+                         "ble_hci_usb_evt_lo_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    /*
+     * Create memory pool of packet list nodes. NOTE: the number of these
+     * buffers should be, at least, the total number of event buffers (hi
+     * and lo), the number of command buffers (currently 1) and the total
+     * number of buffers that the controller could possibly hand to the host.
+     */
+    rc = os_mempool_init(&ble_hci_pkt_pool,
+                         BLE_HCI_USB_EVT_COUNT + 1 +
+                         MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+                         sizeof (struct ble_hci_pkt),
+                         ble_hci_pkt_buf,
+                         "ble_hci_usb_pkt_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+}
diff --git a/nimble/transport/usb/syscfg.yml b/nimble/transport/usb/syscfg.yml
new file mode 100644
index 0000000..ebc261a
--- /dev/null
+++ b/nimble/transport/usb/syscfg.yml
@@ -0,0 +1,57 @@
+# 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.
+#
+
+syscfg.defs:
+    BLE_HCI_EVT_BUF_SIZE:
+        description: 'The size of the allocated event buffers'
+        value: 70
+    BLE_HCI_EVT_HI_BUF_COUNT:
+        description: 'The number of high priority event buffers'
+        value: 8
+    BLE_HCI_EVT_LO_BUF_COUNT:
+        description: 'The number of low priority event buffers'
+        value: 8
+    BLE_ACL_BUF_COUNT:
+        description: 'The number of ACL data buffers'
+        value: 12
+    BLE_ACL_BUF_SIZE:
+        description: >
+            This is the maximum size of the data portion of HCI ACL data
+            packets. It does not include the HCI data header (of 4 bytes).
+        value: 255
+
+    BLE_HCI_ACL_OUT_COUNT:
+        description: >
+            This count is used in creating a pool of elements used by the
+            code to enqueue various elements. In the case of the controller
+            only HCI, this number should be equal to the number of mbufs in
+            the msys pool. For host only, it is really dependent on the
+            number of ACL buffers that the controller tells the host it
+            has.
+        value: 12
+
+    BLE_TRANS_USB_SYSINIT_STAGE:
+        description: >
+            Sysinit stage for the USB BLE transport.
+        value: 500
+
+syscfg.vals.BLE_EXT_ADV:
+    BLE_HCI_EVT_BUF_SIZE: 257
+
+syscfg.restrictions:
+    - '!BLE_HOST'


[mynewt-nimble] 02/02: nimble/transport: Add 'usb' to transport choices

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit e99e394c0ab0f72ceac06feaf220a387b2e42916
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue May 19 13:12:54 2020 +0200

    nimble/transport: Add 'usb' to transport choices
---
 nimble/transport/pkg.yml    | 3 +++
 nimble/transport/syscfg.yml | 1 +
 2 files changed, 4 insertions(+)

diff --git a/nimble/transport/pkg.yml b/nimble/transport/pkg.yml
index 2bc4ac2..3bfca88 100644
--- a/nimble/transport/pkg.yml
+++ b/nimble/transport/pkg.yml
@@ -43,3 +43,6 @@ pkg.deps.'BLE_HCI_TRANSPORT == "uart"':
 
 pkg.deps.'BLE_HCI_TRANSPORT == "da1469x"':
     - nimble/transport/da1469x
+
+pkg.deps.'BLE_HCI_TRANSPORT == "usb"':
+    - nimble/transport/usb
diff --git a/nimble/transport/syscfg.yml b/nimble/transport/syscfg.yml
index 137d6e9..96ea2c2 100644
--- a/nimble/transport/syscfg.yml
+++ b/nimble/transport/syscfg.yml
@@ -33,6 +33,7 @@ syscfg.defs:
             - socket    # Socket transport (for native builds)
             - emspi     # SPI transport for EM Microelectionic controllers
             - da1469x   # Dialog DA1469x integrated controller
+            - usb       # USB
 
 # Deprecated settings
     BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: