Merge pull request #418 from hathach/enhance-usbd-driver-open

Enhance usbd driver open() API
This commit is contained in:
Ha Thach 2020-05-28 15:04:15 +07:00 committed by GitHub
commit b8783e10a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 214 additions and 172 deletions

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 // Only support ACM subclass
TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && 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 // 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 // Find available interface
cdcd_interface_t * p_cdc = NULL; 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; break;
} }
} }
TU_ASSERT(p_cdc); TU_ASSERT(p_cdc, 0);
//------------- Control Interface -------------// //------------- Control Interface -------------//
p_cdc->itf_num = itf_desc->bInterfaceNumber; 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 ); uint8_t const * p_desc = tu_desc_next( itf_desc );
(*p_length) = sizeof(tusb_desc_interface_t);
// Communication Functional Descriptors // 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); drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
} }
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{ {
// notification endpoint if any // 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_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
(*p_length) += tu_desc_len(p_desc); drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
} }
//------------- Data Interface (if any) -------------// //------------- 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) ) (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
{ {
// next to endpoint descriptor // 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 // 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 // Prepare for incoming data
_prep_out_transaction(cdc_id); _prep_out_transaction(cdc_id);
return true; return drv_len;
} }
// Invoked when class request DATA stage is finished. // 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 // INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void cdcd_init (void); void cdcd_init (void);
void cdcd_reset (uint8_t rhport); 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);
bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); 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_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); bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -56,24 +56,25 @@ void dfu_rtd_reset(uint8_t rhport)
(void) 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) rhport;
(void) max_len;
// Ensure this is DFU Runtime // Ensure this is DFU Runtime
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS &&
TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0);
uint8_t const * p_desc = tu_desc_next( itf_desc ); 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) ) if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) )
{ {
(*p_length) += p_desc[DESC_OFFSET_LEN]; drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(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) 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 // Internal Class Driver API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void dfu_rtd_init(void); void dfu_rtd_init(void);
void dfu_rtd_reset(uint8_t rhport); 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); 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_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_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); bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -158,11 +158,13 @@ void hidd_reset(uint8_t rhport)
tu_memclr(_hidd_itf, sizeof(_hidd_itf)); 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 // Find available interface
hidd_interface_t * p_hid = NULL; hidd_interface_t * p_hid = NULL;
@ -175,16 +177,18 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t
break; break;
} }
} }
TU_ASSERT(p_hid); TU_ASSERT(p_hid, 0);
uint8_t const *p_desc = (uint8_t const *) desc_itf;
//------------- HID descriptor -------------// //------------- HID descriptor -------------//
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) 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 -------------// //------------- Endpoint Descriptor -------------//
p_desc = tu_desc_next(p_desc); 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; if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol;
@ -192,12 +196,17 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t
p_hid->itf_num = desc_itf->bInterfaceNumber; p_hid->itf_num = desc_itf->bInterfaceNumber;
memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); 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);
// Prepare for output endpoint // 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 // 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 // Internal Class Driver API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void hidd_init (void); void hidd_init (void);
void hidd_reset (uint8_t rhport); void hidd_reset (uint8_t rhport);
bool hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); 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_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_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); bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus #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 // 1st Interface is Audio Control v1
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && 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); uint16_t drv_len = tu_desc_len(desc_itf);
uint8_t const * p_desc = tu_desc_next(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf);
// Skip Class Specific descriptors // 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); 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 // 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; tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc;
TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass &&
AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass &&
AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol ); AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol, 0);
// Find available interface // Find available interface
midid_interface_t * p_midi = NULL; 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 // next descriptor
drv_len += tu_desc_len(p_desc); 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 // Find and open endpoint descriptors
uint8_t found_endpoints = 0; 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); 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; 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;
}
drv_len += p_desc[DESC_OFFSET_LEN]; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN)
p_desc = tu_desc_next(p_desc); {
found_endpoints += 1; 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 // 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) 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 // Internal Class Driver API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void midid_init (void); void midid_init (void);
void midid_reset (uint8_t rhport); void midid_reset (uint8_t rhport);
bool midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); 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_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_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); bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -154,25 +154,33 @@ void mscd_reset(uint8_t rhport)
tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); 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 // only support SCSI's BOT protocol
TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass &&
MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && 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; mscd_interface_t * p_msc = &_mscd_itf;
p_msc->itf_num = itf_desc->bInterfaceNumber;
// Open endpoint pair // 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) ); 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 );
p_msc->itf_num = itf_desc->bInterfaceNumber;
(*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
// Prepare for Command Block Wrapper // 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 // 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 // Internal Class Driver API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void mscd_init (void); void mscd_init (void);
void mscd_reset (uint8_t rhport); void mscd_reset (uint8_t rhport);
bool mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); 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_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_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); bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -135,7 +135,7 @@ void netd_reset(uint8_t rhport)
netd_init(); 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 && bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass &&
TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && 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 && CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass &&
0x00 == itf_desc->bInterfaceProtocol); 0x00 == itf_desc->bInterfaceProtocol);
TU_VERIFY ( is_rndis || is_ecm ); TU_VERIFY(is_rndis || is_ecm, 0);
// confirm interface hasn't already been allocated // 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 // sanity check the descriptor
_netd_itf.ecm_mode = is_ecm; _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 -------------// //------------- Management Interface -------------//
_netd_itf.itf_num = itf_desc->bInterfaceNumber; _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 ); uint8_t const * p_desc = tu_desc_next( itf_desc );
// Communication Functional Descriptors // 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); drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
} }
// notification endpoint (if any) // notification endpoint (if any)
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) 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; _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
(*p_length) += tu_desc_len(p_desc); drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
} }
//------------- Data Interface -------------// //------------- 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 // - CDC-ECM data interface has 2 alternate settings
// - 0 : zero endpoints for inactive (default) // - 0 : zero endpoints for inactive (default)
// - 1 : IN & OUT endpoints for active networking // - 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 do
{ {
tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; 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); drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
}while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) ); }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) );
// Pair of endpoints // 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 ) 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 }else
{ {
// Open endpoint pair for RNDIS // 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(); 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(); 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. // 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 // INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void netd_init (void); void netd_init (void);
void netd_reset (uint8_t rhport); void netd_reset (uint8_t rhport);
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 netd_control_request (uint8_t rhport, tusb_control_request_t const * request); 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_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); 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_report (uint8_t *buf, uint16_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

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

View File

@ -108,12 +108,12 @@ bool tud_usbtmc_start_bus_read(void);
/* "callbacks" from USB device core */ /* "callbacks" from USB device core */
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 usbtmcd_reset_cb(uint8_t rhport); 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_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_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); bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request);
void usbtmcd_init_cb(void); void usbtmcd_init_cb(void);
/************************************************************ /************************************************************
* USBTMC Descriptor Templates * 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 // Find available interface
vendord_interface_t* p_vendor = NULL; 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; break;
} }
} }
TU_VERIFY(p_vendor); TU_VERIFY(p_vendor, 0);
// Open endpoint pair with usbd helper // 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_vendor->itf_num = itf_desc->bInterfaceNumber;
(*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
// Prepare for incoming data // 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) 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 // Internal Class Driver API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void vendord_init(void); void vendord_init(void);
void vendord_reset(uint8_t rhport); void vendord_reset(uint8_t rhport);
bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); 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); bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -228,6 +228,7 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize)
for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]); for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]);
} }
// Log with debug level 1 // Log with debug level 1
#define TU_LOG1 tu_printf #define TU_LOG1 tu_printf
#define TU_LOG1_MEM tu_print_mem #define TU_LOG1_MEM tu_print_mem
@ -235,6 +236,7 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize)
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) ) #define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) )
#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) ) #define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) )
#define TU_LOG1_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) #define TU_LOG1_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
#define TU_LOG1_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
// Log with debug level 2 // Log with debug level 2
#if CFG_TUSB_DEBUG > 1 #if CFG_TUSB_DEBUG > 1
@ -277,6 +279,7 @@ static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t ke
#define TU_LOG1_VAR(...) #define TU_LOG1_VAR(...)
#define TU_LOG1_INT(...) #define TU_LOG1_INT(...)
#define TU_LOG1_HEX(...) #define TU_LOG1_HEX(...)
#define TU_LOG1_FAILED()
#endif #endif
#ifndef TU_LOG2 #ifndef TU_LOG2

View File

@ -85,13 +85,13 @@ typedef struct
char const* name; char const* name;
#endif #endif
void (* init ) (void); void (* init ) (void);
void (* reset ) (uint8_t rhport); void (* reset ) (uint8_t rhport);
bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len);
bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request);
bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request);
bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void (* sof ) (uint8_t rhport); /* optional */ void (* sof ) (uint8_t rhport); /* optional */
} usbd_class_driver_t; } usbd_class_driver_t;
static usbd_class_driver_t const _usbd_driver[] = static usbd_class_driver_t const _usbd_driver[] =
@ -713,6 +713,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) );
tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc;
uint16_t const remaining_len = desc_end-p_desc;
uint8_t drv_id; uint8_t drv_id;
uint16_t drv_len; uint16_t drv_len;
@ -720,13 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
{ {
usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; usbd_class_driver_t const *driver = &_usbd_driver[drv_id];
drv_len = 0; drv_len = driver->open(rhport, desc_itf, remaining_len);
if ( driver->open(rhport, desc_itf, &drv_len) )
if ( drv_len > 0 )
{ {
// Open successfully, check if length is correct
TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len);
// Interface number must not be used already // Interface number must not be used already
TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] );
TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); TU_LOG2(" %s opened\r\n", driver->name);
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
// If IAD exist, assign all interfaces to the same driver // If IAD exist, assign all interfaces to the same driver
@ -748,8 +754,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
} }
} }
// Assert if cannot find supported driver // Failed if cannot find supported driver
TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT);
mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor