| /* |
| * Copyright (c) 2016 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdio.h> |
| |
| #include <device.h> |
| #include <uart.h> |
| |
| #include <logging/sys_log.h> |
| #include <misc/util.h> |
| |
| #include <net/buf.h> |
| #include <bluetooth/buf.h> |
| #include <bluetooth/hci_raw.h> |
| |
| #include "usb_device.h" |
| #include "usb_common.h" |
| |
| #define BTUSB_BUFFER_SIZE 64 |
| |
| /* Max packet size for endpoints */ |
| #define BTUSB_BULK_EP_MPS 64 |
| |
| #define BTUSB_ISO1_EP_MPS 0 |
| #define BTUSB_ISO2_EP_MPS 9 |
| #define BTUSB_ISO3_EP_MPS 17 |
| #define BTUSB_ISO4_EP_MPS 25 |
| #define BTUSB_ISO5_EP_MPS 33 |
| #define BTUSB_ISO6_EP_MPS 49 |
| |
| /* Max packet size for Interrupt endpoints */ |
| #define BTUSB_INTERRUPT_EP_MPS 16 |
| |
| /* Max Bluetooth command data size */ |
| #define BTUSB_CLASS_MAX_DATA_SIZE 100 |
| |
| #define INTEL_VENDOR_ID 0x8086 |
| #define PRODUCT_ID 0xFF02 /* TODO: Find better ID */ |
| #define DEVICE_RELNUM 0x0100 |
| |
| #define BTUSB_NUM_CONF 1 |
| |
| #define BTUSB_NUM_ITF 2 |
| /* Add also alternat interfaces */ |
| #define BTUSB_NUM_ITF_TOTAL (BTUSB_NUM_ITF + 5) |
| |
| #define BTUSB_IF1_NUM_EP 3 |
| #define BTUSB_IF2_NUM_EP 2 |
| /* Include all endpoints, also alternate configurations */ |
| #define BTUSB_NUM_EP (BTUSB_IF1_NUM_EP + BTUSB_IF2_NUM_EP * 6) |
| |
| #define BTUSB_ENDP_INT 0x81 |
| #define BTUSB_ENDP_BULK_OUT 0x02 |
| #define BTUSB_ENDP_BULK_IN 0x82 |
| #define BTUSB_ENDP_ISO_OUT 0x03 |
| #define BTUSB_ENDP_ISO_IN 0x83 |
| |
| #define BTUSB_CONF_SIZE (USB_CONFIGURATION_DESC_SIZE + \ |
| (BTUSB_NUM_ITF_TOTAL * USB_INTERFACE_DESC_SIZE) + \ |
| (BTUSB_NUM_EP * USB_ENDPOINT_DESC_SIZE)) |
| |
| /* Misc. macros */ |
| #define LOW_BYTE(x) ((x) & 0xFF) |
| #define HIGH_BYTE(x) ((x) >> 8) |
| |
| static struct device *btusb_dev; |
| |
| #define DEV_DATA(dev) \ |
| ((struct btusb_dev_data_t * const)(dev)->driver_data) |
| |
| static K_FIFO_DEFINE(rx_queue); |
| |
| /* HCI command buffers */ |
| #define CMD_BUF_SIZE (CONFIG_BLUETOOTH_HCI_SEND_RESERVE + \ |
| sizeof(struct bt_hci_cmd_hdr) + \ |
| CONFIG_BLUETOOTH_MAX_CMD_LEN) |
| |
| NET_BUF_POOL_DEFINE(tx_pool, CONFIG_BLUETOOTH_HCI_CMD_COUNT, CMD_BUF_SIZE, |
| sizeof(uint8_t), NULL); |
| |
| #define BT_L2CAP_MTU 64 |
| /** Data size needed for ACL buffers */ |
| #define BT_BUF_ACL_SIZE (CONFIG_BLUETOOTH_HCI_RECV_RESERVE + \ |
| sizeof(struct bt_hci_acl_hdr) + \ |
| 4 /* L2CAP header size */ + \ |
| BT_L2CAP_MTU) |
| |
| NET_BUF_POOL_DEFINE(acl_tx_pool, 2, BT_BUF_ACL_SIZE, sizeof(uint8_t), NULL); |
| |
| /* Device data structure */ |
| struct btusb_dev_data_t { |
| /* USB device status code */ |
| enum usb_dc_status_code usb_status; |
| uint8_t interface_data[BTUSB_CLASS_MAX_DATA_SIZE]; |
| uint8_t notification_sent; |
| }; |
| |
| /** |
| * Bluetooth USB descriptors configuration |
| */ |
| static const uint8_t btusb_desc[] = { |
| /* Device descriptor */ |
| USB_DEVICE_DESC_SIZE, /* Descriptor size */ |
| USB_DEVICE_DESC, /* Descriptor type */ |
| LOW_BYTE(USB_1_1), |
| HIGH_BYTE(USB_1_1), /* USB version in BCD format */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass - Interface specific */ |
| BLUETOOTH_PROTOCOL, /* Protocol - Interface specific */ |
| MAX_PACKET_SIZE0, /* Max Packet Size */ |
| LOW_BYTE(INTEL_VENDOR_ID), |
| HIGH_BYTE(INTEL_VENDOR_ID), /* Vendor Id */ |
| LOW_BYTE(PRODUCT_ID), |
| HIGH_BYTE(PRODUCT_ID), /* Product Id */ |
| LOW_BYTE(DEVICE_RELNUM), |
| HIGH_BYTE(DEVICE_RELNUM), /* Device Release Number */ |
| /* Index of Manufacturer String Descriptor */ |
| 0x01, |
| /* Index of Product String Descriptor */ |
| 0x02, |
| /* Index of Serial Number String Descriptor */ |
| 0x03, |
| BTUSB_NUM_CONF, /* Number of Possible Configuration */ |
| |
| /* Configuration descriptor */ |
| USB_CONFIGURATION_DESC_SIZE, /* Descriptor size */ |
| USB_CONFIGURATION_DESC, /* Descriptor type */ |
| /* Total length in bytes of data returned */ |
| LOW_BYTE(BTUSB_CONF_SIZE), |
| HIGH_BYTE(BTUSB_CONF_SIZE), |
| BTUSB_NUM_ITF, /* Number of interfaces */ |
| 0x01, /* Configuration value */ |
| 0x00, /* Index of the Configuration string */ |
| USB_CONFIGURATION_ATTRIBUTES, /* Attributes */ |
| MAX_LOW_POWER, /* Max power consumption */ |
| |
| /* Interface descriptor 0 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x00, /* Interface index */ |
| 0x00, /* Alternate setting */ |
| BTUSB_IF1_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint INT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_INT, /* Endpoint address */ |
| USB_DC_EP_INTERRUPT, /* Attributes */ |
| LOW_BYTE(BTUSB_INTERRUPT_EP_MPS), |
| HIGH_BYTE(BTUSB_INTERRUPT_EP_MPS),/* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_BULK_OUT, /* Endpoint address */ |
| USB_DC_EP_BULK, /* Attributes */ |
| LOW_BYTE(BTUSB_BULK_EP_MPS), |
| HIGH_BYTE(BTUSB_BULK_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_BULK_IN, /* Endpoint address */ |
| USB_DC_EP_BULK, /* Attributes */ |
| LOW_BYTE(BTUSB_BULK_EP_MPS), |
| HIGH_BYTE(BTUSB_BULK_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Interface descriptor 1:0 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x01, /* Interface index */ |
| 0x00, /* Alternate setting */ |
| BTUSB_IF2_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_OUT, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO1_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO1_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_IN, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO1_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO1_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Interface descriptor 1:1 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x01, /* Interface index */ |
| 0x01, /* Alternate setting */ |
| BTUSB_IF2_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_OUT, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO2_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO2_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_IN, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO2_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO2_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Interface descriptor 1:2 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x01, /* Interface index */ |
| 0x02, /* Alternate setting */ |
| BTUSB_IF2_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_OUT, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO3_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO3_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_IN, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO3_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO3_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Interface descriptor 1:3 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x01, /* Interface index */ |
| 0x03, /* Alternate setting */ |
| BTUSB_IF2_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_OUT, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO4_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO4_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_IN, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO4_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO4_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Interface descriptor 1:4 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x01, /* Interface index */ |
| 0x04, /* Alternate setting */ |
| BTUSB_IF2_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_OUT, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO5_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO5_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_IN, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO5_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO5_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Interface descriptor 1:5 */ |
| USB_INTERFACE_DESC_SIZE, /* Descriptor size */ |
| USB_INTERFACE_DESC, /* Descriptor type */ |
| 0x01, /* Interface index */ |
| 0x05, /* Alternate setting */ |
| BTUSB_IF2_NUM_EP, /* Number of Endpoints */ |
| WIRELESS_DEVICE_CLASS, /* Class */ |
| RF_SUBCLASS, /* SubClass */ |
| BLUETOOTH_PROTOCOL, /* Protocol */ |
| /* Index of the Interface String Descriptor */ |
| 0x00, |
| |
| /* Endpoint OUT */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_OUT, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO6_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO6_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* Endpoint IN */ |
| USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ |
| USB_ENDPOINT_DESC, /* Descriptor type */ |
| BTUSB_ENDP_ISO_IN, /* Endpoint address */ |
| USB_DC_EP_ISOCHRONOUS, /* Attributes */ |
| LOW_BYTE(BTUSB_ISO6_EP_MPS), |
| HIGH_BYTE(BTUSB_ISO6_EP_MPS), /* Max packet size */ |
| 0x01, /* Interval */ |
| |
| /* String descriptor language, only one, so min size 4 bytes. |
| * 0x0409 English(US) language code used |
| */ |
| USB_STRING_DESC_SIZE, /* Descriptor size */ |
| USB_STRING_DESC, /* Descriptor type */ |
| 0x09, |
| 0x04, |
| |
| /* Manufacturer String Descriptor "Intel" */ |
| 0x0C, |
| USB_STRING_DESC, |
| 'I', 0, 'n', 0, 't', 0, 'e', 0, 'l', 0, |
| |
| /* Product String Descriptor */ |
| 0x10, |
| USB_STRING_DESC, |
| 'Q', 0, 'U', 0, 'A', 0, 'R', 0, 'Q', 0, 'B', 0, 'T', 0, |
| |
| /* Serial Number String Descriptor "00.01" */ |
| 0x0C, |
| USB_STRING_DESC, |
| '0', 0, '0', 0, '.', 0, '0', 0, '1', 0, |
| }; |
| |
| /* TODO: move to standard utils */ |
| static void hexdump(const char *str, const uint8_t *packet, size_t length) |
| { |
| int n = 0; |
| |
| if (!length) { |
| printf("%s zero-length signal packet\n", str); |
| return; |
| } |
| |
| while (length--) { |
| if (n % 16 == 0) { |
| printf("%s %08X ", str, n); |
| } |
| |
| printf("%02X ", *packet++); |
| |
| n++; |
| if (n % 8 == 0) { |
| if (n % 16 == 0) { |
| printf("\n"); |
| } else { |
| printf(" "); |
| } |
| } |
| } |
| |
| if (n % 16) { |
| printf("\n"); |
| } |
| } |
| |
| static void btusb_int_in(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
| { |
| SYS_LOG_DBG("ep %x status %d", ep, ep_status); |
| } |
| |
| /* EP Bulk OUT handler, used to read the data received from the Host */ |
| static void btusb_bulk_out(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
| { |
| struct net_buf *buf; |
| uint32_t len, read = 0; |
| uint8_t tmp[4]; |
| |
| SYS_LOG_DBG("ep %x status %d", ep, ep_status); |
| |
| /* Read number of butes to read */ |
| usb_read(ep, NULL, 0, &len); |
| |
| if (!len || len > BT_BUF_ACL_SIZE) { |
| SYS_LOG_ERR("Incorrect length: %u\n", len); |
| return; |
| } |
| |
| buf = net_buf_alloc(&acl_tx_pool, K_NO_WAIT); |
| if (!buf) { |
| SYS_LOG_ERR("Cannot get free buffer\n"); |
| return; |
| } |
| |
| /** |
| * Quark SE USB controller is always storing data |
| * in the FIFOs per 32-bit words. |
| */ |
| while (len > buf->len) { |
| usb_read(ep, tmp, 4, NULL); |
| read += 4; |
| |
| if (len > read) { |
| net_buf_add_mem(buf, tmp, 4); |
| } else { |
| uint8_t remains = 4 - (read - len); |
| |
| net_buf_add_mem(buf, tmp, remains); |
| } |
| } |
| |
| hexdump(">", buf->data, buf->len); |
| |
| bt_buf_set_type(buf, BT_BUF_ACL_OUT); |
| |
| bt_send(buf); |
| } |
| |
| /* EP Bulk IN handler, used to send data to the Host */ |
| static void btusb_bulk_in(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
| { |
| SYS_LOG_ERR("Not implemented"); |
| } |
| |
| /* EP ISO OUT handler, used to read the data received from the Host */ |
| static void btusb_iso_out(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
| { |
| SYS_LOG_ERR("Not implemented"); |
| } |
| |
| /* EP ISO IN handler, used to send data to the Host */ |
| static void btusb_iso_in(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
| { |
| SYS_LOG_ERR("Not implemented"); |
| } |
| |
| /* Describe EndPoints configuration */ |
| static struct usb_ep_cfg_data btusb_ep[] = { |
| { |
| .ep_cb = btusb_int_in, |
| .ep_addr = BTUSB_ENDP_INT |
| }, |
| { |
| .ep_cb = btusb_bulk_out, |
| .ep_addr = BTUSB_ENDP_BULK_OUT |
| }, |
| { |
| .ep_cb = btusb_bulk_in, |
| .ep_addr = BTUSB_ENDP_BULK_IN |
| }, |
| { |
| .ep_cb = btusb_iso_out, |
| .ep_addr = BTUSB_ENDP_ISO_OUT |
| }, |
| { |
| .ep_cb = btusb_iso_in, |
| .ep_addr = BTUSB_ENDP_ISO_IN |
| }, |
| #if 0 |
| /* FIXME: check endpoints */ |
| /* Alt 1 */ |
| { |
| .ep_cb = btusb_iso_out, |
| .ep_addr = BTUSB_ENDP_ISO_OUT |
| }, |
| { |
| .ep_cb = btusb_iso_in, |
| .ep_addr = BTUSB_ENDP_ISO_IN |
| }, |
| /* Alt 2 */ |
| { |
| .ep_cb = btusb_iso_out, |
| .ep_addr = BTUSB_ENDP_ISO_OUT |
| }, |
| { |
| .ep_cb = btusb_iso_in, |
| .ep_addr = BTUSB_ENDP_ISO_IN |
| }, |
| /* Alt 3 */ |
| { |
| .ep_cb = btusb_iso_out, |
| .ep_addr = BTUSB_ENDP_ISO_OUT |
| }, |
| { |
| .ep_cb = btusb_iso_in, |
| .ep_addr = BTUSB_ENDP_ISO_IN |
| }, |
| /* Alt 4 */ |
| { |
| .ep_cb = btusb_iso_out, |
| .ep_addr = BTUSB_ENDP_ISO_OUT |
| }, |
| { |
| .ep_cb = btusb_iso_in, |
| .ep_addr = BTUSB_ENDP_ISO_IN |
| }, |
| /* Alt 5 */ |
| { |
| .ep_cb = btusb_iso_out, |
| .ep_addr = BTUSB_ENDP_ISO_OUT |
| }, |
| { |
| .ep_cb = btusb_iso_in, |
| .ep_addr = BTUSB_ENDP_ISO_IN |
| }, |
| #endif |
| }; |
| |
| static void btusb_status_cb(enum usb_dc_status_code status) |
| { |
| struct btusb_dev_data_t * const dev_data = DEV_DATA(btusb_dev); |
| |
| /* Store the new status */ |
| dev_data->usb_status = status; |
| |
| /* Check the USB status and do needed action if required */ |
| switch (status) { |
| case USB_DC_ERROR: |
| SYS_LOG_DBG("USB device error"); |
| break; |
| case USB_DC_RESET: |
| SYS_LOG_DBG("USB device reset detected"); |
| break; |
| case USB_DC_CONNECTED: |
| SYS_LOG_DBG("USB device connected"); |
| break; |
| case USB_DC_CONFIGURED: |
| SYS_LOG_DBG("USB device configured"); |
| break; |
| case USB_DC_DISCONNECTED: |
| SYS_LOG_DBG("USB device disconnected"); |
| break; |
| case USB_DC_SUSPEND: |
| SYS_LOG_DBG("USB device supended"); |
| break; |
| case USB_DC_RESUME: |
| SYS_LOG_DBG("USB device resumed"); |
| break; |
| case USB_DC_UNKNOWN: |
| default: |
| SYS_LOG_DBG("USB unknown state"); |
| break; |
| } |
| } |
| |
| static int btusb_class_handler(struct usb_setup_packet *setup, |
| int32_t *len, uint8_t **data) |
| { |
| struct net_buf *buf; |
| |
| if (!*len || *len > CMD_BUF_SIZE) { |
| SYS_LOG_ERR("Incorrect length: %u\n", len); |
| return -EINVAL; |
| } |
| |
| hexdump(">", *data, *len); |
| |
| buf = net_buf_alloc(&tx_pool, K_NO_WAIT); |
| if (!buf) { |
| SYS_LOG_ERR("Cannot get free buffer\n"); |
| return -ENOMEM; |
| } |
| |
| bt_buf_set_type(buf, BT_BUF_CMD); |
| |
| net_buf_add_mem(buf, *data, *len); |
| |
| bt_send(buf); |
| |
| return 0; |
| } |
| |
| static struct usb_cfg_data btusb_config = { |
| .usb_device_description = btusb_desc, |
| .cb_usb_status = btusb_status_cb, |
| .interface = { |
| .class_handler = btusb_class_handler, |
| .custom_handler = NULL, |
| }, |
| .num_endpoints = ARRAY_SIZE(btusb_ep), |
| .endpoint = btusb_ep, |
| }; |
| |
| static int btusb_init(struct device *dev) |
| { |
| struct btusb_dev_data_t * const dev_data = DEV_DATA(dev); |
| int ret; |
| |
| btusb_config.interface.payload_data = dev_data->interface_data; |
| btusb_dev = dev; |
| |
| /* Initialize the USB driver with the right configuration */ |
| ret = usb_set_config(&btusb_config); |
| if (ret < 0) { |
| SYS_LOG_ERR("Failed to config USB"); |
| return ret; |
| } |
| |
| /* Enable USB driver */ |
| ret = usb_enable(&btusb_config); |
| if (ret < 0) { |
| SYS_LOG_ERR("Failed to enable USB"); |
| return ret; |
| } |
| |
| return 0; |
| } |
| |
| static struct btusb_dev_data_t btusb_dev_data = { |
| .usb_status = USB_DC_UNKNOWN, |
| }; |
| |
| DEVICE_INIT(btusb, "btusb", &btusb_init, |
| &btusb_dev_data, NULL, |
| APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); |
| |
| static int try_write(uint8_t ep, struct net_buf *buf) |
| { |
| while (1) { |
| int ret = usb_write(ep, buf->data, buf->len, NULL); |
| |
| switch (ret) { |
| case -EAGAIN: |
| break; |
| /* TODO: Handle other error codes */ |
| default: |
| return ret; |
| } |
| } |
| } |
| |
| void main(void) |
| { |
| SYS_LOG_DBG("Start"); |
| |
| bt_enable_raw(&rx_queue); |
| |
| while (1) { |
| struct net_buf *buf; |
| |
| buf = net_buf_get(&rx_queue, K_FOREVER); |
| |
| hexdump("<", buf->data, buf->len); |
| |
| switch (bt_buf_get_type(buf)) { |
| case BT_BUF_EVT: |
| try_write(BTUSB_ENDP_INT, buf); |
| break; |
| case BT_BUF_ACL_IN: |
| try_write(BTUSB_ENDP_BULK_IN, buf); |
| break; |
| default: |
| SYS_LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); |
| break; |
| } |
| |
| net_buf_unref(buf); |
| } |
| } |