From febe71b30c6786041dcf8b38d68874d76adb8749 Mon Sep 17 00:00:00 2001 From: alvin Date: Fri, 17 Apr 2026 17:23:38 +0800 Subject: 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 --- third_party/nimble-1.6.0/ble_hci_usbh.c | 40 +++++++++-------------- third_party/zephyr_bluetooth-2.7.5/ble_hci_usbh.c | 37 ++++++++++++++------- 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 +#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(); } -- cgit v1.3.1