From 0b39168dc25ad970a9829ada2c0e6af26cb0d1ed Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 15:40:53 +0700 Subject: [PATCH 1/2] add IAD for CDC ECM, remove EEM descriptor template --- src/device/usbd.h | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/device/usbd.h b/src/device/usbd.h index acefb6943..3b409e70b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -343,11 +343,13 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- CDC-ECM -------------// // Length of template descriptor: 71 bytes -#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+9+7+7) +#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ /* CDC Control Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ /* CDC-ECM Header */\ @@ -410,22 +412,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- CDC-EEM -------------// - -// Length of template descriptor: 23 bytes -#define TUD_CDC_EEM_DESC_LEN (9+7+7) - -// CDC-EEM Descriptor Template -// Interface number, description string index, EP data address (out, in) and size. -#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* EEM Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - - #ifdef __cplusplus } #endif From d315393fbb39ab6a70ea2c636d28305d9777ff97 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 16:18:24 +0700 Subject: [PATCH 2/2] use IAD to assign itf2drv mapping correctly merge net_data back into net driver --- src/class/cdc/cdc_device.c | 4 +- src/class/net/net_device.c | 30 +++------- src/class/net/net_device.h | 2 - src/device/usbd.c | 112 ++++++++++++++++++------------------- 4 files changed, 63 insertions(+), 85 deletions(-) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 04c73da78..95b14ba54 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -262,12 +262,12 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8d0cb5d37..8bbce2305 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -117,10 +117,6 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } -void netd_init_data(void) -{ -} - void netd_reset(uint8_t rhport) { (void) rhport; @@ -166,32 +162,21 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } - return true; -} - -bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) -{ - TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); - //------------- Data Interface -------------// - while ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // TODO extract Alt Interface 0 & 1 + while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - (*p_length) += sizeof(tusb_desc_interface_t); } - if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); @@ -207,6 +192,7 @@ bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint // prepare for incoming packets tud_network_recv_renew(); + return true; } diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 6914ed050..67cd99933 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,10 +73,8 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); -void netd_init_data (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_open_data (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); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4587a2cc7..ad5a32f92 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -188,9 +188,8 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET - /* RNDIS management interface */ { - DRIVER_NAME("RNDIS") + DRIVER_NAME("NET") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -199,30 +198,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, - - /* CDC-ECM management interface */ - { - DRIVER_NAME("CDC-ECM") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_request = netd_control_request, - .control_complete = netd_control_complete, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - - /* RNDIS/CDC-ECM data interface */ - { - DRIVER_NAME("CDC-DATA") - .init = netd_init_data, - .reset = NULL, - .open = netd_open_data, - .control_request = NULL, - .control_complete = NULL, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, #endif }; @@ -611,9 +586,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_SET_INTERFACE: { uint8_t const alternate = (uint8_t) p_request->wValue; + (void) alternate; // TODO not support alternate interface yet - TU_ASSERT(alternate == 0); +// TU_ASSERT(alternate == 0); tud_control_status(rhport, p_request); } break; @@ -727,41 +703,59 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - // Each interface always starts with Interface or Association descriptor + tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + + // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - p_desc = tu_desc_next(p_desc); // ignore Interface Association - }else - { - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; - - uint8_t drv_id; - uint16_t drv_len; - - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) - { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) - { - // Interface number must not be used already TODO alternate interface - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - break; - } - } - - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); - - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor - - p_desc += drv_len; // next interface + desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to Interface } + + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint8_t drv_id; + uint16_t drv_len; + + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + drv_len = 0; + if ( driver->open(rhport, desc_itf, &drv_len) ) + { + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + + TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + // If IAD exist, assign all interfaces to the same driver + if (desc_itf_assoc) + { + // IAD's first interface number and class/subclass/protocol should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && + desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && + desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + + for(uint8_t i=1; ibInterfaceCount; i++) + { + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; + } + } + + break; + } + } + + // Assert if cannot find supported driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + + p_desc += drv_len; // next interface } // invoke callback