mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-22 15:40:06 +00:00
Merge pull request #413 from kasjer/kasjer/ble-over-usb
Bluetooth HCI transport over USB
This commit is contained in:
commit
5efeaf2ac1
252
src/class/bth/bth_device.c
Executable file
252
src/class/bth/bth_device.c
Executable file
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Jerzy Kasenberg
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of the TinyUSB stack.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tusb_option.h"
|
||||||
|
|
||||||
|
#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH)
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// INCLUDE
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
#include "bth_device.h"
|
||||||
|
#include <common/tusb_types.h>
|
||||||
|
#include <device/usbd_pvt.h>
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// MACRO CONSTANT TYPEDEF
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t itf_num;
|
||||||
|
uint8_t ep_ev;
|
||||||
|
uint8_t ep_acl_in;
|
||||||
|
uint8_t ep_acl_out;
|
||||||
|
uint8_t ep_voice[2]; // Not used yet
|
||||||
|
uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT];
|
||||||
|
|
||||||
|
// Endpoint Transfer buffer
|
||||||
|
CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd;
|
||||||
|
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE];
|
||||||
|
|
||||||
|
} btd_interface_t;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf;
|
||||||
|
|
||||||
|
static bool bt_tx_data(uint8_t ep, void *data, uint16_t len)
|
||||||
|
{
|
||||||
|
// skip if previous transfer not complete
|
||||||
|
TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep));
|
||||||
|
|
||||||
|
TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// READ API
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// WRITE API
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
bool tud_bt_event_send(void *event, uint16_t event_len)
|
||||||
|
{
|
||||||
|
return bt_tx_data(_btd_itf.ep_ev, event, event_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tud_bt_acl_data_send(void *event, uint16_t event_len)
|
||||||
|
{
|
||||||
|
return bt_tx_data(_btd_itf.ep_acl_in, event, event_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// USBD Driver API
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
void btd_init(void)
|
||||||
|
{
|
||||||
|
tu_memclr(&_btd_itf, sizeof(_btd_itf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void btd_reset(uint8_t rhport)
|
||||||
|
{
|
||||||
|
(void)rhport;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
|
||||||
|
{
|
||||||
|
tusb_desc_endpoint_t const *desc_ep;
|
||||||
|
uint16_t drv_len = 0;
|
||||||
|
// Size of single alternative of ISO interface
|
||||||
|
const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t);
|
||||||
|
// Size of hci interface
|
||||||
|
const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t);
|
||||||
|
// Ensure this is BT Primary Controller
|
||||||
|
TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass &&
|
||||||
|
TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass &&
|
||||||
|
TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0);
|
||||||
|
|
||||||
|
// Distinguish interface by number of endpoints, as both interface have same class, subclass and protocol
|
||||||
|
if (itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size)
|
||||||
|
{
|
||||||
|
_btd_itf.itf_num = itf_desc->bInterfaceNumber;
|
||||||
|
|
||||||
|
desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc);
|
||||||
|
|
||||||
|
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0);
|
||||||
|
TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0);
|
||||||
|
_btd_itf.ep_ev = desc_ep->bEndpointAddress;
|
||||||
|
|
||||||
|
// Open endpoint pair
|
||||||
|
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out,
|
||||||
|
&_btd_itf.ep_acl_in), 0);
|
||||||
|
|
||||||
|
// Prepare for incoming data from host
|
||||||
|
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0);
|
||||||
|
|
||||||
|
drv_len = hci_itf_size;
|
||||||
|
}
|
||||||
|
else if (itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size)
|
||||||
|
{
|
||||||
|
uint8_t dir;
|
||||||
|
|
||||||
|
desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc);
|
||||||
|
TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0);
|
||||||
|
TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0);
|
||||||
|
dir = tu_edpt_dir(desc_ep->bEndpointAddress);
|
||||||
|
_btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress;
|
||||||
|
// Store endpoint size for alternative
|
||||||
|
_btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size;
|
||||||
|
|
||||||
|
desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep);
|
||||||
|
TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0);
|
||||||
|
dir = tu_edpt_dir(desc_ep->bEndpointAddress);
|
||||||
|
_btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress;
|
||||||
|
// Store endpoint size for alternative
|
||||||
|
_btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size;
|
||||||
|
drv_len += iso_alt_itf_size;
|
||||||
|
|
||||||
|
for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) {
|
||||||
|
// Make sure rest of alternatives matches
|
||||||
|
itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep);
|
||||||
|
if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE ||
|
||||||
|
TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass ||
|
||||||
|
TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass ||
|
||||||
|
TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol)
|
||||||
|
{
|
||||||
|
// Not an Iso interface instance
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0);
|
||||||
|
|
||||||
|
desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc);
|
||||||
|
dir = tu_edpt_dir(desc_ep->bEndpointAddress);
|
||||||
|
// Verify that alternative endpoint are same as first ones
|
||||||
|
TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT &&
|
||||||
|
_btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0);
|
||||||
|
_btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size;
|
||||||
|
|
||||||
|
desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep);
|
||||||
|
dir = tu_edpt_dir(desc_ep->bEndpointAddress);
|
||||||
|
// Verify that alternative endpoint are same as first ones
|
||||||
|
TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT &&
|
||||||
|
_btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0);
|
||||||
|
_btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size;
|
||||||
|
drv_len += iso_alt_itf_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return drv_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request)
|
||||||
|
{
|
||||||
|
(void)rhport;
|
||||||
|
|
||||||
|
// Handle class request only
|
||||||
|
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||||
|
|
||||||
|
if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request)
|
||||||
|
{
|
||||||
|
(void)rhport;
|
||||||
|
|
||||||
|
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||||
|
request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE)
|
||||||
|
{
|
||||||
|
// HCI command packet addressing for single function Primary Controllers
|
||||||
|
TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0);
|
||||||
|
}
|
||||||
|
else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE)
|
||||||
|
{
|
||||||
|
if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex)
|
||||||
|
{
|
||||||
|
// TODO: Set interface it would involve changing size of endpoint size
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// HCI command packet for Primary Controller function in a composite device
|
||||||
|
TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
|
||||||
|
return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||||
|
{
|
||||||
|
(void)result;
|
||||||
|
|
||||||
|
// received new data from host
|
||||||
|
if (ep_addr == _btd_itf.ep_acl_out)
|
||||||
|
{
|
||||||
|
if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes);
|
||||||
|
|
||||||
|
// prepare for next data
|
||||||
|
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE));
|
||||||
|
}
|
||||||
|
else if (ep_addr == _btd_itf.ep_ev)
|
||||||
|
{
|
||||||
|
if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes);
|
||||||
|
}
|
||||||
|
else if (ep_addr == _btd_itf.ep_acl_in)
|
||||||
|
{
|
||||||
|
if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TUSB_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
110
src/class/bth/bth_device.h
Executable file
110
src/class/bth/bth_device.h
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Jerzy Kasenberg
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of the TinyUSB stack.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TUSB_BTH_DEVICE_H_
|
||||||
|
#define _TUSB_BTH_DEVICE_H_
|
||||||
|
|
||||||
|
#include <common/tusb_common.h>
|
||||||
|
#include <device/usbd.h>
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Class Driver Configuration
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
#ifndef CFG_TUD_BTH_EVENT_EPSIZE
|
||||||
|
#define CFG_TUD_BTH_EVENT_EPSIZE 16
|
||||||
|
#endif
|
||||||
|
#ifndef CFG_TUD_BTH_DATA_EPSIZE
|
||||||
|
#define CFG_TUD_BTH_DATA_EPSIZE 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct TU_ATTR_PACKED
|
||||||
|
{
|
||||||
|
uint16_t op_code;
|
||||||
|
uint8_t param_length;
|
||||||
|
uint8_t param[255];
|
||||||
|
} bt_hci_cmd_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Application Callback API (weak is optional)
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
// Invoked when HCI command was received over USB from Bluetooth host.
|
||||||
|
// Detailed format is described in Bluetooth core specification Vol 2,
|
||||||
|
// Part E, 5.4.1.
|
||||||
|
// Length of the command is from 3 bytes (2 bytes for OpCode,
|
||||||
|
// 1 byte for parameter total length) to 258.
|
||||||
|
TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len);
|
||||||
|
|
||||||
|
// Invoked when ACL data was received over USB from Bluetooth host.
|
||||||
|
// Detailed format is described in Bluetooth core specification Vol 2,
|
||||||
|
// Part E, 5.4.2.
|
||||||
|
// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags
|
||||||
|
// and 16 bits for data total length) to endpoint size.
|
||||||
|
TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len);
|
||||||
|
|
||||||
|
// Called when event sent with tud_bt_event_send() was delivered to BT stack.
|
||||||
|
// Controller can release/reuse buffer with Event packet at this point.
|
||||||
|
TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes);
|
||||||
|
|
||||||
|
// Called when ACL data that was sent with tud_bt_acl_data_send()
|
||||||
|
// was delivered to BT stack.
|
||||||
|
// Controller can release/reuse buffer with ACL packet at this point.
|
||||||
|
TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes);
|
||||||
|
|
||||||
|
// Bluetooth controller calls this function when it wants to send even packet
|
||||||
|
// as described in Bluetooth core specification Vol 2, Part E, 5.4.4.
|
||||||
|
// Event has at least 2 bytes, first is Event code second contains parameter
|
||||||
|
// total length. Controller can release/reuse event memory after
|
||||||
|
// tud_bt_event_sent_cb() is called.
|
||||||
|
bool tud_bt_event_send(void *event, uint16_t event_len);
|
||||||
|
|
||||||
|
// Bluetooth controller calls this to send ACL data packet
|
||||||
|
// as described in Bluetooth core specification Vol 2, Part E, 5.4.2
|
||||||
|
// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags
|
||||||
|
// and 16 bits for data total length). Upper limit is not limited
|
||||||
|
// to endpoint size since buffer is allocate by controller
|
||||||
|
// and must not be reused till tud_bt_acl_data_sent_cb() is called.
|
||||||
|
bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Internal Class Driver API
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
void btd_init (void);
|
||||||
|
void btd_reset (uint8_t rhport);
|
||||||
|
uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||||
|
bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||||
|
bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||||
|
bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _TUSB_BTH_DEVICE_H_ */
|
@ -199,6 +199,19 @@ static usbd_class_driver_t const _usbd_driver[] =
|
|||||||
.sof = NULL,
|
.sof = NULL,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_BTH
|
||||||
|
{
|
||||||
|
DRIVER_NAME("BTH")
|
||||||
|
.init = btd_init,
|
||||||
|
.reset = btd_reset,
|
||||||
|
.open = btd_open,
|
||||||
|
.control_request = btd_control_request,
|
||||||
|
.control_complete = btd_control_complete,
|
||||||
|
.xfer_cb = btd_xfer_cb,
|
||||||
|
.sof = NULL
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
|
enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
|
||||||
@ -507,6 +520,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
|
|||||||
{
|
{
|
||||||
//------------- Device Requests e.g in enumeration -------------//
|
//------------- Device Requests e.g in enumeration -------------//
|
||||||
case TUSB_REQ_RCPT_DEVICE:
|
case TUSB_REQ_RCPT_DEVICE:
|
||||||
|
if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type )
|
||||||
|
{
|
||||||
|
uint8_t const itf = tu_u16_low(p_request->wIndex);
|
||||||
|
TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
|
||||||
|
|
||||||
|
uint8_t const drvid = _usbd_dev.itf2drv[itf];
|
||||||
|
TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
|
||||||
|
|
||||||
|
// forward to class driver: "non-STD request to Interface"
|
||||||
|
TU_VERIFY(invoke_class_control(rhport, drvid, p_request));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
|
if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
|
||||||
{
|
{
|
||||||
// Non standard request is not supported
|
// Non standard request is not supported
|
||||||
|
@ -448,6 +448,60 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
|||||||
/* Endpoint Out */\
|
/* Endpoint Out */\
|
||||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
|
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
|
||||||
|
|
||||||
|
//------------- BT Radio -------------//
|
||||||
|
#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER)
|
||||||
|
#define TUD_BT_APP_SUBCLASS 0x01
|
||||||
|
#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01
|
||||||
|
#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02
|
||||||
|
|
||||||
|
#ifndef CFG_TUD_BTH_ISO_ALT_COUNT
|
||||||
|
#define CFG_TUD_BTH_ISO_ALT_COUNT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Length of template descriptor: 30 bytes + number of ISO alternatives * 23
|
||||||
|
#define TUD_BTH_DESC_LEN (9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7))
|
||||||
|
|
||||||
|
/* Primary Interface */
|
||||||
|
#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \
|
||||||
|
9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \
|
||||||
|
/* Endpoint In for events */ \
|
||||||
|
7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \
|
||||||
|
/* Endpoint In for ACL data */ \
|
||||||
|
7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \
|
||||||
|
/* Endpoint Out for ACL data */ \
|
||||||
|
7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1
|
||||||
|
|
||||||
|
#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\
|
||||||
|
/* Interface with 2 endpoints */ \
|
||||||
|
9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \
|
||||||
|
/* Isochronous endpoints */ \
|
||||||
|
7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \
|
||||||
|
7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1
|
||||||
|
|
||||||
|
#define _FIRST(a, ...) a
|
||||||
|
#define _REST(a, ...) __VA_ARGS__
|
||||||
|
|
||||||
|
#define TUD_BTH_ISO_ITF_0(_itfnum, ...)
|
||||||
|
#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__))
|
||||||
|
#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \
|
||||||
|
TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__))
|
||||||
|
#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \
|
||||||
|
TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__))
|
||||||
|
#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \
|
||||||
|
TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__))
|
||||||
|
#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \
|
||||||
|
TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__))
|
||||||
|
#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \
|
||||||
|
TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \
|
||||||
|
TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__)
|
||||||
|
|
||||||
|
// BT Primary controller descriptor
|
||||||
|
// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes
|
||||||
|
#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \
|
||||||
|
TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \
|
||||||
|
TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,10 @@
|
|||||||
#if CFG_TUD_NET
|
#if CFG_TUD_NET
|
||||||
#include "class/net/net_device.h"
|
#include "class/net/net_device.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_BTH
|
||||||
|
#include "class/bth/bth_device.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,6 +219,10 @@
|
|||||||
#define CFG_TUD_NET 0
|
#define CFG_TUD_NET 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CFG_TUD_BTH
|
||||||
|
#define CFG_TUD_BTH 0
|
||||||
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// HOST OPTIONS
|
// HOST OPTIONS
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user