diff --git a/demos/device/keyboard/main.c b/demos/device/keyboard/main.c index 388f0cb8f..eb943221e 100644 --- a/demos/device/keyboard/main.c +++ b/demos/device/keyboard/main.c @@ -94,7 +94,7 @@ void led_blinking_task(void * p_para) void keyboard_device_app_task(void * p_para) { #if 0 - if (tusb_device_is_configured()) + if (tusbd_is_configured()) { static uint32_t count =0; if (count < 4) diff --git a/tinyusb/class/custom_class.h b/tinyusb/class/custom_class.h new file mode 100644 index 000000000..9a6588a26 --- /dev/null +++ b/tinyusb/class/custom_class.h @@ -0,0 +1,79 @@ +/**************************************************************************/ +/*! + @file custom_class.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup TBD + * \defgroup TBD + * \brief TBD + * + * @{ + */ + +#ifndef _TUSB_CUSTOM_CLASS_H_ +#define _TUSB_CUSTOM_CLASS_H_ + +#include "common/common.h" +#include "host/usbh.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + pipe_handle_t pipe_in; + pipe_handle_t pipe_out; +}custom_interface_info_t; + +//--------------------------------------------------------------------+ +// USBH-CLASS DRIVER API +//--------------------------------------------------------------------+ +#ifdef _TINY_USB_SOURCE_FILE_ + +void cush_init(void); +tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; +void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event); +void cush_close(uint8_t dev_addr); + +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CUSTOM_CLASS_H_ */ + +/** @} */ diff --git a/tinyusb/class/custom_class_host.c b/tinyusb/class/custom_class_host.c new file mode 100644 index 000000000..723cb06ff --- /dev/null +++ b/tinyusb/class/custom_class_host.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/*! + @file custom_class_host.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "tusb_option.h" + +#if (MODE_HOST_SUPPORTED && TUSB_CFG_HOST_CUSTOM_CLASS) + +#define _TINY_USB_SOURCE_FILE_ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/common.h" +#include "custom_class.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +custom_interface_info_t custom_interface[TUSB_CFG_HOST_DEVICE_MAX]; +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ +void cush_init(void) +{ + memclr_(&custom_interface, sizeof(custom_interface_info_t) * TUSB_CFG_HOST_DEVICE_MAX); +} + +tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) +{ + // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints + uint8_t const *p_desc = (uint8_t const *) p_interface_desc; + + //------------- 1st Bulk Endpiont Descriptor -------------// + for(uint32_t i=0; i<2; i++) + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) p_desc; + ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); + + pipe_handle_t * pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ? + &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; + *pipe_hdl = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); + ASSERT ( pipehandle_is_valid(*pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); + } + + (*p_length) = sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t); + return TUSB_ERROR_NONE; +} + +void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event) +{ + +} + +void cush_close(uint8_t dev_addr) +{ + tusb_error_t err1, err2; + custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; + + // TODO re-consider to check pipe valid before calling pipe_close + if( pipehandle_is_valid( p_interface->pipe_in ) ) + { + err1 = hcd_pipe_close( p_interface->pipe_in ); + } + + if ( pipehandle_is_valid( p_interface->pipe_out ) ) + { + err2 = hcd_pipe_close( p_interface->pipe_out ); + } + + memclr_(p_interface, sizeof(custom_interface_info_t)); + + ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); +} + +#endif diff --git a/tinyusb/class/hid_device.c b/tinyusb/class/hid_device.c index 2aba541bb..adb252c11 100644 --- a/tinyusb/class/hid_device.c +++ b/tinyusb/class/hid_device.c @@ -136,7 +136,7 @@ tusb_error_t hidd_init(uint8_t coreid, tusb_descriptor_interface_t const * p_int { #if TUSB_CFG_DEVICE_HID_KEYBOARD case HID_PROTOCOL_KEYBOARD: - ASSERT_STATUS( dcd_endpoint_configure(coreid, p_desc_endpoint) ); + ASSERT_STATUS( dcd_pipe_open(coreid, p_desc_endpoint) ); break; #endif diff --git a/tinyusb/class/hid_host.c b/tinyusb/class/hid_host.c index b109430af..3546a512a 100644 --- a/tinyusb/class/hid_host.c +++ b/tinyusb/class/hid_host.c @@ -38,7 +38,7 @@ #include "tusb_option.h" -#if (MODE_HOST_SUPPORTED && defined HOST_CLASS_HID) +#if (MODE_HOST_SUPPORTED && HOST_CLASS_HID) #define _TINY_USB_SOURCE_FILE_ //--------------------------------------------------------------------+ @@ -214,40 +214,33 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_INVALID_PARA); - if (p_interface_desc->bInterfaceSubClass == HID_SUBCLASS_BOOT) + switch(p_interface_desc->bInterfaceProtocol) { - switch(p_interface_desc->bInterfaceProtocol) - { - #if TUSB_CFG_HOST_HID_KEYBOARD - case HID_PROTOCOL_KEYBOARD: - ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &keyboard_data[dev_addr-1]) ); - if ( tusbh_hid_keyboard_isr ) - { - tusbh_hid_keyboard_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN); - } - break; - #endif + #if TUSB_CFG_HOST_HID_KEYBOARD + case HID_PROTOCOL_KEYBOARD: + ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &keyboard_data[dev_addr-1]) ); + if ( tusbh_hid_keyboard_isr ) + { + tusbh_hid_keyboard_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN); + } + break; + #endif - #if TUSB_CFG_HOST_HID_MOUSE - case HID_PROTOCOL_MOUSE: - ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &mouse_data[dev_addr-1]) ); - if (tusbh_hid_mouse_isr) - { - tusbh_hid_mouse_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN); - } - break; - #endif + #if TUSB_CFG_HOST_HID_MOUSE + case HID_PROTOCOL_MOUSE: + ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &mouse_data[dev_addr-1]) ); + if (tusbh_hid_mouse_isr) + { + tusbh_hid_mouse_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN); + } + break; + #endif - default: // TODO unknown, unsupported protocol --> skip this interface - return TUSB_ERROR_NONE; - } - *p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t); - }else - { - // open generic - *p_length = 0; + default: // TODO unknown, unsupported protocol --> skip this interface + return TUSB_ERROR_NONE; } + *p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t); return TUSB_ERROR_NONE; } diff --git a/tinyusb/common/errors.h b/tinyusb/common/errors.h index 02cdae1e6..e444a04f8 100644 --- a/tinyusb/common/errors.h +++ b/tinyusb/common/errors.h @@ -64,6 +64,7 @@ ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\ ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\ ENTRY(TUSB_ERROR_HCD_FAILED )\ + ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\ ENTRY(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND )\ ENTRY(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG )\ ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\ diff --git a/tinyusb/core/tusb_types.h b/tinyusb/core/tusb_types.h index 35cb07cd8..ceabb6484 100644 --- a/tinyusb/core/tusb_types.h +++ b/tinyusb/core/tusb_types.h @@ -70,10 +70,13 @@ typedef enum { }tusb_transfer_type_t; typedef enum { - TUSB_DIR_HOST_TO_DEV = 0, - TUSB_DIR_DEV_TO_HOST = 1 + TUSB_DIR_HOST_TO_DEV = 0, + TUSB_DIR_DEV_TO_HOST = 1, + + TUSB_DIR_DEV_TO_HOST_MASK = 0x80 }tusb_direction_t; + /// USB Descriptor Types (section 9.4 table 9-5) typedef enum { TUSB_DESC_TYPE_DEVICE =1 , ///< 1 @@ -137,7 +140,8 @@ typedef enum { TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , ///< 15 TUSB_CLASS_AUDIO_VIDEO = 16 , ///< 16 - TUSB_CLASS_MAX_CONSEC_NUMBER = 17 , // TODO compact & minimize this number + TUSB_CLASS_MAPPED_INDEX_START = 17 , // TODO compact & minimize this number + TUSB_CLASS_MAPPED_INDEX_END = TUSB_CLASS_MAPPED_INDEX_START + 5, TUSB_CLASS_DIAGNOSTIC = 0xDC , TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 , diff --git a/tinyusb/device/dcd.h b/tinyusb/device/dcd.h index 0ae804d08..b6415a1b5 100644 --- a/tinyusb/device/dcd.h +++ b/tinyusb/device/dcd.h @@ -66,7 +66,7 @@ tusb_error_t dcd_pipe_control_write(uint8_t coreid, void const * buffer, uint16_ tusb_error_t dcd_pipe_control_read(uint8_t coreid, void * buffer, uint16_t length); void dcd_pipe_control_write_zero_length(uint8_t coreid); -tusb_error_t dcd_endpoint_configure(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) ATTR_WARN_UNUSED_RESULT; +tusb_error_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) ATTR_WARN_UNUSED_RESULT; void dcd_device_set_address(uint8_t coreid, uint8_t dev_addr); void dcd_device_set_configuration(uint8_t coreid, uint8_t config_num); diff --git a/tinyusb/device/dcd_lpc175x_6x.c b/tinyusb/device/dcd_lpc175x_6x.c index bbae9d314..c6ab3990c 100644 --- a/tinyusb/device/dcd_lpc175x_6x.c +++ b/tinyusb/device/dcd_lpc175x_6x.c @@ -297,7 +297,7 @@ static inline uint8_t endpoint_address_to_physical_index(uint8_t ep_address) return (ep_address << 1) + (ep_address & 0x80 ? 1 : 0 ); } -tusb_error_t dcd_endpoint_configure(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) +tusb_error_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) { uint8_t phy_ep = endpoint_address_to_physical_index( p_endpoint_desc->bEndpointAddress ); diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index 02a8b5f28..3fb8fa542 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -55,7 +55,7 @@ usbd_device_info_t usbd_devices[CONTROLLER_DEVICE_NUMBER]; // TODO fix/compress number of class driver -static device_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER] = +static device_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_START] = { #if DEVICE_CLASS_HID [TUSB_CLASS_HID] = { @@ -78,6 +78,9 @@ bool tusbd_is_configured(uint8_t coreid) return usbd_devices[coreid].state == TUSB_DEVICE_STATE_CONFIGURED; } +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ void usbd_bus_reset(uint32_t coreid) { memclr_(usbd_devices, sizeof(usbd_device_info_t)*CONTROLLER_DEVICE_NUMBER); @@ -166,9 +169,6 @@ void usbd_setup_received(uint8_t coreid) } } -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ tusb_error_t usbd_init (void) { ASSERT_STATUS ( usbd_string_descriptor_init() ); @@ -197,9 +197,16 @@ tusb_error_t usbd_init (void) return TUSB_ERROR_NONE; } -#endif +//--------------------------------------------------------------------+ +// USBD-CLASS API +//--------------------------------------------------------------------+ +tusb_error_t usbd_pipe_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interfacae, tusb_descriptor_endpoint_t const * p_endpoint_desc) +{ + return TUSB_ERROR_NONE; +} + //--------------------------------------------------------------------+ // callback from DCD ISR //--------------------------------------------------------------------+ @@ -252,3 +259,5 @@ static tusb_error_t usbd_string_descriptor_init(void) return TUSB_ERROR_NONE; } + +#endif diff --git a/tinyusb/device/usbd.h b/tinyusb/device/usbd.h index 929900ffc..2f362f6fd 100644 --- a/tinyusb/device/usbd.h +++ b/tinyusb/device/usbd.h @@ -86,6 +86,7 @@ bool tusbd_is_configured(uint8_t coreid) ATTR_WARN_UNUSED_RESULT; #ifdef _TINY_USB_SOURCE_FILE_ tusb_error_t usbd_init(void); +tusb_error_t usbd_pipe_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interfacae, tusb_descriptor_endpoint_t const * p_endpoint_desc); #endif diff --git a/tinyusb/host/ehci/ehci.c b/tinyusb/host/ehci/ehci.c index 21c457c17..4a030cbbe 100644 --- a/tinyusb/host/ehci/ehci.c +++ b/tinyusb/host/ehci/ehci.c @@ -373,10 +373,13 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK) { list_head = (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id); - }else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT) + } + #if EHCI_PERIODIC_LIST // TODO refractor/group this together + else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT) { list_head = get_period_head(usbh_devices[dev_addr].core_id, p_qhd->interval_ms); } + #endif //------------- insert to async/period list TODO might need to disable async/period list -------------// list_insert( list_head, @@ -428,12 +431,15 @@ tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) ASSERT_STATUS( list_remove_qhd( (ehci_link_t*) get_async_head( usbh_devices[pipe_hdl.dev_addr].core_id ), (ehci_link_t*) p_qhd) ); - }else + } + #if EHCI_PERIODIC_LIST // TODO refractor/group this together + else { ASSERT_STATUS( list_remove_qhd( get_period_head( usbh_devices[pipe_hdl.dev_addr].core_id, p_qhd->interval_ms ), (ehci_link_t*) p_qhd) ); } + #endif return TUSB_ERROR_NONE; } @@ -530,6 +536,7 @@ void async_list_process_isr(ehci_qhd_t * const async_head) // TODO abstract max loop guard for async } +#if EHCI_PERIODIC_LIST // TODO refractor/group this together void period_list_process_isr(uint8_t hostid, uint8_t interval_ms) { uint8_t max_loop = 0; @@ -585,6 +592,7 @@ void period_list_process_isr(uint8_t hostid, uint8_t interval_ms) max_loop++; } } +#endif void xfer_error_isr(uint8_t hostid) { @@ -653,6 +661,7 @@ void hcd_isr(uint8_t hostid) async_list_process_isr( get_async_head(hostid) ); } +#if EHCI_PERIODIC_LIST // TODO refractor/group this together if (int_status & EHCI_INT_MASK_NXP_PERIODIC) { for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) @@ -660,6 +669,7 @@ void hcd_isr(uint8_t hostid) period_list_process_isr( hostid, i ); } } +#endif //------------- There is some removed async previously -------------// if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC @@ -676,6 +686,7 @@ STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid) return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) ); } +#if EHCI_PERIODIC_LIST // TODO refractor/group this together STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid) { switch(hostid) @@ -693,6 +704,7 @@ STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid) return NULL; } +#endif STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid) { @@ -710,11 +722,13 @@ STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid) return &ehci_data.async_head[ hostid_to_data_idx(hostid) ]; } +#if EHCI_PERIODIC_LIST // TODO refractor/group this together STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) { return (ehci_link_t*) (&ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ] [ log2_of( min8_of(EHCI_FRAMELIST_SIZE, interval_ms) ) ] ); } +#endif STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr) { diff --git a/tinyusb/host/usbh.c b/tinyusb/host/usbh.c index 3dc28e2b3..33e68b5ed 100644 --- a/tinyusb/host/usbh.c +++ b/tinyusb/host/usbh.c @@ -54,7 +54,7 @@ #define ENUM_QUEUE_DEPTH 5 // TODO fix/compress number of class driver -static host_class_driver_t const usbh_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER] = +static host_class_driver_t const usbh_class_drivers[TUSB_CLASS_MAPPED_INDEX_END] = { #if HOST_CLASS_HID [TUSB_CLASS_HID] = { @@ -83,6 +83,14 @@ static host_class_driver_t const usbh_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER } #endif +#if TUSB_CFG_HOST_CUSTOM_CLASS + [TUSB_CLASS_MAPPED_INDEX_END-1] = { + .init = cush_init, + .open_subtask = cush_open_subtask, + .isr = cush_isr, + .close = cush_close + } +#endif }; //--------------------------------------------------------------------+ @@ -102,6 +110,17 @@ STATIC_ uint8_t enum_data_buffer[TUSB_CFG_HOST_ENUM_BUFFER_SIZE] TUSB_CFG_ATTR_U static inline uint8_t get_new_address(void) ATTR_ALWAYS_INLINE; static inline uint8_t get_configure_number_for_device(tusb_descriptor_device_t* dev_desc) ATTR_ALWAYS_INLINE; +static inline uint8_t std_class_code_to_index(uint8_t std_class_code) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t std_class_code_to_index(uint8_t std_class_code) +{ + return (std_class_code <= TUSB_CLASS_AUDIO_VIDEO ) ? std_class_code : + (std_class_code == TUSB_CLASS_DIAGNOSTIC ) ? TUSB_CLASS_MAPPED_INDEX_START : + (std_class_code == TUSB_CLASS_WIRELESS_CONTROLLER ) ? TUSB_CLASS_MAPPED_INDEX_START + 1 : + (std_class_code == TUSB_CLASS_MISC ) ? TUSB_CLASS_MAPPED_INDEX_START + 2 : + (std_class_code == TUSB_CLASS_APPLICATION_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 3 : + (std_class_code == TUSB_CLASS_VENDOR_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 4 : 0; +} + //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -133,7 +152,7 @@ tusb_error_t usbh_init(void) ASSERT_PTR(enum_queue_hdl, TUSB_ERROR_OSAL_QUEUE_FAILED); //------------- class init -------------// - for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++) + for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAPPED_INDEX_END; class_code++) { if (usbh_class_drivers[class_code].init) usbh_class_drivers[class_code].init(); @@ -229,12 +248,12 @@ void usbh_device_unplugged_isr(uint8_t hostid) if (dev_addr > 0) // device can still be unplugged when not set new address { // if device unplugged is not a hub TODO handle hub unplugged - for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++) + for (uint8_t class_index = 1; class_index < TUSB_CLASS_MAPPED_INDEX_END; class_index++) { - if ((usbh_devices[dev_addr].flag_supported_class & BIT_(class_code)) && - usbh_class_drivers[class_code].close) + if ((usbh_devices[dev_addr].flag_supported_class & BIT_(class_index)) && + usbh_class_drivers[class_index].close) { - usbh_class_drivers[class_code].close(dev_addr); + usbh_class_drivers[class_index].close(dev_addr); } } } @@ -434,29 +453,27 @@ tusb_error_t enumeration_body_subtask(void) p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length }else { - uint8_t class_code = ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass; - if (class_code == 0) - { - SUBTASK_ASSERT( false ); // corrupted data, abort enumeration - } - // supported class TODO custom class - else if ( class_code < TUSB_CLASS_MAX_CONSEC_NUMBER && usbh_class_drivers[class_code].open_subtask) + static uint8_t class_index; // has to be static as it is used to call class's open_subtask + + class_index = std_class_code_to_index( ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ); + SUBTASK_ASSERT( class_index != 0); // class_code == 0 means corrupted data, abort enumeration + + if (usbh_class_drivers[class_index].open_subtask) // supported class { uint16_t length=0; OSAL_SUBTASK_INVOKED_AND_WAIT ( // parameters in task/sub_task must be static storage (static or global) - usbh_class_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].open_subtask( - new_addr, (tusb_descriptor_interface_t*) p_desc, &length), + usbh_class_drivers[class_index].open_subtask( new_addr, (tusb_descriptor_interface_t*) p_desc, &length ), error ); - if (error != TUSB_ERROR_NONE || length == 0) // Interface open failed, for example a subclass is not supported + if (error == TUSB_ERROR_NONE) // Interface open failed, for example a subclass is not supported { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop - // TODO can optimize the length --> open_subtask return a OPEN FAILED status + SUBTASK_ASSERT( length >= sizeof(tusb_descriptor_interface_t) ); + usbh_devices[new_addr].flag_supported_class |= BIT_(class_index); + p_desc += length; }else { - usbh_devices[new_addr].flag_supported_class |= BIT_(((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass); - p_desc += length; + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop } } else // unsupported class (not enable or yet implemented) { diff --git a/tinyusb/tusb.h b/tinyusb/tusb.h index f7c14d9f6..0e5ddc8ca 100644 --- a/tinyusb/tusb.h +++ b/tinyusb/tusb.h @@ -59,15 +59,19 @@ #if MODE_HOST_SUPPORTED #include "host/usbh.h" - #ifdef HOST_CLASS_HID + #if HOST_CLASS_HID #include "class/hid_host.h" #endif - #define HOST_CLASS_MSC +// #define HOST_CLASS_MSC // FIXME hack to test massstorage class #ifdef HOST_CLASS_MSC #include "class/msc_host.h" #endif + #if TUSB_CFG_HOST_CUSTOM_CLASS + #include "class/custom_class.h" + #endif + #endif //------------- DEVICE -------------//