diff --git a/demos/host/src/tusb_config.h b/demos/host/src/tusb_config.h index 050bf3f59..d6a0d6162 100644 --- a/demos/host/src/tusb_config.h +++ b/demos/host/src/tusb_config.h @@ -78,6 +78,7 @@ #define TUSB_CFG_HOST_HID_GENERIC 0 #define TUSB_CFG_HOST_MSC 0 #define TUSB_CFG_HOST_CDC 1 +#define TUSB_CFG_HOST_CDC_RNDIS 1 //--------------------------------------------------------------------+ // DEVICE CONFIGURATION diff --git a/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c b/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c new file mode 100644 index 000000000..df82f9ce3 --- /dev/null +++ b/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/*! + @file descriptor_cdc.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" +#include "descriptor_cdc.h" + +TUSB_CFG_ATTR_USBRAM +const cdc_configuration_desc_t cdc_config_descriptor = +{ + .configuration = + { + .bLength = sizeof(tusb_descriptor_configuration_t), + .bDescriptorType = TUSB_DESC_TYPE_CONFIGURATION, + + .wTotalLength = sizeof(cdc_configuration_desc_t), + .bNumInterfaces = 2, + + .bConfigurationValue = 1, + .iConfiguration = 0x00, + .bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER, + .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100) + }, + + // IAD points to CDC Interfaces + .cdc_iad = + { + .bLength = sizeof(tusb_descriptor_interface_association_t), + .bDescriptorType = TUSB_DESC_TYPE_INTERFACE_ASSOCIATION, + + .bFirstInterface = 1, + .bInterfaceCount = 2, + + .bFunctionClass = TUSB_CLASS_CDC, + .bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, + .bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, + + .iFunction = 0 + }, + + + // USB CDC Serial Interface + //------------- CDC Communication Interface -------------// + .cdc_comm_interface = + { + .bLength = sizeof(tusb_descriptor_interface_t), + .bDescriptorType = TUSB_DESC_TYPE_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_CDC, + .bInterfaceSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, + .bInterfaceProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, + .iInterface = 0x00 + }, + + .cdc_header = + { + .bLength = sizeof(tusb_cdc_func_header_t), + .bDescriptorType = TUSB_DESC_TYPE_INTERFACE_CLASS_SPECIFIC, + .bDescriptorSubType = CDC_FUNC_DESC_HEADER, + .bcdCDC = 0x0120 + }, + + .cdc_acm = + { + .bLength = sizeof(tusb_cdc_func_abstract_control_management_t), + .bDescriptorType = TUSB_DESC_TYPE_INTERFACE_CLASS_SPECIFIC, + .bDescriptorSubType = CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, + .bmCapabilities = { // 0x06 + .support_line_request = 1, + .support_send_break = 1 + } + }, + + .cdc_union = + { + .bLength = sizeof(tusb_cdc_func_union_t), // plus number of + .bDescriptorType = TUSB_DESC_TYPE_INTERFACE_CLASS_SPECIFIC, + .bDescriptorSubType = CDC_FUNC_DESC_UNION, + .bControlInterface = 1, + .bSubordinateInterface = 2, + }, + + .cdc_endpoint_notification = + { + .bLength = sizeof(tusb_descriptor_endpoint_t), + .bDescriptorType = TUSB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = 0x81, + .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT }, + .wMaxPacketSize = 8, + .bInterval = 0x0a // lowest polling rate + }, + + //------------- CDC Data Interface -------------// + .cdc_data_interface = + { + .bLength = sizeof(tusb_descriptor_interface_t), + .bDescriptorType = TUSB_DESC_TYPE_INTERFACE, + .bInterfaceNumber = 2, + .bAlternateSetting = 0x00, + .bNumEndpoints = 2, + .bInterfaceClass = TUSB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0x00 + }, + + .cdc_endpoint_out = + { + .bLength = sizeof(tusb_descriptor_endpoint_t), + .bDescriptorType = TUSB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = 2, + .bmAttributes = { .xfer = TUSB_XFER_BULK }, + .wMaxPacketSize = 64, + .bInterval = 0 + }, + + .cdc_endpoint_in = + { + .bLength = sizeof(tusb_descriptor_endpoint_t), + .bDescriptorType = TUSB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = { .xfer = TUSB_XFER_BULK }, + .wMaxPacketSize = 64, + .bInterval = 0 + }, +}; diff --git a/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.h b/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.h new file mode 100644 index 000000000..685e629ce --- /dev/null +++ b/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.h @@ -0,0 +1,84 @@ +/**************************************************************************/ +/*! + @file descriptor_cdc.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_DESCRIPTOR_CDC_H_ +#define _TUSB_DESCRIPTOR_CDC_H_ + +#include "tusb.h" +#include "class/cdc.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct +{ + tusb_descriptor_configuration_t configuration; + + tusb_descriptor_interface_association_t cdc_iad; + + //CDC Control Interface + tusb_descriptor_interface_t cdc_comm_interface; + tusb_cdc_func_header_t cdc_header; + tusb_cdc_func_abstract_control_management_t cdc_acm; + tusb_cdc_func_union_t cdc_union; + tusb_descriptor_endpoint_t cdc_endpoint_notification; + + //CDC Data Interface + tusb_descriptor_interface_t cdc_data_interface; + tusb_descriptor_endpoint_t cdc_endpoint_out; + tusb_descriptor_endpoint_t cdc_endpoint_in; + +} cdc_configuration_desc_t; + +extern const cdc_configuration_desc_t cdc_config_descriptor; + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DESCRIPTOR_CDC_H_ */ + +/** @} */ diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c new file mode 100644 index 000000000..53e76a70f --- /dev/null +++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/*! + @file test_cdc_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 "stdlib.h" +#include "unity.h" +#include "tusb_option.h" +#include "errors.h" +#include "binary.h" +#include "type_helper.h" + +#include "mock_osal.h" +#include "mock_hcd.h" +#include "mock_usbh.h" + +#include "descriptor_cdc.h" +#include "cdc_host.h" + +uint8_t dev_addr; +uint16_t length; + +tusb_descriptor_interface_t const * p_comm_interface = &cdc_config_descriptor.cdc_comm_interface; +tusb_descriptor_endpoint_t const * p_endpoint_notification = &cdc_config_descriptor.cdc_endpoint_notification; +tusb_descriptor_endpoint_t const * p_endpoint_out = &cdc_config_descriptor.cdc_endpoint_out; +tusb_descriptor_endpoint_t const * p_endpoint_in = &cdc_config_descriptor.cdc_endpoint_in; + +extern cdch_data_t cdch_data[TUSB_CFG_HOST_DEVICE_MAX]; +cdch_data_t * p_cdc = &cdch_data[0]; + +void setUp(void) +{ + length = 0; + dev_addr = 1; + + cdch_init(); +} + +void tearDown(void) +{ + +} + + +void test_cdch_open_failed_to_open_notification_endpoint(void) +{ + pipe_handle_t null_hdl = {0}; + + hcd_pipe_open_ExpectAndReturn(dev_addr, p_endpoint_notification, TUSB_CLASS_CDC, null_hdl); + + //------------- CUT -------------// + TEST_ASSERT_EQUAL(TUSB_ERROR_HCD_OPEN_PIPE_FAILED, cdch_open_subtask(dev_addr, p_comm_interface, &length)); + +} + +void test_cdch_open_failed_to_open_data_endpoint_out(void) +{ + pipe_handle_t dummy_hld = { .dev_addr = 1 }; + pipe_handle_t null_hdl = {0}; + + hcd_pipe_open_ExpectAndReturn(dev_addr, p_endpoint_notification, TUSB_CLASS_CDC, dummy_hld); + hcd_pipe_open_ExpectAndReturn(dev_addr, p_endpoint_out, TUSB_CLASS_CDC, null_hdl); + + //------------- CUT -------------// + TEST_ASSERT_EQUAL(TUSB_ERROR_HCD_OPEN_PIPE_FAILED, cdch_open_subtask(dev_addr, p_comm_interface, &length)); + +} + +void test_cdch_open_failed_to_open_data_endpoint_in(void) +{ + pipe_handle_t dummy_hld = { .dev_addr = 1 }; + pipe_handle_t null_hdl = {0}; + + hcd_pipe_open_ExpectAndReturn(dev_addr, p_endpoint_notification, TUSB_CLASS_CDC, dummy_hld); + hcd_pipe_open_ExpectAndReturn(dev_addr, p_endpoint_out, TUSB_CLASS_CDC, dummy_hld); + hcd_pipe_open_ExpectAndReturn(dev_addr, p_endpoint_in, TUSB_CLASS_CDC, null_hdl); + + //------------- CUT -------------// + TEST_ASSERT_EQUAL(TUSB_ERROR_HCD_OPEN_PIPE_FAILED, cdch_open_subtask(dev_addr, p_comm_interface, &length)); + +} + +void test_cdch_open_length_check(void) +{ + const uint16_t expected_length = + //------------- Comm Interface -------------// + sizeof(tusb_descriptor_interface_t) + sizeof(tusb_cdc_func_header_t) + + sizeof(tusb_cdc_func_abstract_control_management_t) + sizeof(tusb_cdc_func_union_t) + + sizeof(tusb_descriptor_endpoint_t) + + //------------- Data Interface -------------// + sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t); + + pipe_handle_t dummy_hld = { .dev_addr = 1 }; + hcd_pipe_open_IgnoreAndReturn(dummy_hld); + + //------------- CUT -------------// + TEST_ASSERT_EQUAL( TUSB_ERROR_NONE, cdch_open_subtask(dev_addr, p_comm_interface, &length) ); + + TEST_ASSERT_EQUAL(expected_length, length); +} + +void test_cdch_open_interface_number_check(void) +{ + pipe_handle_t dummy_hld = { .dev_addr = 1 }; + hcd_pipe_open_IgnoreAndReturn(dummy_hld); + + //------------- CUT -------------// + TEST_ASSERT_EQUAL( TUSB_ERROR_NONE, cdch_open_subtask(dev_addr, p_comm_interface, &length) ); + + TEST_ASSERT_EQUAL(1, p_cdc->interface_number); + +} + + + + diff --git a/tests/lpc18xx_43xx/test/host/host_helper.h b/tests/lpc18xx_43xx/test/host/host_helper.h index 97102c565..eecd03a8b 100644 --- a/tests/lpc18xx_43xx/test/host/host_helper.h +++ b/tests/lpc18xx_43xx/test/host/host_helper.h @@ -1,39 +1,40 @@ -/* - * host_helper.h - * - * Created on: May 13, 2013 - * Author: hathach - */ +/**************************************************************************/ +/*! + @file host_helper.h + @author hathach (tinyusb.org) -/* - * Software License Agreement (BSD License) - * Copyright (c) 2012, 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 tiny usb stack. - */ + @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 "common/common.h" #include "host/usbh.h" @@ -41,7 +42,14 @@ static inline void helper_class_init_expect(void) { +#if TUSB_CFG_HOST_CDC + cdch_init_Expect(); +#endif + +#if HOST_CLASS_HID hidh_init_Expect(); +#endif + //TODO update more classes } diff --git a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c index ae3fe34c5..d233c45d4 100644 --- a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c +++ b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c @@ -47,6 +47,7 @@ #include "mock_tusb_callback.h" #include "mock_hid_host.h" +#include "mock_cdc_host.h" extern usbh_device_info_t usbh_devices[TUSB_CFG_HOST_DEVICE_MAX+1]; extern uint8_t enum_data_buffer[TUSB_CFG_HOST_ENUM_BUFFER_SIZE]; diff --git a/tests/support/tusb_config.h b/tests/support/tusb_config.h index eb7b462c5..fad061ba7 100644 --- a/tests/support/tusb_config.h +++ b/tests/support/tusb_config.h @@ -74,6 +74,7 @@ //------------- CLASS -------------// #define TUSB_CFG_HOST_HID_KEYBOARD 1 #define TUSB_CFG_HOST_HID_MOUSE 1 +#define TUSB_CFG_HOST_CDC 1 #define HOST_HCD_XFER_INTERRUPT #define HOST_HCD_XFER_BULK 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