summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralvin <[email protected]>2026-04-17 17:23:38 +0800
committersakumisu <[email protected]>2026-04-21 10:05:15 +0800
commitfebe71b30c6786041dcf8b38d68874d76adb8749 (patch)
tree9d662e31bbc44fd3c4c46d00d94050bb02481d72
parent3bd79e23648ac522ebfe9b17768bce7ea359b4a5 (diff)
fix(third_party/bluetooth): fix bugs in USB host BT HCI drivers
NimBLE (nimble-1.6.0/ble_hci_usbh.c): - fix hci_read_callback: pass full buffer to hci_h4_sm_rx in one call instead of splitting type byte and payload into two calls - fix ble_transport_to_ll_cmd_impl: use struct ble_hci_cmd for type-safe length calculation instead of raw byte indexing - fix ble_transport_to_ll_acl_impl: gather mbuf with os_mbuf_copydata and issue single usbh_bluetooth_hci_write; the old per-segment loop violated USB Bluetooth class bulk transfer requirements - fix unused-parameter warnings in run/stop callbacks Zephyr (zephyr_bluetooth-2.7.5/ble_hci_usbh.c): - remove unreachable fallthrough comment after return statement - restore ISO payload length check (was commented out); use inline mask (& 0x3FFF) per BT Core Spec v5.x Vol 4 Part E Section 5.4.5 - fix bt_usbh_send error code: 255 -> -EIO - guard bt_hci_driver_register with static bool to prevent duplicate registration on USB reconnect - fix unused-parameter warnings in run/stop callbacks
-rw-r--r--third_party/nimble-1.6.0/ble_hci_usbh.c40
-rw-r--r--third_party/zephyr_bluetooth-2.7.5/ble_hci_usbh.c37
2 files changed, 42 insertions, 35 deletions
diff --git a/third_party/nimble-1.6.0/ble_hci_usbh.c b/third_party/nimble-1.6.0/ble_hci_usbh.c
index a0275e73..bc0d436b 100644
--- a/third_party/nimble-1.6.0/ble_hci_usbh.c
+++ b/third_party/nimble-1.6.0/ble_hci_usbh.c
@@ -8,6 +8,7 @@
#include "usbh_bluetooth.h"
#include <nimble/ble.h>
+#include "nimble/hci_common.h"
#include "nimble/transport.h"
#include "nimble/transport/hci_h4.h"
@@ -34,21 +35,14 @@ static int hci_usb_frame_cb(uint8_t pkt_type, void *data)
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
{
- size_t remaining = len;
- uint8_t pkt_indicator;
-
- pkt_indicator = *data++;
- remaining -= sizeof(pkt_indicator);
-
- hci_h4_sm_rx(&g_hci_h4sm, &pkt_indicator, 1);
- hci_h4_sm_rx(&g_hci_h4sm, data, remaining);
+ hci_h4_sm_rx(&g_hci_h4sm, data, (uint16_t)len);
}
int ble_transport_to_ll_cmd_impl(void *buf)
{
- int ret = 0;
- uint8_t *cmd_pkt_data = (uint8_t *)buf;
- size_t pkt_len = cmd_pkt_data[2] + 3;
+ const struct ble_hci_cmd *cmd = buf;
+ size_t pkt_len = sizeof(*cmd) + cmd->length;
+ int ret;
ret = usbh_bluetooth_hci_write(USB_BLUETOOTH_HCI_CMD, buf, pkt_len);
if (ret < 0) {
@@ -63,23 +57,19 @@ int ble_transport_to_ll_cmd_impl(void *buf)
int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
{
- struct os_mbuf *x = om;
- int ret = 0;
+ uint8_t buf[BLE_HCI_DATA_HDR_SZ + MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE)];
+ uint16_t pkt_len = OS_MBUF_PKTLEN(om);
+ int ret;
- while (x != NULL) {
- ret = usbh_bluetooth_hci_write(USB_BLUETOOTH_HCI_ACL, x->om_data, x->om_len);
- if (ret < 0) {
- ret = BLE_ERR_MEM_CAPACITY;
- break;
- } else {
- ret = 0;
- }
- x = SLIST_NEXT(x, om_next);
+ if (pkt_len > sizeof(buf)) {
+ os_mbuf_free_chain(om);
+ return BLE_ERR_MEM_CAPACITY;
}
+ os_mbuf_copydata(om, 0, pkt_len, buf);
+ ret = usbh_bluetooth_hci_write(USB_BLUETOOTH_HCI_ACL, buf, pkt_len);
os_mbuf_free_chain(om);
-
- return ret;
+ return ret < 0 ? BLE_ERR_MEM_CAPACITY : 0;
}
__WEAK void usbh_bluetooth_run_callback(void)
@@ -94,6 +84,7 @@ __WEAK void usbh_bluetooth_stop_callback(void)
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
{
+ (void)bluetooth_class;
hci_h4_sm_init(&g_hci_h4sm, &hci_h4_allocs_from_ll, hci_usb_frame_cb);
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
@@ -107,5 +98,6 @@ void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
{
+ (void)bluetooth_class;
usbh_bluetooth_stop_callback();
}
diff --git a/third_party/zephyr_bluetooth-2.7.5/ble_hci_usbh.c b/third_party/zephyr_bluetooth-2.7.5/ble_hci_usbh.c
index d89a08ca..233d5544 100644
--- a/third_party/zephyr_bluetooth-2.7.5/ble_hci_usbh.c
+++ b/third_party/zephyr_bluetooth-2.7.5/ble_hci_usbh.c
@@ -28,7 +28,6 @@ static inline uint8_t __bt_hci_evt_get_flags(uint8_t evt)
switch (evt) {
case BT_HCI_EVT_DISCONN_COMPLETE:
return __BT_HCI_EVT_FLAG_RECV | __BT_HCI_EVT_FLAG_RECV_PRIO;
- /* fallthrough */
#if defined(CONFIG_BT_CONN) || defined(CONFIG_BT_ISO)
case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
#if defined(CONFIG_BT_CONN)
@@ -180,11 +179,19 @@ static struct net_buf *usbh_bt_iso_recv(uint8_t *data, size_t remaining)
return NULL;
}
- // if (remaining != bt_iso_hdr_len(sys_le16_to_cpu(hdr.len))) {
- // USB_LOG_ERR("ISO payload length is not correct\r\n");
- // net_buf_unref(buf);
- // return NULL;
- // }
+ /*
+ * Per Bluetooth Core Spec v5.x Vol 4 Part E Section 5.4.5,
+ * the ISO_Data_Load_Length field occupies bits 0..13 (14 bits) of the
+ * 16-bit length field in the HCI ISO Data packet header.
+ * Bits 14..15 are RFU and must be masked out.
+ * This matches Zephyr's bt_iso_hdr_len() macro definition:
+ * #define bt_iso_hdr_len(h) ((h) & BIT_MASK(14)) // BIT_MASK(14) == 0x3FFF
+ */
+ if (remaining != (sys_le16_to_cpu(hdr.len) & 0x3FFF)) {
+ USB_LOG_ERR("ISO payload length is not correct\r\n");
+ net_buf_unref(buf);
+ return NULL;
+ }
buf_tailroom = net_buf_tailroom(buf);
if (buf_tailroom < remaining) {
@@ -274,7 +281,7 @@ static int bt_usbh_send(struct net_buf *buf)
err = usbh_bluetooth_hci_write(pkt_indicator, buf->data, buf->len);
if (err < 0) {
- err = 255;
+ err = -EIO;
} else {
err = 0;
}
@@ -306,19 +313,27 @@ __WEAK void usbh_bluetooth_stop_callback(void)
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
{
- bt_hci_driver_register(&usbh_drv);
+ static bool s_registered;
+
+ (void)bluetooth_class;
+
+ if (!s_registered) {
+ bt_hci_driver_register(&usbh_drv);
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
- usb_osal_thread_create("ble_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_bluetooth_hci_rx_thread, NULL);
+ usb_osal_thread_create("ble_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_bluetooth_hci_rx_thread, NULL);
#else
- usb_osal_thread_create("ble_evt", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_bluetooth_hci_evt_rx_thread, NULL);
- usb_osal_thread_create("ble_acl", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_bluetooth_hci_acl_rx_thread, NULL);
+ usb_osal_thread_create("ble_evt", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_bluetooth_hci_evt_rx_thread, NULL);
+ usb_osal_thread_create("ble_acl", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_bluetooth_hci_acl_rx_thread, NULL);
#endif
+ s_registered = true;
+ }
usbh_bluetooth_run_callback();
}
void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
{
+ (void)bluetooth_class;
usbh_bluetooth_stop_callback();
}