diff options
Diffstat (limited to 'tinyusb')
| -rw-r--r-- | tinyusb/class/cdc.h | 24 | ||||
| -rw-r--r-- | tinyusb/class/cdc_host.c | 65 | ||||
| -rw-r--r-- | tinyusb/class/cdc_host.h | 9 | ||||
| -rw-r--r-- | tinyusb/class/cdc_host_rndis.c | 90 | ||||
| -rw-r--r-- | tinyusb/class/custom_class_host.c | 8 | ||||
| -rw-r--r-- | tinyusb/common/common.h | 13 | ||||
| -rw-r--r-- | tinyusb/common/errors.h | 3 | ||||
| -rw-r--r-- | tinyusb/core/tusb_types.h | 2 | ||||
| -rw-r--r-- | tinyusb/host/usbh.c | 2 |
9 files changed, 205 insertions, 11 deletions
diff --git a/tinyusb/class/cdc.h b/tinyusb/class/cdc.h index 0835dfbd9..14c7c800b 100644 --- a/tinyusb/class/cdc.h +++ b/tinyusb/class/cdc.h @@ -210,7 +210,7 @@ typedef ATTR_PACKED_STRUCT(struct) { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal + uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }tusb_cdc_func_header_t; typedef ATTR_PACKED_STRUCT(struct) { @@ -218,17 +218,35 @@ typedef ATTR_PACKED_STRUCT(struct) { uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ uint8_t bControlInterface ; ///< Interface number of Communication Interface - uint8_t bSubordinateInterface[0] ; ///< Interface number of Data Interface + uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }tusb_cdc_func_union_t; +#define tusb_cdc_func_union_n_t(no_slave)\ + ATTR_PACKED_STRUCT(struct) { \ + uint8_t bLength ;\ + uint8_t bDescriptorType ;\ + uint8_t bDescriptorSubType ;\ + uint8_t bControlInterface ;\ + uint8_t bSubordinateInterface[no_slave] ;\ +} + typedef ATTR_PACKED_STRUCT(struct) { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. - uint16_t wCountryCode[0] ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. + uint16_t wCountryCode[] ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }tusb_cdc_func_country_selection_t; +#define tusb_cdc_func_country_selection_n_t(no_country) \ + ATTR_PACKED_STRUCT(struct) {\ + uint8_t bLength ;\ + uint8_t bDescriptorType ;\ + uint8_t bDescriptorSubType ;\ + uint8_t iCountryCodeRelDate ;\ + uint16_t wCountryCode[no_country] ;\ +} + //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ diff --git a/tinyusb/class/cdc_host.c b/tinyusb/class/cdc_host.c index ac99df184..0f3a8fcaf 100644 --- a/tinyusb/class/cdc_host.c +++ b/tinyusb/class/cdc_host.c @@ -55,17 +55,78 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +STATIC_ cdch_data_t cdch_data[TUSB_CFG_HOST_DEVICE_MAX]; //--------------------------------------------------------------------+ -// IMPLEMENTATION +// USBH-CLASS DRIVER API //--------------------------------------------------------------------+ void cdch_init(void) { - + memclr_(cdch_data, sizeof(cdch_data_t)*TUSB_CFG_HOST_DEVICE_MAX); } tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) { + + if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) + { + return TUSB_ERROR_CDCH_UNSUPPORTED_SUBCLASS; + } + + if (CDC_COMM_PROTOCOL_ATCOMMAND != p_interface_desc->bInterfaceProtocol) + { + return TUSB_ERROR_CDCH_UNSUPPORTED_PROTOCOL; + } + + uint8_t const * p_desc = descriptor_next ( (uint8_t const *) p_interface_desc ); + cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; + + p_cdc->interface_number = p_interface_desc->bInterfaceNumber; + p_cdc->interface_protocol = p_interface_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com + + //------------- Communication Interface -------------// + (*p_length) = sizeof(tusb_descriptor_interface_t); + + while( TUSB_DESC_TYPE_INTERFACE_CLASS_SPECIFIC == p_desc[DESCRIPTOR_OFFSET_TYPE] ) + { // Communication Functional Descriptors + (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc = descriptor_next(p_desc); + } + + if ( TUSB_DESC_TYPE_ENDPOINT == p_desc[DESCRIPTOR_OFFSET_TYPE]) + { // notification endpoint if any + p_cdc->pipe_notification = hcd_pipe_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, TUSB_CLASS_CDC); + + (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc = descriptor_next(p_desc); + + ASSERT(pipehandle_is_valid(p_cdc->pipe_notification), TUSB_ERROR_HCD_OPEN_PIPE_FAILED); + } + + //------------- Data Interface (if any) -------------// + if ( (TUSB_DESC_TYPE_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE]) && + (TUSB_CLASS_CDC_DATA == ((tusb_descriptor_interface_t const *) p_desc)->bInterfaceClass) ) + { + (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc = descriptor_next(p_desc); + + // data endpoints expected to be in pairs + for(uint32_t i=0; i<2; i++) + { + 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_CDCH_DESCRIPTOR_CORRUPTED); + + pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ? + &p_cdc->pipe_in : &p_cdc->pipe_out; + + (*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_CDC); + ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); + + (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc = descriptor_next( p_desc ); + } + } + return TUSB_ERROR_NONE; } diff --git a/tinyusb/class/cdc_host.h b/tinyusb/class/cdc_host.h index c9ad067ae..12132ca68 100644 --- a/tinyusb/class/cdc_host.h +++ b/tinyusb/class/cdc_host.h @@ -63,6 +63,15 @@ //--------------------------------------------------------------------+ #ifdef _TINY_USB_SOURCE_FILE_ +typedef struct { + uint8_t interface_number; + uint8_t interface_protocol; + pipe_handle_t pipe_notification, pipe_out, pipe_in; + +} cdch_data_t; + +extern cdch_data_t cdch_data[TUSB_CFG_HOST_DEVICE_MAX]; // TODO consider to move to cdch internal header file + void cdch_init(void); tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; void cdch_isr(pipe_handle_t pipe_hdl, tusb_event_t event); diff --git a/tinyusb/class/cdc_host_rndis.c b/tinyusb/class/cdc_host_rndis.c new file mode 100644 index 000000000..66f429f81 --- /dev/null +++ b/tinyusb/class/cdc_host_rndis.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/*! + @file cdc_host_rndis.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_CDC && TUSB_CFG_HOST_CDC_RNDIS) + +#define _TINY_USB_SOURCE_FILE_ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/common.h" +#include "cdc_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static tusb_error_t rndis_body_subtask(void); + +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ + +// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper +// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with +// forever loop cannot have any return at all. +OSAL_TASK_FUNCTION(cdch_rndis_task) (void* p_task_para) +{ + OSAL_TASK_LOOP_BEGIN + + rndis_body_subtask(); + + OSAL_TASK_LOOP_END +} + +static tusb_error_t rndis_body_subtask(void) +{ + static uint8_t relative_addr; + + OSAL_SUBTASK_BEGIN + + for (relative_addr = 0; relative_addr < TUSB_CFG_HOST_DEVICE_MAX; relative_addr++) + { + + } + + osal_task_delay(100); + + OSAL_SUBTASK_END +} diff --git a/tinyusb/class/custom_class_host.c b/tinyusb/class/custom_class_host.c index 39d4c260a..3ff361886 100644 --- a/tinyusb/class/custom_class_host.c +++ b/tinyusb/class/custom_class_host.c @@ -112,17 +112,17 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con // 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 -------------// + //------------- Bulk Endpoints 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 ) ? + pipe_handle_t * p_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_pipe_hdl = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); + ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); } (*p_length) = sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t); diff --git a/tinyusb/common/common.h b/tinyusb/common/common.h index 63ba26d56..ed543de00 100644 --- a/tinyusb/common/common.h +++ b/tinyusb/common/common.h @@ -101,6 +101,19 @@ //--------------------------------------------------------------------+ #define memclr_(buffer, size) memset(buffer, 0, size) + +static inline uint8_t const * descriptor_next(uint8_t const * p_desc) ATTR_ALWAYS_INLINE ATTR_PURE; +static inline uint8_t const * descriptor_next(uint8_t const * p_desc) +{ + return p_desc + p_desc[DESCRIPTOR_OFFSET_LENGTH]; +} + +static inline uint8_t descriptor_typeof(uint8_t const * p_desc) ATTR_ALWAYS_INLINE ATTR_PURE; +static inline uint8_t descriptor_typeof(uint8_t const * p_desc) +{ + return p_desc[DESCRIPTOR_OFFSET_TYPE]; +} + //------------- Conversion -------------// /// form an uint32_t from 4 x uint8_t static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST; diff --git a/tinyusb/common/errors.h b/tinyusb/common/errors.h index dc9908bfd..6118242ad 100644 --- a/tinyusb/common/errors.h +++ b/tinyusb/common/errors.h @@ -80,6 +80,9 @@ ENTRY(TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE )\ ENTRY(TUSB_ERROR_HIDH_NOT_SUPPORTED_PROTOCOL )\ ENTRY(TUSB_ERROR_HIDH_NOT_SUPPORTED_SUBCLASS )\ + ENTRY(TUSB_ERROR_CDCH_DESCRIPTOR_CORRUPTED )\ + ENTRY(TUSB_ERROR_CDCH_UNSUPPORTED_SUBCLASS )\ + ENTRY(TUSB_ERROR_CDCH_UNSUPPORTED_PROTOCOL )\ ENTRY(TUSB_ERROR_NOT_SUPPORTED_YET )\ ENTRY(TUSB_ERROR_FAILED )\ diff --git a/tinyusb/core/tusb_types.h b/tinyusb/core/tusb_types.h index 1197edfec..ac3bb879f 100644 --- a/tinyusb/core/tusb_types.h +++ b/tinyusb/core/tusb_types.h @@ -207,7 +207,7 @@ typedef enum { enum { DESCRIPTOR_OFFSET_LENGTH = 0, - DESCRIPTOR_OFFSET_TYPE = 1 + DESCRIPTOR_OFFSET_TYPE = 1 }; #ifdef __cplusplus diff --git a/tinyusb/host/usbh.c b/tinyusb/host/usbh.c index fa366cb66..71a994443 100644 --- a/tinyusb/host/usbh.c +++ b/tinyusb/host/usbh.c @@ -298,7 +298,7 @@ void usbh_device_unplugged_isr(uint8_t hostid) //--------------------------------------------------------------------+ // ENUMERATION TASK //--------------------------------------------------------------------+ -tusb_error_t enumeration_body_subtask(void); +static tusb_error_t enumeration_body_subtask(void); // To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper // and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with |
