diff options
| author | sakumisu <[email protected]> | 2024-01-25 22:03:35 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2024-01-25 22:06:39 +0800 |
| commit | cdfb7c3fb2008ecaddac6b33decbcdb9a64b3446 (patch) | |
| tree | 2db4dcc5cb5051bf2a615545ca0337bf7abfc80d /class | |
| parent | 24511c4d4be290cd5d620ff23e5f0766a5179add (diff) | |
support hci usb h4 for usb bluetooth
Diffstat (limited to 'class')
| -rw-r--r-- | class/wireless/usbh_bluetooth.c | 178 | ||||
| -rw-r--r-- | class/wireless/usbh_bluetooth.h | 45 |
2 files changed, 173 insertions, 50 deletions
diff --git a/class/wireless/usbh_bluetooth.c b/class/wireless/usbh_bluetooth.c index d117dbe5..82a2b07e 100644 --- a/class/wireless/usbh_bluetooth.c +++ b/class/wireless/usbh_bluetooth.c @@ -10,34 +10,45 @@ static struct usbh_bluetooth g_bluetooth_class; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[512]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_event_buf[512]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_acl_buf[1024]; +#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4 +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE]; +#else +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[1 + 256]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[1 + 256]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE]; +#endif static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf) { struct usb_endpoint_descriptor *ep_desc; - int ret; + int ret = 0; +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 uint8_t mult; uint16_t mps; +#endif struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class; - if (hport->config.config_desc.bNumInterfaces == (intf + 1)) { +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 + if (intf != 0) { return 0; } +#endif memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth)); bluetooth_class->hport = hport; bluetooth_class->intf = intf; +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 bluetooth_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num; - +#endif hport->config.intf[intf].priv = bluetooth_class; for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; - +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) { if (ep_desc->bEndpointAddress & 0x80) { USBH_EP_INIT(bluetooth_class->intin, ep_desc); @@ -45,14 +56,17 @@ static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf) return -USB_ERR_NOTSUPP; } } else { +#endif if (ep_desc->bEndpointAddress & 0x80) { USBH_EP_INIT(bluetooth_class->bulkin, ep_desc); } else { USBH_EP_INIT(bluetooth_class->bulkout, ep_desc); } +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 } +#endif } - +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 USB_LOG_INFO("Num of altsettings:%u\r\n", bluetooth_class->num_of_intf_altsettings); for (uint8_t i = 0; i < bluetooth_class->num_of_intf_altsettings; i++) { @@ -77,7 +91,7 @@ static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf) return ret; } USB_LOG_INFO("Bluetooth select altsetting 0\r\n"); - +#endif snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT); USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname); usbh_bluetooth_run(bluetooth_class); @@ -102,7 +116,7 @@ static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf) if (bluetooth_class->bulkout) { usbh_kill_urb(&bluetooth_class->bulkout_urb); } - +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 if (bluetooth_class->intin) { usbh_kill_urb(&bluetooth_class->intin_urb); } @@ -114,7 +128,7 @@ static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf) // if (bluetooth_class->isoin) { // usbh_kill_urb(&bluetooth_class->isoinin_urb); // } - +#endif if (hport->config.intf[intf].devname[0] != '\0') { USB_LOG_INFO("Unregister Bluetooth Class:%s\r\n", hport->config.intf[intf].devname); usbh_bluetooth_stop(bluetooth_class); @@ -126,7 +140,94 @@ static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf) return ret; } -int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen) +#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_LOG +static void usbh_bluetooth_hci_dump(uint8_t *data, uint32_t len) +{ + uint32_t i = 0; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) { + USB_LOG_RAW("\r\n"); + } + + USB_LOG_RAW("%02x ", data[i]); + } + + USB_LOG_RAW("\r\n"); +} +#else +#define usbh_bluetooth_hci_dump(data, len) +#endif + +static int usbh_bluetooth_hci_bulk_out(uint8_t *buffer, uint32_t buflen) +{ + struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class; + struct usbh_urb *urb = &bluetooth_class->bulkout_urb; + int ret; + + usbh_bulk_urb_fill(urb, bluetooth_class->hport, bluetooth_class->bulkout, buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(urb); + if (ret == 0) { + ret = urb->actual_length; + } + return ret; +} + +#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4 +int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen) +{ + int ret; + + g_bluetooth_tx_buf[0] = hci_type; + memcpy(&g_bluetooth_tx_buf[1], buffer, buflen); + usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1); + ret = usbh_bluetooth_hci_bulk_out(g_bluetooth_tx_buf, buflen + 1); + return ret; +} + +void usbh_bluetooth_hci_rx_thread(void *argument) +{ + int ret; + uint32_t ep_mps; + uint8_t retry = 0; + uint16_t actual_len = 0; + + ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize); + + USB_LOG_INFO("Create hc rx thread\r\n"); + while (1) { + usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL); + ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb); + if (ret < 0) { + if (ret == -USB_ERR_SHUTDOWN) { + goto delete; + } else { + retry++; + if (retry == 3) { + retry = 0; + goto delete; + } + continue; + } + } + actual_len += g_bluetooth_class.bulkin_urb.actual_length; + if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) { + usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len); + usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len); + actual_len = 0; + } else { + /* read continue util read short packet */ + } + } + // clang-format off +delete : + USB_LOG_INFO("Delete hc acl rx thread\r\n"); + usb_osal_thread_delete(NULL); + // clang-format on +} + +#else +static int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen) { struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class; struct usb_setup_packet *setup = bluetooth_class->hport->setup; @@ -137,25 +238,31 @@ int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen) setup->wIndex = bluetooth_class->intf; setup->wLength = buflen; - memcpy(g_bluetooth_cmd_buf, buffer, buflen); - return usbh_control_transfer(bluetooth_class->hport, setup, g_bluetooth_cmd_buf); + return usbh_control_transfer(bluetooth_class->hport, setup, buffer); } -int usbh_bluetooth_hci_acl_out(uint8_t *buffer, uint32_t buflen) +int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen) { - struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class; - struct usbh_urb *urb = &bluetooth_class->bulkout_urb; int ret; - usbh_bulk_urb_fill(urb, bluetooth_class->hport, bluetooth_class->bulkout, buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL); - ret = usbh_submit_urb(urb); - if (ret == 0) { - ret = urb->actual_length; + if (hci_type == USB_BLUETOOTH_HCI_CMD) { + g_bluetooth_cmd_buf[0] = USB_BLUETOOTH_HCI_CMD; + memcpy(&g_bluetooth_cmd_buf[1], buffer, buflen); + usbh_bluetooth_hci_dump(g_bluetooth_cmd_buf, buflen + 1); + ret = usbh_bluetooth_hci_cmd(&g_bluetooth_cmd_buf[1], buflen); + } else if (hci_type == USB_BLUETOOTH_HCI_ACL) { + g_bluetooth_tx_buf[0] = USB_BLUETOOTH_HCI_ACL; + memcpy(&g_bluetooth_tx_buf[1], buffer, buflen); + usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1); + ret = usbh_bluetooth_hci_bulk_out(&g_bluetooth_tx_buf[1], buflen); + } else { + ret = -1; } + return ret; } -void usbh_bluetooth_hci_event_rx_thread(void *argument) +void usbh_bluetooth_hci_evt_rx_thread(void *argument) { int ret; uint32_t ep_mps; @@ -168,7 +275,7 @@ void usbh_bluetooth_hci_event_rx_thread(void *argument) USB_LOG_INFO("Create hc event rx thread\r\n"); while (1) { - usbh_int_urb_fill(&g_bluetooth_class.intin_urb, g_bluetooth_class.hport, g_bluetooth_class.intin, &g_bluetooth_event_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL); + usbh_int_urb_fill(&g_bluetooth_class.intin_urb, g_bluetooth_class.hport, g_bluetooth_class.intin, &g_bluetooth_evt_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL); ret = usbh_submit_urb(&g_bluetooth_class.intin_urb); if (ret < 0) { if (ret == -USB_ERR_SHUTDOWN) { @@ -188,7 +295,9 @@ void usbh_bluetooth_hci_event_rx_thread(void *argument) } actual_len += g_bluetooth_class.intin_urb.actual_length; if (g_bluetooth_class.intin_urb.actual_length != ep_mps) { - usbh_bluetooth_hci_rx_callback(USB_BLUETOOTH_HCI_EVT, g_bluetooth_event_buf, actual_len); + g_bluetooth_evt_buf[0] = USB_BLUETOOTH_HCI_EVT; + usbh_bluetooth_hci_dump(g_bluetooth_evt_buf, actual_len + 1); + usbh_bluetooth_hci_read_callback(g_bluetooth_evt_buf, actual_len + 1); actual_len = 0; } else { /* read continue util read short packet */ @@ -213,7 +322,7 @@ void usbh_bluetooth_hci_acl_rx_thread(void *argument) USB_LOG_INFO("Create hc acl rx thread\r\n"); while (1) { - usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_acl_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL); + usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL); ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb); if (ret < 0) { if (ret == -USB_ERR_SHUTDOWN) { @@ -229,7 +338,9 @@ void usbh_bluetooth_hci_acl_rx_thread(void *argument) } actual_len += g_bluetooth_class.bulkin_urb.actual_length; if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) { - usbh_bluetooth_hci_rx_callback(USB_BLUETOOTH_HCI_ACL_IN, g_bluetooth_acl_buf, actual_len); + g_bluetooth_rx_buf[0] = USB_BLUETOOTH_HCI_ACL; + usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len + 1); + usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len + 1); actual_len = 0; } else { /* read continue util read short packet */ @@ -241,8 +352,9 @@ delete : usb_osal_thread_delete(NULL); // clang-format on } +#endif -__WEAK void usbh_bluetooth_hci_rx_callback(uint8_t hci_type, uint8_t *data, uint32_t len) +__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len) { } @@ -269,3 +381,15 @@ CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = { .pid = 0x00, .class_driver = &bluetooth_class_driver }; + +#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4 +CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = { + .match_flags = USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, + .class = 0xff, + .subclass = 0x00, + .protocol = 0x00, + .vid = 0x2fe3, + .pid = 0x000c, + .class_driver = &bluetooth_class_driver +}; +#endif diff --git a/class/wireless/usbh_bluetooth.h b/class/wireless/usbh_bluetooth.h index 11e8e15e..c05aeb9a 100644 --- a/class/wireless/usbh_bluetooth.h +++ b/class/wireless/usbh_bluetooth.h @@ -6,27 +6,29 @@ #ifndef USBH_BLUETOOTH_H #define USBH_BLUETOOTH_H -#define USB_BLUETOOTH_HCI_CMD 0 -#define USB_BLUETOOTH_HCI_EVT 1 -#define USB_BLUETOOTH_HCI_ACL_OUT 2 -#define USB_BLUETOOTH_HCI_ACL_IN 3 -#define USB_BLUETOOTH_HCI_ISO_OUT 4 -#define USB_BLUETOOTH_HCI_ISO_IN 5 +#define USB_BLUETOOTH_HCI_NONE 0x00 +#define USB_BLUETOOTH_HCI_CMD 0x01 +#define USB_BLUETOOTH_HCI_ACL 0x02 +#define USB_BLUETOOTH_HCI_SCO 0x03 +#define USB_BLUETOOTH_HCI_EVT 0x04 +#define USB_BLUETOOTH_HCI_ISO 0x05 struct usbh_bluetooth { struct usbh_hubport *hport; + uint8_t intf; struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ - struct usb_endpoint_descriptor *intin; /* INTR endpoint */ - struct usb_endpoint_descriptor *isoin; /* Bulk IN endpoint */ - struct usb_endpoint_descriptor *isoout; /* Bulk OUT endpoint */ struct usbh_urb bulkin_urb; /* Bulk IN urb */ struct usbh_urb bulkout_urb; /* Bulk OUT urb */ - struct usbh_urb intin_urb; /* INTR IN urb */ - struct usbh_urb *isoin_urb; /* Bulk IN urb */ - struct usbh_urb *isoout_urb; /* Bulk OUT urb */ - uint8_t intf; +#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4 + struct usb_endpoint_descriptor *intin; /* INTR endpoint */ + struct usb_endpoint_descriptor *isoin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *isoout; /* Bulk OUT endpoint */ + struct usbh_urb intin_urb; /* INTR IN urb */ + struct usbh_urb *isoin_urb; /* Bulk IN urb */ + struct usbh_urb *isoout_urb; /* Bulk OUT urb */ uint8_t num_of_intf_altsettings; +#endif }; #ifdef __cplusplus @@ -36,17 +38,14 @@ extern "C" { void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class); void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class); -/* OpCode(OCF+OGF:2bytes) + ParamLength + Paramas */ -int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen); -/* Handle (12bits) + Packet_Boundary_Flag(2bits) + BC_flag(2bits) + data_len(2bytes) + data */ -int usbh_bluetooth_hci_acl_out(uint8_t *buffer, uint32_t buflen); -void usbh_bluetooth_hci_event_rx_thread(void *argument); +int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen); +void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len); +#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4 +void usbh_bluetooth_hci_rx_thread(void *argument); +#else +void usbh_bluetooth_hci_evt_rx_thread(void *argument); void usbh_bluetooth_hci_acl_rx_thread(void *argument); - -/* USB_BLUETOOTH_HCI_EVT : EventCode(1byte) + ParamLength + Parama0 + Parama1 + Parama2; - USB_BLUETOOTH_HCI_ACL : Handle (12bits) + Packet_Boundary_Flag(2bits) + BC_flag(2bits) + data_len(2bytes) + data -*/ -void usbh_bluetooth_hci_rx_callback(uint8_t hci_type, uint8_t *data, uint32_t len); +#endif #ifdef __cplusplus } |
