From 25ea8f9c9e65d1617382a7896df07afd0dc90ce3 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Sep 2021 21:02:38 +0700 Subject: [PATCH] update configuration parser --- .../audio_4_channel_mic/src/usb_descriptors.c | 13 ++++-- src/class/msc/msc_device.c | 2 +- src/device/usbd.c | 44 ++++++++++-------- src/host/usbh.c | 46 +++++++++++-------- src/tusb.c | 2 +- src/tusb_option.h | 24 ++++++++++ 6 files changed, 85 insertions(+), 46 deletions(-) diff --git a/examples/device/audio_4_channel_mic/src/usb_descriptors.c b/examples/device/audio_4_channel_mic/src/usb_descriptors.c index 018919bf3..2b66bfe34 100644 --- a/examples/device/audio_4_channel_mic/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic/src/usb_descriptors.c @@ -81,12 +81,15 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_FOUR_CH_DESC_LEN) -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX -// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number -// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... -#define EPNUM_AUDIO 0x03 +#if TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_AUDIO 0x03 +#elif TU_CHECK_MCU(NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_AUDIO 0x08 #else -#define EPNUM_AUDIO 0x01 + #define EPNUM_AUDIO 0x01 #endif uint8_t const desc_configuration[] = diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 0fd592129..765760fd1 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -258,7 +258,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // 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 + // Max length must be at least 1 interface + 2 endpoints TU_ASSERT(max_len >= drv_len, 0); mscd_interface_t * p_msc = &_mscd_itf; diff --git a/src/device/usbd.c b/src/device/usbd.c index a5773c625..2874dc5eb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -888,23 +888,40 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - tusb_desc_interface_assoc_t const * desc_iad = NULL; + uint8_t assoc_itf_count = 1; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + p_desc = tu_desc_next(p_desc); // next to Interface + + // IAD's first interface number and class should match with opened interface + //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); } TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; // Interface number must not be used already TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); +#if CFG_TUD_MIDI + // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD + // manually increase the associated count + if (1 == assoc_itf_count && + TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) + { + assoc_itf_count = 2; + } +#endif + + uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); TU_ASSERT(drv_len); // Find driver for this interface @@ -915,29 +932,18 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if ( driver->open(rhport, desc_itf, drv_len) ) { - // Open successfully, check if length is correct + // Open successfully TU_LOG2(" %s opened\r\n", driver->name); - // bind interface to found driver - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - // If using IAD, bind all interfaces to the same driver - if (desc_iad) + // bind (associated) interfaces to found driver + for(uint8_t i=0; ibFirstInterface == desc_itf->bInterfaceNumber && - desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - - for(uint8_t i=1; ibInterfaceCount; i++) - { - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; - } + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; } // bind all endpoints to found driver tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); - break; // exit driver find loop } } diff --git a/src/host/usbh.c b/src/host/usbh.c index 886a120a8..14e71379b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -982,24 +982,40 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura // parse each interfaces while( p_desc < desc_end ) { - // TODO Do we need to use IAD - tusb_desc_interface_assoc_t const * desc_iad = NULL; + uint8_t assoc_itf_count = 1; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + p_desc = tu_desc_next(p_desc); // next to Interface + + // IAD's first interface number and class should match with opened interface + //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); } TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; // Interface number must not be used already - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == DRVID_INVALID ); + TU_ASSERT( DRVID_INVALID == dev->itf2drv[desc_itf->bInterfaceNumber] ); - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); +#if CFG_TUH_MIDI + // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD + // manually increase the associated count + if (1 == assoc_itf_count && + TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) + { + assoc_itf_count = 2; + } +#endif + + uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); TU_ASSERT(drv_len); if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) @@ -1019,22 +1035,12 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) { // open successfully - TU_LOG2(" Opened successfully\r\n"); + TU_LOG2(" %s opened\r\n", driver->name); - // bind interface to found driver - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - // If using IAD, bind all interfaces to the same driver - if (desc_iad) + // bind (associated) interfaces to found driver + for(uint8_t i=0; ibFirstInterface == desc_itf->bInterfaceNumber && - desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - - for(uint8_t i=1; ibInterfaceCount; i++) - { - dev->itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; - } + dev->itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; } // bind all endpoints to found driver diff --git a/src/tusb.c b/src/tusb.c index 6494287d2..5c6adad24 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -121,7 +121,7 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_ ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - len = (uint16_t)(len + tu_desc_len(p_desc)); + len += (uint16_t) tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } } diff --git a/src/tusb_option.h b/src/tusb_option.h index a00f3489f..4d7e1e9d2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -278,6 +278,30 @@ //------------- CLASS -------------// #endif // TUSB_OPT_HOST_ENABLED +#ifndef CFG_TUH_HUB +#define CFG_TUH_HUB 0 +#endif + +#ifndef CFG_TUH_CDC +#define CFG_TUH_CDC 0 +#endif + +#ifndef CFG_TUH_HID +#define CFG_TUH_HID 0 +#endif + +#ifndef CFG_TUH_MIDI +#define CFG_TUH_MIDI 0 +#endif + +#ifndef CFG_TUH_MSC +#define CFG_TUH_MSC 0 +#endif + +#ifndef CFG_TUH_VENDOR +#define CFG_TUH_VENDOR 0 +#endif + //--------------------------------------------------------------------+ // Port Specific // TUP stand for TinyUSB Port (can be renamed)