From 672057de5a6feb854eb4f1a1e21766127be75728 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 15 Nov 2013 17:20:40 +0700 Subject: [PATCH] IAD support --- .../device/device_os_none/tusb_descriptors.c | 24 ++++++++-------- .../device/device_os_none/tusb_descriptors.h | 2 +- tinyusb/common/tusb_types.h | 8 ++++++ tinyusb/device/dcd_lpc_11uxx_13uxx.c | 10 +------ tinyusb/device/usbd.c | 28 +++++++++++-------- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/demos/device/device_os_none/tusb_descriptors.c b/demos/device/device_os_none/tusb_descriptors.c index fec41e65..78c2ab30 100644 --- a/demos/device/device_os_none/tusb_descriptors.c +++ b/demos/device/device_os_none/tusb_descriptors.c @@ -135,18 +135,19 @@ tusb_descriptor_device_t app_tusb_desc_device = .bDescriptorType = TUSB_DESC_TYPE_DEVICE, .bcdUSB = 0x0200, #if IAD_DESC_REQUIRED - /* Multiple Interfaces Using Interface Association Descriptor (IAD) */ - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = TUSB_CLASS_CDC, - .bDeviceProtocol = 1, + // Multiple Interfaces Using Interface Association Descriptor (IAD) + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, #elif TUSB_CFG_DEVICE_CDC - .bDeviceClass = TUSB_CLASS_CDC, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, + .bDeviceClass = TUSB_CLASS_CDC, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, #else - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, #endif .bMaxPacketSize0 = TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE, @@ -186,13 +187,12 @@ app_descriptor_configuration_t app_tusb_desc_configuration = .bLength = sizeof(tusb_descriptor_interface_association_t), .bDescriptorType = TUSB_DESC_TYPE_INTERFACE_ASSOCIATION, - .bFirstInterface = 1, + .bFirstInterface = INTERFACE_INDEX_CDC, .bInterfaceCount = 2, .bFunctionClass = TUSB_CLASS_CDC, .bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, .bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, - .iFunction = 0 }, #endif diff --git a/demos/device/device_os_none/tusb_descriptors.h b/demos/device/device_os_none/tusb_descriptors.h index 02fe929f..682c9d41 100644 --- a/demos/device/device_os_none/tusb_descriptors.h +++ b/demos/device/device_os_none/tusb_descriptors.h @@ -73,7 +73,7 @@ #define MSC_EDPT_OUT ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3) // Interface Assosication Descriptor if device is CDC + other class -#define IAD_DESC_REQUIRED ( 0 && TUSB_CFG_DEVICE_CDC && (TOTAL_INTEFACES > 2) ) +#define IAD_DESC_REQUIRED ( TUSB_CFG_DEVICE_CDC && (TOTAL_INTEFACES > 2) ) // each combination of interfaces need to have different productid, as windows will bind & remember device driver after the diff --git a/tinyusb/common/tusb_types.h b/tinyusb/common/tusb_types.h index 75ae576a..a4720052 100644 --- a/tinyusb/common/tusb_types.h +++ b/tinyusb/common/tusb_types.h @@ -151,6 +151,14 @@ typedef enum { TUSB_CLASS_VENDOR_SPECIFIC = 0xFF }tusb_std_class_code_t; +typedef enum { + MISC_SUBCLASS_COMMON = 2 +}misc_subclass_type_t; + +typedef enum { + MISC_PROTOCOL_IAD = 1 +}misc_protocol_type_t; + typedef enum tusb_std_class_flag_{ TUSB_CLASS_FLAG_AUDIO = BIT_(TUSB_CLASS_AUDIO) , ///< 1 TUSB_CLASS_FLAG_CDC = BIT_(TUSB_CLASS_CDC) , ///< 2 diff --git a/tinyusb/device/dcd_lpc_11uxx_13uxx.c b/tinyusb/device/dcd_lpc_11uxx_13uxx.c index 72171405..1ce96b2b 100644 --- a/tinyusb/device/dcd_lpc_11uxx_13uxx.c +++ b/tinyusb/device/dcd_lpc_11uxx_13uxx.c @@ -392,14 +392,7 @@ bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) return dcd_data.qhd[edpt_hdl.index][0].active || dcd_data.qhd[edpt_hdl.index][1].active; } -//// add only, controller virtually cannot know -//static tusb_error_t pipe_add_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t total_bytes, bool int_on_complete) -//{ -// -// -// return TUSB_ERROR_NONE; -//} - +// add only, not actually xfer data yet tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t total_bytes) { ASSERT( !dcd_pipe_is_busy(edpt_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); // endpoint must not in transferring @@ -417,7 +410,6 @@ tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, void* buffer, uint16_t t { ASSERT( !dcd_pipe_is_busy(edpt_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); // endpoint must not in transferring - // In case both Buffers (0 & 1) have xfer and only buffer1 has int_on_complete, enable interrupt will also cause buffer0's // xfer completion assert interrupt. This is unintentional side effect, and only can be handled in dcd_isr LPC_USB->INTEN = int_on_complete ? BIT_SET_(LPC_USB->INTEN, edpt_hdl.index) : BIT_CLR_(LPC_USB->INTEN, edpt_hdl.index); diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index 5c10f9c5..69e89b68 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -304,23 +304,29 @@ tusb_error_t usbd_set_configure_received(uint8_t coreid, uint8_t config_number) while( p_desc < p_desc_configure + ((tusb_descriptor_configuration_t*)p_desc_configure)->wTotalLength ) { - ASSERT( TUSB_DESC_TYPE_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_NOT_SUPPORTED_YET ); + if ( TUSB_DESC_TYPE_INTERFACE_ASSOCIATION == p_desc[DESCRIPTOR_OFFSET_TYPE]) + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // ignore IAD + }else + { + ASSERT( TUSB_DESC_TYPE_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_NOT_SUPPORTED_YET ); - uint8_t class_index; - tusb_descriptor_interface_t* p_desc_interface = (tusb_descriptor_interface_t*) p_desc; + uint8_t class_index; + tusb_descriptor_interface_t* p_desc_interface = (tusb_descriptor_interface_t*) p_desc; - class_index = p_desc_interface->bInterfaceClass; + class_index = p_desc_interface->bInterfaceClass; - ASSERT( class_index != 0 && usbd_class_drivers[class_index].open != NULL, TUSB_ERROR_NOT_SUPPORTED_YET ); - ASSERT( 0 == usbd_devices[coreid].interface2class[p_desc_interface->bInterfaceNumber], TUSB_ERROR_FAILED); // duplicate interface number TODO alternate setting + ASSERT( class_index != 0 && usbd_class_drivers[class_index].open != NULL, TUSB_ERROR_NOT_SUPPORTED_YET ); + ASSERT( 0 == usbd_devices[coreid].interface2class[p_desc_interface->bInterfaceNumber], TUSB_ERROR_FAILED); // duplicate interface number TODO alternate setting - usbd_devices[coreid].interface2class[p_desc_interface->bInterfaceNumber] = class_index; + usbd_devices[coreid].interface2class[p_desc_interface->bInterfaceNumber] = class_index; - uint16_t length=0; - ASSERT_STATUS( usbd_class_drivers[class_index].open( coreid, p_desc_interface, &length ) ); + uint16_t length=0; + ASSERT_STATUS( usbd_class_drivers[class_index].open( coreid, p_desc_interface, &length ) ); - ASSERT( length >= sizeof(tusb_descriptor_interface_t), TUSB_ERROR_FAILED ); - p_desc += length; + ASSERT( length >= sizeof(tusb_descriptor_interface_t), TUSB_ERROR_FAILED ); + p_desc += length; + } } return TUSB_ERROR_NONE;