Merge branch 'master' into add-stm-hs

This commit is contained in:
hathach
2020-06-30 01:55:57 +07:00
46 changed files with 1271 additions and 248 deletions

252
src/class/bth/bth_device.c Executable file
View 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
View 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_ */

View File

@@ -222,14 +222,14 @@ void cdcd_reset(uint8_t rhport)
}
}
bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
// Only support ACM subclass
TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
// Note: 0xFF can be used with RNDIS
TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA));
TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0);
// Find available interface
cdcd_interface_t * p_cdc = NULL;
@@ -242,30 +242,30 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
break;
}
}
TU_ASSERT(p_cdc);
TU_ASSERT(p_cdc, 0);
//------------- Control Interface -------------//
p_cdc->itf_num = itf_desc->bInterfaceNumber;
uint16_t drv_len = sizeof(tusb_desc_interface_t);
uint8_t const * p_desc = tu_desc_next( itf_desc );
(*p_length) = sizeof(tusb_desc_interface_t);
// Communication Functional Descriptors
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
{
(*p_length) += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{
// notification endpoint if any
TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) );
TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 );
p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
(*p_length) += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
//------------- Data Interface (if any) -------------//
@@ -273,18 +273,19 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
{
// next to endpoint descriptor
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
// Open endpoint pair
TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) );
TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 );
(*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
drv_len += 2*sizeof(tusb_desc_endpoint_t);
}
// Prepare for incoming data
_prep_out_transaction(cdc_id);
return true;
return drv_len;
}
// Invoked when class request DATA stage is finished.

View File

@@ -229,12 +229,12 @@ static inline uint32_t tud_cdc_write_available(void)
//--------------------------------------------------------------------+
// INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+
void cdcd_init (void);
void cdcd_reset (uint8_t rhport);
bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void cdcd_init (void);
void cdcd_reset (uint8_t rhport);
uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
#ifdef __cplusplus
}

View File

@@ -56,24 +56,25 @@ void dfu_rtd_reset(uint8_t rhport)
(void) rhport;
}
bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
(void) rhport;
(void) max_len;
// Ensure this is DFU Runtime
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS);
TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT);
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS &&
itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0);
uint8_t const * p_desc = tu_desc_next( itf_desc );
(*p_length) = sizeof(tusb_desc_interface_t);
uint16_t drv_len = sizeof(tusb_desc_interface_t);
if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) )
{
(*p_length) += p_desc[DESC_OFFSET_LEN];
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
return true;
return drv_len;
}
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request)

View File

@@ -63,12 +63,12 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void dfu_rtd_init(void);
void dfu_rtd_reset(uint8_t rhport);
bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request);
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request);
bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void dfu_rtd_init(void);
void dfu_rtd_reset(uint8_t rhport);
uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request);
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request);
bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
}

View File

@@ -158,11 +158,13 @@ void hidd_reset(uint8_t rhport)
tu_memclr(_hidd_itf, sizeof(_hidd_itf));
}
bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len)
uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len)
{
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0);
uint8_t const *p_desc = (uint8_t const *) desc_itf;
// len = interface + hid + n*endpoints
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
TU_ASSERT(max_len >= drv_len, 0);
// Find available interface
hidd_interface_t * p_hid = NULL;
@@ -175,29 +177,38 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t
break;
}
}
TU_ASSERT(p_hid);
TU_ASSERT(p_hid, 0);
uint8_t const *p_desc = (uint8_t const *) desc_itf;
//------------- HID descriptor -------------//
p_desc = tu_desc_next(p_desc);
p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc;
TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType);
TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType, 0);
//------------- Endpoint Descriptor -------------//
p_desc = tu_desc_next(p_desc);
TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in));
TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0);
if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol;
p_hid->boot_mode = false; // default mode is REPORT
p_hid->itf_num = desc_itf->bInterfaceNumber;
memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2);
*p_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
// Use offsetof to avoid pointer to the odd/misaligned address
memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2);
// Prepare for output endpoint
if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
if (p_hid->ep_out)
{
if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) )
{
TU_LOG1_FAILED();
TU_BREAKPOINT();
}
}
return true;
return drv_len;
}
// Handle class control request

View File

@@ -300,12 +300,12 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void hidd_init (void);
void hidd_reset (uint8_t rhport);
bool hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void hidd_init (void);
void hidd_reset (uint8_t rhport);
uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
}

View File

@@ -290,31 +290,30 @@ void midid_reset(uint8_t rhport)
}
}
bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length)
uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len)
{
// 1st Interface is Audio Control v1
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol);
AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol, 0);
uint16_t drv_len = tu_desc_len(desc_itf);
uint8_t const * p_desc = tu_desc_next(desc_itf);
// Skip Class Specific descriptors
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
{
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
p_desc = tu_desc_next(p_desc);
}
// 2nd Interface is MIDI Streaming
TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc));
TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0);
tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc;
TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass &&
AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass &&
AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol );
AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol, 0);
// Find available interface
midid_interface_t * p_midi = NULL;
@@ -327,40 +326,46 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t
}
}
p_midi->itf_num = desc_midi->bInterfaceNumber;
p_midi->itf_num = desc_midi->bInterfaceNumber;
// next descriptor
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
p_desc = tu_desc_next(p_desc);
// Find and open endpoint descriptors
uint8_t found_endpoints = 0;
while (found_endpoints < desc_midi->bNumEndpoints)
while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) )
{
if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{
TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false);
uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
p_midi->ep_in = ep_addr;
} else {
p_midi->ep_out = ep_addr;
}
TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0);
uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
drv_len += p_desc[DESC_OFFSET_LEN];
p_desc = tu_desc_next(p_desc);
found_endpoints += 1;
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN)
{
p_midi->ep_in = ep_addr;
} else {
p_midi->ep_out = ep_addr;
}
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
found_endpoints += 1;
}
drv_len += p_desc[DESC_OFFSET_LEN];
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
*p_length = drv_len;
// Prepare for incoming data
TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false);
if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE) )
{
TU_LOG1_FAILED();
TU_BREAKPOINT();
}
return true;
return drv_len;
}
bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request)

View File

@@ -136,12 +136,12 @@ static inline bool tud_midi_send (uint8_t const packet[4])
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void midid_init (void);
void midid_reset (uint8_t rhport);
bool midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
void midid_init (void);
void midid_reset (uint8_t rhport);
uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
#ifdef __cplusplus
}

View File

@@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[])
// copy first to prevent mis-aligned access
uint32_t lba;
memcpy(&lba, &p_rdwr10->lba, 4);
// use offsetof to avoid pointer to the odd/misaligned address
memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4);
// lba is in Big Endian format
return tu_ntohl(lba);
@@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[])
// copy first to prevent mis-aligned access
uint16_t block_count;
memcpy(&block_count, &p_rdwr10->block_count, 2);
// use offsetof to avoid pointer to the odd/misaligned address
memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2);
return tu_ntohs(block_count);
}
@@ -154,25 +156,33 @@ void mscd_reset(uint8_t rhport)
tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
}
bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len)
uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
// only support SCSI's BOT protocol
TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass &&
MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol);
MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0);
// msc driver length is fixed
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
// Max length mus be at least 1 interface + 2 endpoints
TU_ASSERT(max_len >= drv_len, 0);
mscd_interface_t * p_msc = &_mscd_itf;
p_msc->itf_num = itf_desc->bInterfaceNumber;
// Open endpoint pair
TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in) );
p_msc->itf_num = itf_desc->bInterfaceNumber;
(*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 );
// Prepare for Command Block Wrapper
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) )
{
TU_LOG1_FAILED();
TU_BREAKPOINT();
}
return true;
return drv_len;
}
// Handle class control request

View File

@@ -151,12 +151,12 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void mscd_init (void);
void mscd_reset (uint8_t rhport);
bool mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request);
bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request);
bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void mscd_init (void);
void mscd_reset (uint8_t rhport);
uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request);
bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request);
bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
}

View File

@@ -135,7 +135,7 @@ void netd_reset(uint8_t rhport)
netd_init();
}
bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass &&
TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass &&
@@ -145,10 +145,10 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass &&
0x00 == itf_desc->bInterfaceProtocol);
TU_VERIFY ( is_rndis || is_ecm );
TU_VERIFY(is_rndis || is_ecm, 0);
// confirm interface hasn't already been allocated
TU_ASSERT(0 == _netd_itf.ep_notif);
TU_ASSERT(0 == _netd_itf.ep_notif, 0);
// sanity check the descriptor
_netd_itf.ecm_mode = is_ecm;
@@ -156,25 +156,25 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
//------------- Management Interface -------------//
_netd_itf.itf_num = itf_desc->bInterfaceNumber;
(*p_length) = sizeof(tusb_desc_interface_t);
uint16_t drv_len = sizeof(tusb_desc_interface_t);
uint8_t const * p_desc = tu_desc_next( itf_desc );
// Communication Functional Descriptors
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
{
(*p_length) += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
// notification endpoint (if any)
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{
TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) );
TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 );
_netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
(*p_length) += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
//------------- Data Interface -------------//
@@ -182,19 +182,19 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
// - CDC-ECM data interface has 2 alternate settings
// - 0 : zero endpoints for inactive (default)
// - 1 : IN & OUT endpoints for active networking
TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc));
TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0);
do
{
tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc;
TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass);
TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0);
(*p_length) += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) );
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) );
// Pair of endpoints
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc));
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0);
if ( _netd_itf.ecm_mode )
{
@@ -204,7 +204,7 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
}else
{
// Open endpoint pair for RNDIS
TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 );
tud_network_init_cb();
@@ -215,9 +215,9 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
tud_network_recv_renew();
}
(*p_length) += 2*sizeof(tusb_desc_endpoint_t);
drv_len += 2*sizeof(tusb_desc_endpoint_t);
return true;
return drv_len;
}
// Invoked when class request DATA stage is finished.

View File

@@ -72,13 +72,13 @@ void tud_network_xmit(struct pbuf *p);
//--------------------------------------------------------------------+
// INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+
void netd_init (void);
void netd_reset (uint8_t rhport);
bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void netd_report (uint8_t *buf, uint16_t len);
void netd_init (void);
void netd_reset (uint8_t rhport);
uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request);
bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void netd_report (uint8_t *buf, uint16_t len);
#ifdef __cplusplus
}

View File

@@ -260,37 +260,39 @@ void usbtmcd_init_cb(void)
usbtmcLock = osal_mutex_create(&usbtmcLockBuffer);
}
bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
(void)rhport;
uint16_t drv_len;
uint8_t const * p_desc;
uint8_t found_endpoints = 0;
TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS);
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS);
TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0);
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0);
#ifndef NDEBUG
// Only 2 or 3 endpoints are allowed for USBTMC.
TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3));
TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0);
#endif
TU_ASSERT(usbtmc_state.state == STATE_CLOSED);
TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0);
// Interface
(*p_length) = 0u;
drv_len = 0u;
p_desc = (uint8_t const *) itf_desc;
usbtmc_state.itf_id = itf_desc->bInterfaceNumber;
usbtmc_state.rhport = rhport;
while (found_endpoints < itf_desc->bNumEndpoints)
while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len)
{
if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
{
tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc;
switch(ep_desc->bmAttributes.xfer) {
case TUSB_XFER_BULK:
TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE);
TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE, 0);
if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN)
{
usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress;
@@ -301,45 +303,46 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
break;
case TUSB_XFER_INTERRUPT:
#ifndef NDEBUG
TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN);
TU_ASSERT(usbtmc_state.ep_int_in == 0);
TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0);
TU_ASSERT(usbtmc_state.ep_int_in == 0, 0);
#endif
usbtmc_state.ep_int_in = ep_desc->bEndpointAddress;
break;
default:
TU_ASSERT(false);
TU_ASSERT(false, 0);
}
TU_VERIFY( usbd_edpt_open(rhport, ep_desc));
TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0);
found_endpoints++;
}
(*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]);
p_desc = tu_desc_next(p_desc);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
// bulk endpoints are required, but interrupt IN is optional
#ifndef NDEBUG
TU_ASSERT(usbtmc_state.ep_bulk_in != 0);
TU_ASSERT(usbtmc_state.ep_bulk_out != 0);
TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0);
TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0);
if (itf_desc->bNumEndpoints == 2)
{
TU_ASSERT(usbtmc_state.ep_int_in == 0);
TU_ASSERT(usbtmc_state.ep_int_in == 0, 0);
}
else if (itf_desc->bNumEndpoints == 3)
{
TU_ASSERT(usbtmc_state.ep_int_in != 0);
TU_ASSERT(usbtmc_state.ep_int_in != 0, 0);
}
#if (CFG_TUD_USBTMC_ENABLE_488)
if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 ||
usbtmc_state.capabilities->bmDevCapabilities488.SR1)
{
TU_ASSERT(usbtmc_state.ep_int_in != 0);
TU_ASSERT(usbtmc_state.ep_int_in != 0, 0);
}
#endif
#endif
atomicChangeState(STATE_CLOSED, STATE_NAK);
tud_usbtmc_open_cb(itf_desc->iInterface);
return true;
return drv_len;
}
// Tell USBTMC class to set its bulk-in EP to ACK so that it can
// receive USBTMC commands.

View File

@@ -108,12 +108,12 @@ bool tud_usbtmc_start_bus_read(void);
/* "callbacks" from USB device core */
bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
void usbtmcd_reset_cb(uint8_t rhport);
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request);
bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request);
void usbtmcd_init_cb(void);
uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
void usbtmcd_reset_cb(uint8_t rhport);
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request);
bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request);
void usbtmcd_init_cb(void);
/************************************************************
* USBTMC Descriptor Templates

View File

@@ -166,9 +166,12 @@ void vendord_reset(uint8_t rhport)
}
}
bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len)
uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass);
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass, 0);
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
TU_VERIFY(max_len >= drv_len, 0);
// Find available interface
vendord_interface_t* p_vendor = NULL;
@@ -180,18 +183,21 @@ bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16
break;
}
}
TU_VERIFY(p_vendor);
TU_VERIFY(p_vendor, 0);
// Open endpoint pair with usbd helper
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in));
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0);
p_vendor->itf_num = itf_desc->bInterfaceNumber;
(*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
// Prepare for incoming data
TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)));
if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) )
{
TU_LOG1_FAILED();
TU_BREAKPOINT();
}
return true;
return drv_len;
}
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)

View File

@@ -118,10 +118,10 @@ static inline uint32_t tud_vendor_write_available (void)
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void vendord_init(void);
void vendord_reset(uint8_t rhport);
bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void vendord_init(void);
void vendord_reset(uint8_t rhport);
uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
}