summaryrefslogtreecommitdiff
path: root/src/class/cdc
diff options
context:
space:
mode:
authorPeter Lawrence <[email protected]>2020-03-15 18:28:13 -0500
committerPeter Lawrence <[email protected]>2020-03-15 18:28:13 -0500
commite7efcb6fd57b689d25a3b42d01c14ffe39e76500 (patch)
tree20e9d5b48207299aadeaf8d37bcfe826608997c9 /src/class/cdc
parent53732805b76882b3e0eba561ce854e0a95dd6dfe (diff)
parenta0eb8a26517040850a0e4185aef398183b04ddc7 (diff)
merge with current master
Diffstat (limited to 'src/class/cdc')
-rw-r--r--src/class/cdc/cdc.h810
-rw-r--r--src/class/cdc/cdc_device.c839
-rw-r--r--src/class/cdc/cdc_device.h426
-rw-r--r--src/class/cdc/cdc_host.c450
-rw-r--r--src/class/cdc/cdc_host.h246
5 files changed, 1390 insertions, 1381 deletions
diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h
index 9cc8b82e3..f0488acbb 100644
--- a/src/class/cdc/cdc.h
+++ b/src/class/cdc/cdc.h
@@ -1,405 +1,405 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-/** \ingroup group_class
- * \defgroup ClassDriver_CDC Communication Device Class (CDC)
- * Currently only Abstract Control Model subclass is supported
- * @{ */
-
-#ifndef _TUSB_CDC_H__
-#define _TUSB_CDC_H__
-
-#include "common/tusb_common.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/** \defgroup ClassDriver_CDC_Common Common Definitions
- * @{ */
-
-// TODO remove
-/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In)
-typedef enum
-{
- CDC_PIPE_NOTIFICATION , ///< Notification pipe
- CDC_PIPE_DATA_IN , ///< Data in pipe
- CDC_PIPE_DATA_OUT , ///< Data out pipe
- CDC_PIPE_ERROR , ///< Invalid Pipe ID
-}cdc_pipeid_t;
-
-//--------------------------------------------------------------------+
-// CDC Communication Interface Class
-//--------------------------------------------------------------------+
-
-/// Communication Interface Subclass Codes
-typedef enum
-{
- CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2]
- CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL , ///< Abstract Control Model [USBPSTN1.2]
- CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL , ///< Telephone Control Model [USBPSTN1.2]
- CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL , ///< Multi-Channel Control Model [USBISDN1.2]
- CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL , ///< CAPI Control Model [USBISDN1.2]
- CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2]
- CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL , ///< ATM Networking Control Model [USBATM1.2]
- CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL , ///< Wireless Handset Control Model [USBWMC1.1]
- CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT , ///< Device Management [USBWMC1.1]
- CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL , ///< Mobile Direct Line Model [USBWMC1.1]
- CDC_COMM_SUBCLASS_OBEX , ///< OBEX [USBWMC1.1]
- CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL ///< Ethernet Emulation Model [USBEEM1.0]
-} cdc_comm_sublcass_type_t;
-
-/// Communication Interface Protocol Codes
-typedef enum
-{
- CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol
- CDC_COMM_PROTOCOL_ATCOMMAND , ///< AT Commands: V.250 etc
- CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 , ///< AT Commands defined by PCCA-101
- CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO , ///< AT Commands defined by PCCA-101 & Annex O
- CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 , ///< AT Commands defined by GSM 07.07
- CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 , ///< AT Commands defined by 3GPP 27.007
- CDC_COMM_PROTOCOL_ATCOMMAND_CDMA , ///< AT Commands defined by TIA for CDMA
- CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL ///< Ethernet Emulation Model
-} cdc_comm_protocol_type_t;
-
-//------------- SubType Descriptor in COMM Functional Descriptor -------------//
-/// Communication Interface SubType Descriptor
-typedef enum
-{
- CDC_FUNC_DESC_HEADER = 0x00 , ///< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface.
- CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 , ///< Call Management Functional Descriptor.
- CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 , ///< Abstract Control Management Functional Descriptor.
- CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 , ///< Direct Line Management Functional Descriptor.
- CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 , ///< Telephone Ringer Functional Descriptor.
- CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 , ///< Telephone Call and Line State Reporting Capabilities Functional Descriptor.
- CDC_FUNC_DESC_UNION = 0x06 , ///< Union Functional Descriptor
- CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 , ///< Country Selection Functional Descriptor
- CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 , ///< Telephone Operational ModesFunctional Descriptor
- CDC_FUNC_DESC_USB_TERMINAL = 0x09 , ///< USB Terminal Functional Descriptor
- CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A , ///< Network Channel Terminal Descriptor
- CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B , ///< Protocol Unit Functional Descriptor
- CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C , ///< Extension Unit Functional Descriptor
- CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D , ///< Multi-Channel Management Functional Descriptor
- CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E , ///< CAPI Control Management Functional Descriptor
- CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F , ///< Ethernet Networking Functional Descriptor
- CDC_FUNC_DESC_ATM_NETWORKING = 0x10 , ///< ATM Networking Functional Descriptor
- CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 , ///< Wireless Handset Control Model Functional Descriptor
- CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 , ///< Mobile Direct Line Model Functional Descriptor
- CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 , ///< MDLM Detail Functional Descriptor
- CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 , ///< Device Management Model Functional Descriptor
- CDC_FUNC_DESC_OBEX = 0x15 , ///< OBEX Functional Descriptor
- CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor
- CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor
- CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor
- CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 ///< OBEX Service Identifier Functional Descriptor
-}cdc_func_desc_type_t;
-
-//--------------------------------------------------------------------+
-// CDC Data Interface Class
-//--------------------------------------------------------------------+
-
-// SUBCLASS code of Data Interface is not used and should/must be zero
-/// Data Interface Protocol Codes
-typedef enum{
- CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI
- CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC
- CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, ///< Transparent
- CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50, ///< Management protocol for Q.921 data link protocol
- CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51, ///< Data link protocol for Q.931
- CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52, ///< TEI-multiplexor for Q.921 data link protocol
- CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90, ///< Data compression procedures
- CDC_DATA_PROTOCOL_EURO_ISDN = 0x91, ///< Euro-ISDN protocol control
- CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92, ///< V.24 rate adaptation to ISDN
- CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93, ///< CAPI Commands
- CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD, ///< Host based driver. Note: This protocol code should only be used in messages between host and device to identify the host driver portion of a protocol stack.
- CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE ///< The protocol(s) are described using a ProtocolUnit Functional Descriptors on Communications Class Interface
-}cdc_data_protocol_type_t;
-
-//--------------------------------------------------------------------+
-// Management Element Request (Control Endpoint)
-//--------------------------------------------------------------------+
-
-/// Communication Interface Management Element Request Codes
-typedef enum
-{
- CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface
- CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface.
-
- CDC_REQUEST_SET_COMM_FEATURE = 0x02,
- CDC_REQUEST_GET_COMM_FEATURE = 0x03,
- CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04,
-
- CDC_REQUEST_SET_AUX_LINE_STATE = 0x10,
- CDC_REQUEST_SET_HOOK_STATE = 0x11,
- CDC_REQUEST_PULSE_SETUP = 0x12,
- CDC_REQUEST_SEND_PULSE = 0x13,
- CDC_REQUEST_SET_PULSE_TIME = 0x14,
- CDC_REQUEST_RING_AUX_JACK = 0x15,
-
- CDC_REQUEST_SET_LINE_CODING = 0x20,
- CDC_REQUEST_GET_LINE_CODING = 0x21,
- CDC_REQUEST_SET_CONTROL_LINE_STATE = 0x22,
- CDC_REQUEST_SEND_BREAK = 0x23,
-
- CDC_REQUEST_SET_RINGER_PARMS = 0x30,
- CDC_REQUEST_GET_RINGER_PARMS = 0x31,
- CDC_REQUEST_SET_OPERATION_PARMS = 0x32,
- CDC_REQUEST_GET_OPERATION_PARMS = 0x33,
- CDC_REQUEST_SET_LINE_PARMS = 0x34,
- CDC_REQUEST_GET_LINE_PARMS = 0x35,
- CDC_REQUEST_DIAL_DIGITS = 0x36,
- CDC_REQUEST_SET_UNIT_PARAMETER = 0x37,
- CDC_REQUEST_GET_UNIT_PARAMETER = 0x38,
- CDC_REQUEST_CLEAR_UNIT_PARAMETER = 0x39,
- CDC_REQUEST_GET_PROFILE = 0x3A,
-
- CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS = 0x40,
- CDC_REQUEST_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
- CDC_REQUEST_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
- CDC_REQUEST_SET_ETHERNET_PACKET_FILTER = 0x43,
- CDC_REQUEST_GET_ETHERNET_STATISTIC = 0x44,
-
- CDC_REQUEST_SET_ATM_DATA_FORMAT = 0x50,
- CDC_REQUEST_GET_ATM_DEVICE_STATISTICS = 0x51,
- CDC_REQUEST_SET_ATM_DEFAULT_VC = 0x52,
- CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53,
-
- CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60,
-}cdc_management_request_t;
-
-//--------------------------------------------------------------------+
-// Management Elemenent Notification (Notification Endpoint)
-//--------------------------------------------------------------------+
-
-/// Communication Interface Management Element Notification Codes
-typedef enum
-{
- NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status.
- RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request.
-
- AUX_JACK_HOOK_STATE = 0x08,
- RING_DETECT = 0x09,
-
- SERIAL_STATE = 0x20,
-
- CALL_STATE_CHANGE = 0x28,
- LINE_STATE_CHANGE = 0x29,
- CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred
- MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
-}cdc_notification_request_t;
-
-//--------------------------------------------------------------------+
-// Class Specific Functional Descriptor (Communication Interface)
-//--------------------------------------------------------------------+
-
-/// Header Functional Descriptor (Communication Interface)
-typedef struct TU_ATTR_PACKED
-{
- 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_FUNC_DESC_
- uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal
-}cdc_desc_func_header_t;
-
-/// Union Functional Descriptor (Communication Interface)
-typedef struct TU_ATTR_PACKED
-{
- 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 bControlInterface ; ///< Interface number of Communication Interface
- uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface
-}cdc_desc_func_union_t;
-
-#define cdc_desc_func_union_n_t(no_slave)\
- struct TU_ATTR_PACKED { \
- uint8_t bLength ;\
- uint8_t bDescriptorType ;\
- uint8_t bDescriptorSubType ;\
- uint8_t bControlInterface ;\
- uint8_t bSubordinateInterface[no_slave] ;\
-}
-
-/// Country Selection Functional Descriptor (Communication Interface)
-typedef struct TU_ATTR_PACKED
-{
- 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 ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
-}cdc_desc_func_country_selection_t;
-
-#define cdc_desc_func_country_selection_n_t(no_country) \
- struct TU_ATTR_PACKED {\
- uint8_t bLength ;\
- uint8_t bDescriptorType ;\
- uint8_t bDescriptorSubType ;\
- uint8_t iCountryCodeRelDate ;\
- uint16_t wCountryCode[no_country] ;\
-}
-
-//--------------------------------------------------------------------+
-// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS
-//--------------------------------------------------------------------+
-
-/// \brief Call Management Functional Descriptor
-/// \details This functional descriptor describes the processing of calls for the Communications Class interface.
-typedef struct TU_ATTR_PACKED
-{
- 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_
-
- struct {
- uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
- uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
- uint8_t : 0;
- } bmCapabilities;
-
- uint8_t bDataInterface;
-}cdc_desc_func_call_management_t;
-
-
-typedef struct TU_ATTR_PACKED
-{
- uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
- uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
- uint8_t support_send_break : 1; ///< Device supports the request Send_Break
- uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
- uint8_t : 0;
-}cdc_acm_capability_t;
-
-TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
-
-/// \brief Abstract Control Management Functional Descriptor
-/// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
-typedef struct TU_ATTR_PACKED
-{
- 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_
- cdc_acm_capability_t bmCapabilities ;
-}cdc_desc_func_acm_t;
-
-/// \brief Direct Line Management Functional Descriptor
-/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT
-typedef struct TU_ATTR_PACKED
-{
- 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_
- struct {
- uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
- uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
- uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
- uint8_t : 0;
- } bmCapabilities;
-}cdc_desc_func_direct_line_management_t;
-
-/// \brief Telephone Ringer Functional Descriptor
-/// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface,
-/// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL
-typedef struct TU_ATTR_PACKED
-{
- 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 bRingerVolSteps ;
- uint8_t bNumRingerPatterns ;
-}cdc_desc_func_telephone_ringer_t;
-
-/// \brief Telephone Operational Modes Functional Descriptor
-/// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by
-/// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL
-typedef struct TU_ATTR_PACKED
-{
- 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_
- struct {
- uint8_t simple_mode : 1;
- uint8_t standalone_mode : 1;
- uint8_t computer_centric_mode : 1;
- uint8_t : 0;
- } bmCapabilities;
-}cdc_desc_func_telephone_operational_modes_t;
-
-/// \brief Telephone Call and Line State Reporting Capabilities Descriptor
-/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a
-/// telephone device to report optional call and line states.
-typedef struct TU_ATTR_PACKED
-{
- 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_
- struct {
- uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone
- uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
- uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
- uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
- uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
- uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
- uint32_t : 0;
- } bmCapabilities;
-}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
-
-static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
-{
- return p_desc[2];
-}
-
-//--------------------------------------------------------------------+
-// Requests
-//--------------------------------------------------------------------+
-typedef struct TU_ATTR_PACKED
-{
- uint32_t bit_rate;
- uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
- uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
- uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
-} cdc_line_coding_t;
-
-TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct");
-
-typedef struct TU_ATTR_PACKED
-{
- uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR.
- uint16_t half_duplex_carrier_control : 1;
- uint16_t : 14;
-} cdc_line_control_state_t;
-
-TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct");
-
-/** @} */
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
-
-/** @} */
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+/** \ingroup group_class
+ * \defgroup ClassDriver_CDC Communication Device Class (CDC)
+ * Currently only Abstract Control Model subclass is supported
+ * @{ */
+
+#ifndef _TUSB_CDC_H__
+#define _TUSB_CDC_H__
+
+#include "common/tusb_common.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** \defgroup ClassDriver_CDC_Common Common Definitions
+ * @{ */
+
+// TODO remove
+/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In)
+typedef enum
+{
+ CDC_PIPE_NOTIFICATION , ///< Notification pipe
+ CDC_PIPE_DATA_IN , ///< Data in pipe
+ CDC_PIPE_DATA_OUT , ///< Data out pipe
+ CDC_PIPE_ERROR , ///< Invalid Pipe ID
+}cdc_pipeid_t;
+
+//--------------------------------------------------------------------+
+// CDC Communication Interface Class
+//--------------------------------------------------------------------+
+
+/// Communication Interface Subclass Codes
+typedef enum
+{
+ CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2]
+ CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL , ///< Abstract Control Model [USBPSTN1.2]
+ CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL , ///< Telephone Control Model [USBPSTN1.2]
+ CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL , ///< Multi-Channel Control Model [USBISDN1.2]
+ CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL , ///< CAPI Control Model [USBISDN1.2]
+ CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2]
+ CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL , ///< ATM Networking Control Model [USBATM1.2]
+ CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL , ///< Wireless Handset Control Model [USBWMC1.1]
+ CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT , ///< Device Management [USBWMC1.1]
+ CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL , ///< Mobile Direct Line Model [USBWMC1.1]
+ CDC_COMM_SUBCLASS_OBEX , ///< OBEX [USBWMC1.1]
+ CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL ///< Ethernet Emulation Model [USBEEM1.0]
+} cdc_comm_sublcass_type_t;
+
+/// Communication Interface Protocol Codes
+typedef enum
+{
+ CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol
+ CDC_COMM_PROTOCOL_ATCOMMAND , ///< AT Commands: V.250 etc
+ CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 , ///< AT Commands defined by PCCA-101
+ CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO , ///< AT Commands defined by PCCA-101 & Annex O
+ CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 , ///< AT Commands defined by GSM 07.07
+ CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 , ///< AT Commands defined by 3GPP 27.007
+ CDC_COMM_PROTOCOL_ATCOMMAND_CDMA , ///< AT Commands defined by TIA for CDMA
+ CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL ///< Ethernet Emulation Model
+} cdc_comm_protocol_type_t;
+
+//------------- SubType Descriptor in COMM Functional Descriptor -------------//
+/// Communication Interface SubType Descriptor
+typedef enum
+{
+ CDC_FUNC_DESC_HEADER = 0x00 , ///< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface.
+ CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 , ///< Call Management Functional Descriptor.
+ CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 , ///< Abstract Control Management Functional Descriptor.
+ CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 , ///< Direct Line Management Functional Descriptor.
+ CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 , ///< Telephone Ringer Functional Descriptor.
+ CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 , ///< Telephone Call and Line State Reporting Capabilities Functional Descriptor.
+ CDC_FUNC_DESC_UNION = 0x06 , ///< Union Functional Descriptor
+ CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 , ///< Country Selection Functional Descriptor
+ CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 , ///< Telephone Operational ModesFunctional Descriptor
+ CDC_FUNC_DESC_USB_TERMINAL = 0x09 , ///< USB Terminal Functional Descriptor
+ CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A , ///< Network Channel Terminal Descriptor
+ CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B , ///< Protocol Unit Functional Descriptor
+ CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C , ///< Extension Unit Functional Descriptor
+ CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D , ///< Multi-Channel Management Functional Descriptor
+ CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E , ///< CAPI Control Management Functional Descriptor
+ CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F , ///< Ethernet Networking Functional Descriptor
+ CDC_FUNC_DESC_ATM_NETWORKING = 0x10 , ///< ATM Networking Functional Descriptor
+ CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 , ///< Wireless Handset Control Model Functional Descriptor
+ CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 , ///< Mobile Direct Line Model Functional Descriptor
+ CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 , ///< MDLM Detail Functional Descriptor
+ CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 , ///< Device Management Model Functional Descriptor
+ CDC_FUNC_DESC_OBEX = 0x15 , ///< OBEX Functional Descriptor
+ CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor
+ CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor
+ CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor
+ CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 ///< OBEX Service Identifier Functional Descriptor
+}cdc_func_desc_type_t;
+
+//--------------------------------------------------------------------+
+// CDC Data Interface Class
+//--------------------------------------------------------------------+
+
+// SUBCLASS code of Data Interface is not used and should/must be zero
+/// Data Interface Protocol Codes
+typedef enum{
+ CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI
+ CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC
+ CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, ///< Transparent
+ CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50, ///< Management protocol for Q.921 data link protocol
+ CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51, ///< Data link protocol for Q.931
+ CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52, ///< TEI-multiplexor for Q.921 data link protocol
+ CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90, ///< Data compression procedures
+ CDC_DATA_PROTOCOL_EURO_ISDN = 0x91, ///< Euro-ISDN protocol control
+ CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92, ///< V.24 rate adaptation to ISDN
+ CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93, ///< CAPI Commands
+ CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD, ///< Host based driver. Note: This protocol code should only be used in messages between host and device to identify the host driver portion of a protocol stack.
+ CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE ///< The protocol(s) are described using a ProtocolUnit Functional Descriptors on Communications Class Interface
+}cdc_data_protocol_type_t;
+
+//--------------------------------------------------------------------+
+// Management Element Request (Control Endpoint)
+//--------------------------------------------------------------------+
+
+/// Communication Interface Management Element Request Codes
+typedef enum
+{
+ CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface
+ CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface.
+
+ CDC_REQUEST_SET_COMM_FEATURE = 0x02,
+ CDC_REQUEST_GET_COMM_FEATURE = 0x03,
+ CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04,
+
+ CDC_REQUEST_SET_AUX_LINE_STATE = 0x10,
+ CDC_REQUEST_SET_HOOK_STATE = 0x11,
+ CDC_REQUEST_PULSE_SETUP = 0x12,
+ CDC_REQUEST_SEND_PULSE = 0x13,
+ CDC_REQUEST_SET_PULSE_TIME = 0x14,
+ CDC_REQUEST_RING_AUX_JACK = 0x15,
+
+ CDC_REQUEST_SET_LINE_CODING = 0x20,
+ CDC_REQUEST_GET_LINE_CODING = 0x21,
+ CDC_REQUEST_SET_CONTROL_LINE_STATE = 0x22,
+ CDC_REQUEST_SEND_BREAK = 0x23,
+
+ CDC_REQUEST_SET_RINGER_PARMS = 0x30,
+ CDC_REQUEST_GET_RINGER_PARMS = 0x31,
+ CDC_REQUEST_SET_OPERATION_PARMS = 0x32,
+ CDC_REQUEST_GET_OPERATION_PARMS = 0x33,
+ CDC_REQUEST_SET_LINE_PARMS = 0x34,
+ CDC_REQUEST_GET_LINE_PARMS = 0x35,
+ CDC_REQUEST_DIAL_DIGITS = 0x36,
+ CDC_REQUEST_SET_UNIT_PARAMETER = 0x37,
+ CDC_REQUEST_GET_UNIT_PARAMETER = 0x38,
+ CDC_REQUEST_CLEAR_UNIT_PARAMETER = 0x39,
+ CDC_REQUEST_GET_PROFILE = 0x3A,
+
+ CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS = 0x40,
+ CDC_REQUEST_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
+ CDC_REQUEST_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
+ CDC_REQUEST_SET_ETHERNET_PACKET_FILTER = 0x43,
+ CDC_REQUEST_GET_ETHERNET_STATISTIC = 0x44,
+
+ CDC_REQUEST_SET_ATM_DATA_FORMAT = 0x50,
+ CDC_REQUEST_GET_ATM_DEVICE_STATISTICS = 0x51,
+ CDC_REQUEST_SET_ATM_DEFAULT_VC = 0x52,
+ CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53,
+
+ CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60,
+}cdc_management_request_t;
+
+//--------------------------------------------------------------------+
+// Management Elemenent Notification (Notification Endpoint)
+//--------------------------------------------------------------------+
+
+/// Communication Interface Management Element Notification Codes
+typedef enum
+{
+ NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status.
+ RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request.
+
+ AUX_JACK_HOOK_STATE = 0x08,
+ RING_DETECT = 0x09,
+
+ SERIAL_STATE = 0x20,
+
+ CALL_STATE_CHANGE = 0x28,
+ LINE_STATE_CHANGE = 0x29,
+ CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred
+ MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
+}cdc_notification_request_t;
+
+//--------------------------------------------------------------------+
+// Class Specific Functional Descriptor (Communication Interface)
+//--------------------------------------------------------------------+
+
+/// Header Functional Descriptor (Communication Interface)
+typedef struct TU_ATTR_PACKED
+{
+ 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_FUNC_DESC_
+ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal
+}cdc_desc_func_header_t;
+
+/// Union Functional Descriptor (Communication Interface)
+typedef struct TU_ATTR_PACKED
+{
+ 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 bControlInterface ; ///< Interface number of Communication Interface
+ uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface
+}cdc_desc_func_union_t;
+
+#define cdc_desc_func_union_n_t(no_slave)\
+ struct TU_ATTR_PACKED { \
+ uint8_t bLength ;\
+ uint8_t bDescriptorType ;\
+ uint8_t bDescriptorSubType ;\
+ uint8_t bControlInterface ;\
+ uint8_t bSubordinateInterface[no_slave] ;\
+}
+
+/// Country Selection Functional Descriptor (Communication Interface)
+typedef struct TU_ATTR_PACKED
+{
+ 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 ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
+}cdc_desc_func_country_selection_t;
+
+#define cdc_desc_func_country_selection_n_t(no_country) \
+ struct TU_ATTR_PACKED {\
+ uint8_t bLength ;\
+ uint8_t bDescriptorType ;\
+ uint8_t bDescriptorSubType ;\
+ uint8_t iCountryCodeRelDate ;\
+ uint16_t wCountryCode[no_country] ;\
+}
+
+//--------------------------------------------------------------------+
+// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS
+//--------------------------------------------------------------------+
+
+/// \brief Call Management Functional Descriptor
+/// \details This functional descriptor describes the processing of calls for the Communications Class interface.
+typedef struct TU_ATTR_PACKED
+{
+ 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_
+
+ struct {
+ uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
+ uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
+ uint8_t : 0;
+ } bmCapabilities;
+
+ uint8_t bDataInterface;
+}cdc_desc_func_call_management_t;
+
+
+typedef struct TU_ATTR_PACKED
+{
+ uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
+ uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
+ uint8_t support_send_break : 1; ///< Device supports the request Send_Break
+ uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
+ uint8_t : 0;
+}cdc_acm_capability_t;
+
+TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
+
+/// \brief Abstract Control Management Functional Descriptor
+/// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
+typedef struct TU_ATTR_PACKED
+{
+ 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_
+ cdc_acm_capability_t bmCapabilities ;
+}cdc_desc_func_acm_t;
+
+/// \brief Direct Line Management Functional Descriptor
+/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT
+typedef struct TU_ATTR_PACKED
+{
+ 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_
+ struct {
+ uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
+ uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
+ uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
+ uint8_t : 0;
+ } bmCapabilities;
+}cdc_desc_func_direct_line_management_t;
+
+/// \brief Telephone Ringer Functional Descriptor
+/// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface,
+/// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL
+typedef struct TU_ATTR_PACKED
+{
+ 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 bRingerVolSteps ;
+ uint8_t bNumRingerPatterns ;
+}cdc_desc_func_telephone_ringer_t;
+
+/// \brief Telephone Operational Modes Functional Descriptor
+/// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by
+/// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL
+typedef struct TU_ATTR_PACKED
+{
+ 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_
+ struct {
+ uint8_t simple_mode : 1;
+ uint8_t standalone_mode : 1;
+ uint8_t computer_centric_mode : 1;
+ uint8_t : 0;
+ } bmCapabilities;
+}cdc_desc_func_telephone_operational_modes_t;
+
+/// \brief Telephone Call and Line State Reporting Capabilities Descriptor
+/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a
+/// telephone device to report optional call and line states.
+typedef struct TU_ATTR_PACKED
+{
+ 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_
+ struct {
+ uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone
+ uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
+ uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
+ uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
+ uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
+ uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
+ uint32_t : 0;
+ } bmCapabilities;
+}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
+
+static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
+{
+ return p_desc[2];
+}
+
+//--------------------------------------------------------------------+
+// Requests
+//--------------------------------------------------------------------+
+typedef struct TU_ATTR_PACKED
+{
+ uint32_t bit_rate;
+ uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
+ uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
+ uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
+} cdc_line_coding_t;
+
+TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct");
+
+typedef struct TU_ATTR_PACKED
+{
+ uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR.
+ uint16_t half_duplex_carrier_control : 1;
+ uint16_t : 14;
+} cdc_line_control_state_t;
+
+TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct");
+
+/** @} */
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
+/** @} */
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index 015c1c6fd..73eafab07 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -1,415 +1,424 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb_option.h"
-
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC)
-
-#include "cdc_device.h"
-#include "device/usbd_pvt.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-typedef struct
-{
- uint8_t itf_num;
- uint8_t ep_notif;
- uint8_t ep_in;
- uint8_t ep_out;
-
- // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
- uint8_t line_state;
-
- /*------------- From this point, data is not cleared by bus reset -------------*/
- char wanted_char;
- cdc_line_coding_t line_coding;
-
- // FIFO
- tu_fifo_t rx_ff;
- tu_fifo_t tx_ff;
-
- uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE];
- uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE];
-
-#if CFG_FIFO_MUTEX
- osal_mutex_def_t rx_ff_mutex;
- osal_mutex_def_t tx_ff_mutex;
-#endif
-
- // Endpoint Transfer buffer
- CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EPSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EPSIZE];
-
-}cdcd_interface_t;
-
-#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
-
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
-
-static void _prep_out_transaction (uint8_t itf)
-{
- cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
-
- // skip if previous transfer not complete
- if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return;
-
- // Prepare for incoming data but only allow what we can store in the ring buffer.
- uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff);
- if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) )
- {
- usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf));
- }
-}
-
-//--------------------------------------------------------------------+
-// APPLICATION API
-//--------------------------------------------------------------------+
-bool tud_cdc_n_connected(uint8_t itf)
-{
- // DTR (bit 0) active is considered as connected
- return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0);
-}
-
-uint8_t tud_cdc_n_get_line_state (uint8_t itf)
-{
- return _cdcd_itf[itf].line_state;
-}
-
-void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding)
-{
- (*coding) = _cdcd_itf[itf].line_coding;
-}
-
-void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted)
-{
- _cdcd_itf[itf].wanted_char = wanted;
-}
-
-
-//--------------------------------------------------------------------+
-// READ API
-//--------------------------------------------------------------------+
-uint32_t tud_cdc_n_available(uint8_t itf)
-{
- return tu_fifo_count(&_cdcd_itf[itf].rx_ff);
-}
-
-uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
-{
- uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize);
- _prep_out_transaction(itf);
- return num_read;
-}
-
-bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr)
-{
- return tu_fifo_peek_at(&_cdcd_itf[itf].rx_ff, pos, chr);
-}
-
-void tud_cdc_n_read_flush (uint8_t itf)
-{
- tu_fifo_clear(&_cdcd_itf[itf].rx_ff);
- _prep_out_transaction(itf);
-}
-
-//--------------------------------------------------------------------+
-// WRITE API
-//--------------------------------------------------------------------+
-uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
-{
- uint16_t ret = tu_fifo_write_n(&_cdcd_itf[itf].tx_ff, buffer, bufsize);
-
-#if 0 // TODO issue with circuitpython's REPL
- // flush if queue more than endpoint size
- if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EPSIZE )
- {
- tud_cdc_n_write_flush(itf);
- }
-#endif
-
- return ret;
-}
-
-bool tud_cdc_n_write_flush (uint8_t itf)
-{
- cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
- TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete
-
- uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf));
- if ( count )
- {
- TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected
- TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) );
- }
-
- return true;
-}
-
-uint32_t tud_cdc_n_write_available (uint8_t itf)
-{
- return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff);
-}
-
-
-//--------------------------------------------------------------------+
-// USBD Driver API
-//--------------------------------------------------------------------+
-void cdcd_init(void)
-{
- tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
-
- for(uint8_t i=0; i<CFG_TUD_CDC; i++)
- {
- cdcd_interface_t* p_cdc = &_cdcd_itf[i];
-
- p_cdc->wanted_char = -1;
-
- // default line coding is : stop bit = 1, parity = none, data bits = 8
- p_cdc->line_coding.bit_rate = 115200;
- p_cdc->line_coding.stop_bits = 0;
- p_cdc->line_coding.parity = 0;
- p_cdc->line_coding.data_bits = 8;
-
- // config fifo
- tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false);
- tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false);
-
-#if CFG_FIFO_MUTEX
- tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex));
- tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex));
-#endif
- }
-}
-
-void cdcd_reset(uint8_t rhport)
-{
- (void) rhport;
-
- for(uint8_t i=0; i<CFG_TUD_CDC; i++)
- {
- tu_memclr(&_cdcd_itf[i], ITF_MEM_RESET_SIZE);
- tu_fifo_clear(&_cdcd_itf[i].rx_ff);
- tu_fifo_clear(&_cdcd_itf[i].tx_ff);
- }
-}
-
-bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
-{
- // Only support ACM subclass
- TU_ASSERT ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
-
- // Only support AT commands, no protocol and vendor specific commands.
- TU_ASSERT(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) ||
- itf_desc->bInterfaceProtocol == 0xff);
-
- // Find available interface
- cdcd_interface_t * p_cdc = NULL;
- uint8_t cdc_id;
- for(cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++)
- {
- if ( _cdcd_itf[cdc_id].ep_in == 0 )
- {
- p_cdc = &_cdcd_itf[cdc_id];
- break;
- }
- }
- TU_ASSERT(p_cdc);
-
- //------------- Control Interface -------------//
- p_cdc->itf_num = itf_desc->bInterfaceNumber;
-
- uint8_t const * p_desc = tu_desc_next( itf_desc );
- (*p_length) = sizeof(tusb_desc_interface_t);
-
- // Communication Functional Descriptors
- while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
- {
- (*p_length) += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
- }
-
- if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
- {
- // notification endpoint if any
- TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) );
-
- p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
-
- (*p_length) += p_desc[DESC_OFFSET_LEN];
- p_desc = tu_desc_next(p_desc);
- }
-
- //------------- Data Interface (if any) -------------//
- if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
- (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
- {
- // next to endpoint descriptor
- p_desc = tu_desc_next(p_desc);
-
- // Open endpoint pair
- TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) );
-
- (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
- }
-
- // Prepare for incoming data
- _prep_out_transaction(cdc_id);
-
- return true;
-}
-
-// Invoked when class request DATA stage is finished.
-// return false to stall control endpoint (e.g Host send non-sense DATA)
-bool cdcd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
-{
- (void) rhport;
-
- //------------- Class Specific Request -------------//
- TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
-
- uint8_t itf = 0;
- cdcd_interface_t* p_cdc = _cdcd_itf;
-
- // Identify which interface to use
- for ( ; ; itf++, p_cdc++)
- {
- if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
-
- if ( p_cdc->itf_num == request->wIndex ) break;
- }
-
- // Invoke callback
- if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest )
- {
- if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
- }
-
- return true;
-}
-
-// Handle class control request
-// return false to stall control endpoint (e.g unsupported request)
-bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request)
-{
- // Handle class request only
- TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
-
- uint8_t itf = 0;
- cdcd_interface_t* p_cdc = _cdcd_itf;
-
- // Identify which interface to use
- for ( ; ; itf++, p_cdc++)
- {
- if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
-
- if ( p_cdc->itf_num == request->wIndex ) break;
- }
-
- switch ( request->bRequest )
- {
- case CDC_REQUEST_SET_LINE_CODING:
- tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
- break;
-
- case CDC_REQUEST_GET_LINE_CODING:
- tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
- break;
-
- case CDC_REQUEST_SET_CONTROL_LINE_STATE:
- // CDC PSTN v1.2 section 6.3.12
- // Bit 0: Indicates if DTE is present or not.
- // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready)
- // Bit 1: Carrier control for half-duplex modems.
- // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send)
- p_cdc->line_state = (uint8_t) request->wValue;
-
- tud_control_status(rhport, request);
-
- // Invoke callback
- if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, tu_bit_test(request->wValue, 0), tu_bit_test(request->wValue, 1));
- break;
-
- default: return false; // stall unsupported request
- }
-
- return true;
-}
-
-bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
- (void) rhport;
- (void) result;
-
- uint8_t itf = 0;
- cdcd_interface_t* p_cdc = _cdcd_itf;
-
- // Identify which interface to use
- for ( ; ; itf++, p_cdc++)
- {
- if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
-
- if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break;
- }
-
- // Received new data
- if ( ep_addr == p_cdc->ep_out )
- {
- for(uint32_t i=0; i<xferred_bytes; i++)
- {
- tu_fifo_write(&p_cdc->rx_ff, &p_cdc->epout_buf[i]);
-
- // Check for wanted char and invoke callback if needed
- if ( tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1 ) && ( p_cdc->wanted_char == p_cdc->epout_buf[i] ) )
- {
- tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
- }
- }
-
- // invoke receive callback (if there is still data)
- if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
-
- // prepare for OUT transaction
- _prep_out_transaction(itf);
- }
-
- // Data sent to host, we could continue to fetch data tx fifo to send.
- // But it will cause incorrect baudrate set in line coding.
- // Though maybe the baudrate is not really important !!!
- if ( ep_addr == p_cdc->ep_in )
- {
- if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0);
- }
-
- // nothing to do with notif endpoint for now
-
- return true;
-}
-
-#endif
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC)
+
+#include "cdc_device.h"
+#include "device/usbd_pvt.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+typedef struct
+{
+ uint8_t itf_num;
+ uint8_t ep_notif;
+ uint8_t ep_in;
+ uint8_t ep_out;
+
+ // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
+ uint8_t line_state;
+
+ /*------------- From this point, data is not cleared by bus reset -------------*/
+ char wanted_char;
+ cdc_line_coding_t line_coding;
+
+ // FIFO
+ tu_fifo_t rx_ff;
+ tu_fifo_t tx_ff;
+
+ uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE];
+ uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE];
+
+#if CFG_FIFO_MUTEX
+ osal_mutex_def_t rx_ff_mutex;
+ osal_mutex_def_t tx_ff_mutex;
+#endif
+
+ // Endpoint Transfer buffer
+ CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EPSIZE];
+ CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EPSIZE];
+
+}cdcd_interface_t;
+
+#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
+
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+
+static void _prep_out_transaction (uint8_t itf)
+{
+ cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
+
+ // skip if previous transfer not complete
+ if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return;
+
+ // Prepare for incoming data but only allow what we can store in the ring buffer.
+ uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff);
+ if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) )
+ {
+ usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf));
+ }
+}
+
+//--------------------------------------------------------------------+
+// APPLICATION API
+//--------------------------------------------------------------------+
+bool tud_cdc_n_connected(uint8_t itf)
+{
+ // DTR (bit 0) active is considered as connected
+ return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0);
+}
+
+uint8_t tud_cdc_n_get_line_state (uint8_t itf)
+{
+ return _cdcd_itf[itf].line_state;
+}
+
+void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding)
+{
+ (*coding) = _cdcd_itf[itf].line_coding;
+}
+
+void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted)
+{
+ _cdcd_itf[itf].wanted_char = wanted;
+}
+
+
+//--------------------------------------------------------------------+
+// READ API
+//--------------------------------------------------------------------+
+uint32_t tud_cdc_n_available(uint8_t itf)
+{
+ return tu_fifo_count(&_cdcd_itf[itf].rx_ff);
+}
+
+uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
+{
+ uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize);
+ _prep_out_transaction(itf);
+ return num_read;
+}
+
+bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr)
+{
+ return tu_fifo_peek_at(&_cdcd_itf[itf].rx_ff, pos, chr);
+}
+
+void tud_cdc_n_read_flush (uint8_t itf)
+{
+ tu_fifo_clear(&_cdcd_itf[itf].rx_ff);
+ _prep_out_transaction(itf);
+}
+
+//--------------------------------------------------------------------+
+// WRITE API
+//--------------------------------------------------------------------+
+uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
+{
+ uint16_t ret = tu_fifo_write_n(&_cdcd_itf[itf].tx_ff, buffer, bufsize);
+
+#if 0 // TODO issue with circuitpython's REPL
+ // flush if queue more than endpoint size
+ if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EPSIZE )
+ {
+ tud_cdc_n_write_flush(itf);
+ }
+#endif
+
+ return ret;
+}
+
+bool tud_cdc_n_write_flush (uint8_t itf)
+{
+ cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
+ TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete
+
+ uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf));
+ if ( count )
+ {
+ TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected
+ TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) );
+ }
+
+ return true;
+}
+
+uint32_t tud_cdc_n_write_available (uint8_t itf)
+{
+ return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff);
+}
+
+
+//--------------------------------------------------------------------+
+// USBD Driver API
+//--------------------------------------------------------------------+
+void cdcd_init(void)
+{
+ tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
+
+ for(uint8_t i=0; i<CFG_TUD_CDC; i++)
+ {
+ cdcd_interface_t* p_cdc = &_cdcd_itf[i];
+
+ p_cdc->wanted_char = -1;
+
+ // default line coding is : stop bit = 1, parity = none, data bits = 8
+ p_cdc->line_coding.bit_rate = 115200;
+ p_cdc->line_coding.stop_bits = 0;
+ p_cdc->line_coding.parity = 0;
+ p_cdc->line_coding.data_bits = 8;
+
+ // config fifo
+ tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false);
+ tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false);
+
+#if CFG_FIFO_MUTEX
+ tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex));
+ tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex));
+#endif
+ }
+}
+
+void cdcd_reset(uint8_t rhport)
+{
+ (void) rhport;
+
+ for(uint8_t i=0; i<CFG_TUD_CDC; i++)
+ {
+ tu_memclr(&_cdcd_itf[i], ITF_MEM_RESET_SIZE);
+ tu_fifo_clear(&_cdcd_itf[i].rx_ff);
+ tu_fifo_clear(&_cdcd_itf[i].tx_ff);
+ }
+}
+
+bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
+{
+ // Only support ACM subclass
+ TU_ASSERT ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
+
+ // Only support AT commands, no protocol and vendor specific commands.
+ TU_ASSERT(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) ||
+ itf_desc->bInterfaceProtocol == 0xff);
+
+ // Find available interface
+ cdcd_interface_t * p_cdc = NULL;
+ uint8_t cdc_id;
+ for(cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++)
+ {
+ if ( _cdcd_itf[cdc_id].ep_in == 0 )
+ {
+ p_cdc = &_cdcd_itf[cdc_id];
+ break;
+ }
+ }
+ TU_ASSERT(p_cdc);
+
+ //------------- Control Interface -------------//
+ p_cdc->itf_num = itf_desc->bInterfaceNumber;
+
+ uint8_t const * p_desc = tu_desc_next( itf_desc );
+ (*p_length) = sizeof(tusb_desc_interface_t);
+
+ // Communication Functional Descriptors
+ while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
+ {
+ (*p_length) += tu_desc_len(p_desc);
+ p_desc = tu_desc_next(p_desc);
+ }
+
+ if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
+ {
+ // notification endpoint if any
+ TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) );
+
+ p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
+
+ (*p_length) += p_desc[DESC_OFFSET_LEN];
+ p_desc = tu_desc_next(p_desc);
+ }
+
+ //------------- Data Interface (if any) -------------//
+ if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
+ (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
+ {
+ // next to endpoint descriptor
+ p_desc = tu_desc_next(p_desc);
+
+ // Open endpoint pair
+ TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) );
+
+ (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
+ }
+
+ // Prepare for incoming data
+ _prep_out_transaction(cdc_id);
+
+ return true;
+}
+
+// Invoked when class request DATA stage is finished.
+// return false to stall control endpoint (e.g Host send non-sense DATA)
+bool cdcd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
+{
+ (void) rhport;
+
+ //------------- Class Specific Request -------------//
+ TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
+
+ uint8_t itf = 0;
+ cdcd_interface_t* p_cdc = _cdcd_itf;
+
+ // Identify which interface to use
+ for ( ; ; itf++, p_cdc++)
+ {
+ if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
+
+ if ( p_cdc->itf_num == request->wIndex ) break;
+ }
+
+ // Invoke callback
+ if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest )
+ {
+ if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
+ }
+
+ return true;
+}
+
+// Handle class control request
+// return false to stall control endpoint (e.g unsupported request)
+bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request)
+{
+ // Handle class request only
+ TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
+
+ uint8_t itf = 0;
+ cdcd_interface_t* p_cdc = _cdcd_itf;
+
+ // Identify which interface to use
+ for ( ; ; itf++, p_cdc++)
+ {
+ if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
+
+ if ( p_cdc->itf_num == request->wIndex ) break;
+ }
+
+ switch ( request->bRequest )
+ {
+ case CDC_REQUEST_SET_LINE_CODING:
+ TU_LOG2(" Set Line Coding\n");
+ tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
+ break;
+
+ case CDC_REQUEST_GET_LINE_CODING:
+ TU_LOG2(" Get Line Coding\n");
+ tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
+ break;
+
+ case CDC_REQUEST_SET_CONTROL_LINE_STATE:
+ {
+ // CDC PSTN v1.2 section 6.3.12
+ // Bit 0: Indicates if DTE is present or not.
+ // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready)
+ // Bit 1: Carrier control for half-duplex modems.
+ // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send)
+ bool const dtr = tu_bit_test(request->wValue, 0);
+ bool const rts = tu_bit_test(request->wValue, 1);
+
+ p_cdc->line_state = (uint8_t) request->wValue;
+
+ TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts);
+
+ tud_control_status(rhport, request);
+
+ // Invoke callback
+ if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts);
+ }
+ break;
+
+ default: return false; // stall unsupported request
+ }
+
+ return true;
+}
+
+bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
+{
+ (void) rhport;
+ (void) result;
+
+ uint8_t itf = 0;
+ cdcd_interface_t* p_cdc = _cdcd_itf;
+
+ // Identify which interface to use
+ for ( ; ; itf++, p_cdc++)
+ {
+ if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
+
+ if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break;
+ }
+
+ // Received new data
+ if ( ep_addr == p_cdc->ep_out )
+ {
+ for(uint32_t i=0; i<xferred_bytes; i++)
+ {
+ tu_fifo_write(&p_cdc->rx_ff, &p_cdc->epout_buf[i]);
+
+ // Check for wanted char and invoke callback if needed
+ if ( tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1 ) && ( p_cdc->wanted_char == p_cdc->epout_buf[i] ) )
+ {
+ tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
+ }
+ }
+
+ // invoke receive callback (if there is still data)
+ if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
+
+ // prepare for OUT transaction
+ _prep_out_transaction(itf);
+ }
+
+ // Data sent to host, we could continue to fetch data tx fifo to send.
+ // But it will cause incorrect baudrate set in line coding.
+ // Though maybe the baudrate is not really important !!!
+ if ( ep_addr == p_cdc->ep_in )
+ {
+ if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0);
+ }
+
+ // nothing to do with notif endpoint for now
+
+ return true;
+}
+
+#endif
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h
index b8b3c864d..969ec7f99 100644
--- a/src/class/cdc/cdc_device.h
+++ b/src/class/cdc/cdc_device.h
@@ -1,213 +1,213 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef _TUSB_CDC_DEVICE_H_
-#define _TUSB_CDC_DEVICE_H_
-
-#include "common/tusb_common.h"
-#include "device/usbd.h"
-#include "cdc.h"
-
-//--------------------------------------------------------------------+
-// Class Driver Configuration
-//--------------------------------------------------------------------+
-#ifndef CFG_TUD_CDC_EPSIZE
-#define CFG_TUD_CDC_EPSIZE 64
-#endif
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/** \addtogroup CDC_Serial Serial
- * @{
- * \defgroup CDC_Serial_Device Device
- * @{ */
-
-//--------------------------------------------------------------------+
-// Application API (Multiple Interfaces)
-// CFG_TUD_CDC > 1
-//--------------------------------------------------------------------+
-bool tud_cdc_n_connected (uint8_t itf);
-uint8_t tud_cdc_n_get_line_state (uint8_t itf);
-void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding);
-void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted);
-
-uint32_t tud_cdc_n_available (uint8_t itf);
-uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize);
-void tud_cdc_n_read_flush (uint8_t itf);
-bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8);
-static inline int32_t tud_cdc_n_read_char (uint8_t itf);
-
-uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize);
-bool tud_cdc_n_write_flush (uint8_t itf);
-uint32_t tud_cdc_n_write_available (uint8_t itf);
-static inline uint32_t tud_cdc_n_write_char (uint8_t itf, char ch);
-static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str);
-
-//--------------------------------------------------------------------+
-// Application API (Interface0)
-//--------------------------------------------------------------------+
-static inline bool tud_cdc_connected (void);
-static inline uint8_t tud_cdc_get_line_state (void);
-static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding);
-static inline void tud_cdc_set_wanted_char (char wanted);
-
-static inline uint32_t tud_cdc_available (void);
-static inline int32_t tud_cdc_read_char (void);
-static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize);
-static inline void tud_cdc_read_flush (void);
-static inline bool tud_cdc_peek (int pos, uint8_t* u8);
-
-static inline uint32_t tud_cdc_write_char (char ch);
-static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize);
-static inline uint32_t tud_cdc_write_str (char const* str);
-static inline bool tud_cdc_write_flush (void);
-static inline uint32_t tud_cdc_write_available (void);
-
-//--------------------------------------------------------------------+
-// Application Callback API (weak is optional)
-//--------------------------------------------------------------------+
-
-// Invoked when received new data
-TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf);
-
-// Invoked when received `wanted_char`
-TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
-
-// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
-TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts);
-
-// Invoked when line coding is change via SET_LINE_CODING
-TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding);
-
-//--------------------------------------------------------------------+
-// Inline Functions
-//--------------------------------------------------------------------+
-static inline int32_t tud_cdc_n_read_char (uint8_t itf)
-{
- uint8_t ch;
- return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1;
-}
-
-static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch)
-{
- return tud_cdc_n_write(itf, &ch, 1);
-}
-
-static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str)
-{
- return tud_cdc_n_write(itf, str, strlen(str));
-}
-
-static inline bool tud_cdc_connected (void)
-{
- return tud_cdc_n_connected(0);
-}
-
-static inline uint8_t tud_cdc_get_line_state (void)
-{
- return tud_cdc_n_get_line_state(0);
-}
-
-static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding)
-{
- tud_cdc_n_get_line_coding(0, coding);
-}
-
-static inline void tud_cdc_set_wanted_char (char wanted)
-{
- tud_cdc_n_set_wanted_char(0, wanted);
-}
-
-static inline uint32_t tud_cdc_available (void)
-{
- return tud_cdc_n_available(0);
-}
-
-static inline int32_t tud_cdc_read_char (void)
-{
- return tud_cdc_n_read_char(0);
-}
-
-static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize)
-{
- return tud_cdc_n_read(0, buffer, bufsize);
-}
-
-static inline void tud_cdc_read_flush (void)
-{
- tud_cdc_n_read_flush(0);
-}
-
-static inline bool tud_cdc_peek (int pos, uint8_t* u8)
-{
- return tud_cdc_n_peek(0, pos, u8);
-}
-
-static inline uint32_t tud_cdc_write_char (char ch)
-{
- return tud_cdc_n_write_char(0, ch);
-}
-
-static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize)
-{
- return tud_cdc_n_write(0, buffer, bufsize);
-}
-
-static inline uint32_t tud_cdc_write_str (char const* str)
-{
- return tud_cdc_n_write_str(0, str);
-}
-
-static inline bool tud_cdc_write_flush (void)
-{
- return tud_cdc_n_write_flush(0);
-}
-
-static inline uint32_t tud_cdc_write_available(void)
-{
- return tud_cdc_n_write_available(0);
-}
-
-/** @} */
-/** @} */
-
-//--------------------------------------------------------------------+
-// INTERNAL USBD-CLASS DRIVER API
-//--------------------------------------------------------------------+
-void cdcd_init (void);
-void cdcd_reset (uint8_t rhport);
-bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
-bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request);
-bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
-bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_CDC_DEVICE_H_ */
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_CDC_DEVICE_H_
+#define _TUSB_CDC_DEVICE_H_
+
+#include "common/tusb_common.h"
+#include "device/usbd.h"
+#include "cdc.h"
+
+//--------------------------------------------------------------------+
+// Class Driver Configuration
+//--------------------------------------------------------------------+
+#ifndef CFG_TUD_CDC_EPSIZE
+#define CFG_TUD_CDC_EPSIZE 64
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** \addtogroup CDC_Serial Serial
+ * @{
+ * \defgroup CDC_Serial_Device Device
+ * @{ */
+
+//--------------------------------------------------------------------+
+// Application API (Multiple Interfaces)
+// CFG_TUD_CDC > 1
+//--------------------------------------------------------------------+
+bool tud_cdc_n_connected (uint8_t itf);
+uint8_t tud_cdc_n_get_line_state (uint8_t itf);
+void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding);
+void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted);
+
+uint32_t tud_cdc_n_available (uint8_t itf);
+uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize);
+void tud_cdc_n_read_flush (uint8_t itf);
+bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8);
+static inline int32_t tud_cdc_n_read_char (uint8_t itf);
+
+uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize);
+bool tud_cdc_n_write_flush (uint8_t itf);
+uint32_t tud_cdc_n_write_available (uint8_t itf);
+static inline uint32_t tud_cdc_n_write_char (uint8_t itf, char ch);
+static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str);
+
+//--------------------------------------------------------------------+
+// Application API (Interface0)
+//--------------------------------------------------------------------+
+static inline bool tud_cdc_connected (void);
+static inline uint8_t tud_cdc_get_line_state (void);
+static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding);
+static inline void tud_cdc_set_wanted_char (char wanted);
+
+static inline uint32_t tud_cdc_available (void);
+static inline int32_t tud_cdc_read_char (void);
+static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize);
+static inline void tud_cdc_read_flush (void);
+static inline bool tud_cdc_peek (int pos, uint8_t* u8);
+
+static inline uint32_t tud_cdc_write_char (char ch);
+static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize);
+static inline uint32_t tud_cdc_write_str (char const* str);
+static inline bool tud_cdc_write_flush (void);
+static inline uint32_t tud_cdc_write_available (void);
+
+//--------------------------------------------------------------------+
+// Application Callback API (weak is optional)
+//--------------------------------------------------------------------+
+
+// Invoked when received new data
+TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf);
+
+// Invoked when received `wanted_char`
+TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
+
+// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
+TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts);
+
+// Invoked when line coding is change via SET_LINE_CODING
+TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding);
+
+//--------------------------------------------------------------------+
+// Inline Functions
+//--------------------------------------------------------------------+
+static inline int32_t tud_cdc_n_read_char (uint8_t itf)
+{
+ uint8_t ch;
+ return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1;
+}
+
+static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch)
+{
+ return tud_cdc_n_write(itf, &ch, 1);
+}
+
+static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str)
+{
+ return tud_cdc_n_write(itf, str, strlen(str));
+}
+
+static inline bool tud_cdc_connected (void)
+{
+ return tud_cdc_n_connected(0);
+}
+
+static inline uint8_t tud_cdc_get_line_state (void)
+{
+ return tud_cdc_n_get_line_state(0);
+}
+
+static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding)
+{
+ tud_cdc_n_get_line_coding(0, coding);
+}
+
+static inline void tud_cdc_set_wanted_char (char wanted)
+{
+ tud_cdc_n_set_wanted_char(0, wanted);
+}
+
+static inline uint32_t tud_cdc_available (void)
+{
+ return tud_cdc_n_available(0);
+}
+
+static inline int32_t tud_cdc_read_char (void)
+{
+ return tud_cdc_n_read_char(0);
+}
+
+static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize)
+{
+ return tud_cdc_n_read(0, buffer, bufsize);
+}
+
+static inline void tud_cdc_read_flush (void)
+{
+ tud_cdc_n_read_flush(0);
+}
+
+static inline bool tud_cdc_peek (int pos, uint8_t* u8)
+{
+ return tud_cdc_n_peek(0, pos, u8);
+}
+
+static inline uint32_t tud_cdc_write_char (char ch)
+{
+ return tud_cdc_n_write_char(0, ch);
+}
+
+static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize)
+{
+ return tud_cdc_n_write(0, buffer, bufsize);
+}
+
+static inline uint32_t tud_cdc_write_str (char const* str)
+{
+ return tud_cdc_n_write_str(0, str);
+}
+
+static inline bool tud_cdc_write_flush (void)
+{
+ return tud_cdc_n_write_flush(0);
+}
+
+static inline uint32_t tud_cdc_write_available(void)
+{
+ return tud_cdc_n_write_available(0);
+}
+
+/** @} */
+/** @} */
+
+//--------------------------------------------------------------------+
+// INTERNAL USBD-CLASS DRIVER API
+//--------------------------------------------------------------------+
+void cdcd_init (void);
+void cdcd_reset (uint8_t rhport);
+bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
+bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request);
+bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
+bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CDC_DEVICE_H_ */
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index 6a6f508b3..595e7fd62 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -1,225 +1,225 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb_option.h"
-
-#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC)
-
-#include "common/tusb_common.h"
-#include "cdc_host.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-typedef struct {
- uint8_t itf_num;
- uint8_t itf_protocol;
-
- uint8_t ep_notif;
- uint8_t ep_in;
- uint8_t ep_out;
-
- cdc_acm_capability_t acm_capability;
-
-} cdch_data_t;
-
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
-static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX];
-
-bool tuh_cdc_mounted(uint8_t dev_addr)
-{
- cdch_data_t* cdc = &cdch_data[dev_addr-1];
- return cdc->ep_in && cdc->ep_out;
-}
-
-bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid)
-{
- if ( !tuh_cdc_mounted(dev_addr) ) return false;
-
- cdch_data_t const * p_cdc = &cdch_data[dev_addr-1];
-
- switch (pipeid)
- {
- case CDC_PIPE_NOTIFICATION:
- return hcd_edpt_busy(dev_addr, p_cdc->ep_notif );
-
- case CDC_PIPE_DATA_IN:
- return hcd_edpt_busy(dev_addr, p_cdc->ep_in );
-
- case CDC_PIPE_DATA_OUT:
- return hcd_edpt_busy(dev_addr, p_cdc->ep_out );
-
- default:
- return false;
- }
-}
-
-//--------------------------------------------------------------------+
-// APPLICATION API (parameter validation needed)
-//--------------------------------------------------------------------+
-bool tuh_cdc_serial_is_mounted(uint8_t dev_addr)
-{
- // TODO consider all AT Command as serial candidate
- return tuh_cdc_mounted(dev_addr) &&
- (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) &&
- (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA);
-}
-
-bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify)
-{
- TU_VERIFY( tuh_cdc_mounted(dev_addr) );
- TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
-
- uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
- if ( hcd_edpt_busy(dev_addr, ep_out) ) return false;
-
- return hcd_pipe_xfer(dev_addr, ep_out, (void *) p_data, length, is_notify);
-}
-
-bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify)
-{
- TU_VERIFY( tuh_cdc_mounted(dev_addr) );
- TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
-
- uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
- if ( hcd_edpt_busy(dev_addr, ep_in) ) return false;
-
- return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify);
-}
-
-//--------------------------------------------------------------------+
-// USBH-CLASS DRIVER API
-//--------------------------------------------------------------------+
-void cdch_init(void)
-{
- tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX);
-}
-
-bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
-{
- // Only support ACM
- TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
-
- // Only support AT commands, no protocol and vendor specific commands.
- TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) ||
- 0xff == itf_desc->bInterfaceProtocol);
-
- uint8_t const * p_desc;
- cdch_data_t * p_cdc;
-
- p_desc = tu_desc_next(itf_desc);
- p_cdc = &cdch_data[dev_addr-1];
-
- p_cdc->itf_num = itf_desc->bInterfaceNumber;
- p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com
-
- //------------- Communication Interface -------------//
- (*p_length) = sizeof(tusb_desc_interface_t);
-
- // Communication Functional Descriptors
- while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] )
- {
- if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
- {
- // save ACM bmCapabilities
- p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities;
- }
-
- (*p_length) += p_desc[DESC_OFFSET_LEN];
- p_desc = tu_desc_next(p_desc);
- }
-
- if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
- {
- // notification endpoint
- tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc;
-
- TU_ASSERT( hcd_edpt_open(rhport, dev_addr, ep_desc) );
- p_cdc->ep_notif = ep_desc->bEndpointAddress;
-
- (*p_length) += p_desc[DESC_OFFSET_LEN];
- p_desc = tu_desc_next(p_desc);
- }
-
- //------------- Data Interface (if any) -------------//
- if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
- (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
- {
- (*p_length) += p_desc[DESC_OFFSET_LEN];
- p_desc = tu_desc_next(p_desc);
-
- // data endpoints expected to be in pairs
- for(uint32_t i=0; i<2; i++)
- {
- tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc;
- TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
- TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
-
- TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc));
-
- if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
- {
- p_cdc->ep_in = ep_desc->bEndpointAddress;
- }else
- {
- p_cdc->ep_out = ep_desc->bEndpointAddress;
- }
-
- (*p_length) += p_desc[DESC_OFFSET_LEN];
- p_desc = tu_desc_next( p_desc );
- }
- }
-
- // FIXME move to seperate API : connect
- tusb_control_request_t request =
- {
- .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT },
- .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
- .wValue = 0x03, // dtr on, cst on
- .wIndex = p_cdc->itf_num,
- .wLength = 0
- };
-
- TU_ASSERT( usbh_control_xfer(dev_addr, &request, NULL) );
-
- return true;
-}
-
-void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
-{
- (void) ep_addr;
- tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes );
-}
-
-void cdch_close(uint8_t dev_addr)
-{
- cdch_data_t * p_cdc = &cdch_data[dev_addr-1];
- tu_memclr(p_cdc, sizeof(cdch_data_t));
-}
-
-#endif
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC)
+
+#include "common/tusb_common.h"
+#include "cdc_host.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+typedef struct {
+ uint8_t itf_num;
+ uint8_t itf_protocol;
+
+ uint8_t ep_notif;
+ uint8_t ep_in;
+ uint8_t ep_out;
+
+ cdc_acm_capability_t acm_capability;
+
+} cdch_data_t;
+
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX];
+
+bool tuh_cdc_mounted(uint8_t dev_addr)
+{
+ cdch_data_t* cdc = &cdch_data[dev_addr-1];
+ return cdc->ep_in && cdc->ep_out;
+}
+
+bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid)
+{
+ if ( !tuh_cdc_mounted(dev_addr) ) return false;
+
+ cdch_data_t const * p_cdc = &cdch_data[dev_addr-1];
+
+ switch (pipeid)
+ {
+ case CDC_PIPE_NOTIFICATION:
+ return hcd_edpt_busy(dev_addr, p_cdc->ep_notif );
+
+ case CDC_PIPE_DATA_IN:
+ return hcd_edpt_busy(dev_addr, p_cdc->ep_in );
+
+ case CDC_PIPE_DATA_OUT:
+ return hcd_edpt_busy(dev_addr, p_cdc->ep_out );
+
+ default:
+ return false;
+ }
+}
+
+//--------------------------------------------------------------------+
+// APPLICATION API (parameter validation needed)
+//--------------------------------------------------------------------+
+bool tuh_cdc_serial_is_mounted(uint8_t dev_addr)
+{
+ // TODO consider all AT Command as serial candidate
+ return tuh_cdc_mounted(dev_addr) &&
+ (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) &&
+ (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA);
+}
+
+bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify)
+{
+ TU_VERIFY( tuh_cdc_mounted(dev_addr) );
+ TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
+
+ uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
+ if ( hcd_edpt_busy(dev_addr, ep_out) ) return false;
+
+ return hcd_pipe_xfer(dev_addr, ep_out, (void *) p_data, length, is_notify);
+}
+
+bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify)
+{
+ TU_VERIFY( tuh_cdc_mounted(dev_addr) );
+ TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
+
+ uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
+ if ( hcd_edpt_busy(dev_addr, ep_in) ) return false;
+
+ return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify);
+}
+
+//--------------------------------------------------------------------+
+// USBH-CLASS DRIVER API
+//--------------------------------------------------------------------+
+void cdch_init(void)
+{
+ tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX);
+}
+
+bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
+{
+ // Only support ACM
+ TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
+
+ // Only support AT commands, no protocol and vendor specific commands.
+ TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) ||
+ 0xff == itf_desc->bInterfaceProtocol);
+
+ uint8_t const * p_desc;
+ cdch_data_t * p_cdc;
+
+ p_desc = tu_desc_next(itf_desc);
+ p_cdc = &cdch_data[dev_addr-1];
+
+ p_cdc->itf_num = itf_desc->bInterfaceNumber;
+ p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com
+
+ //------------- Communication Interface -------------//
+ (*p_length) = sizeof(tusb_desc_interface_t);
+
+ // Communication Functional Descriptors
+ while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] )
+ {
+ if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
+ {
+ // save ACM bmCapabilities
+ p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities;
+ }
+
+ (*p_length) += p_desc[DESC_OFFSET_LEN];
+ p_desc = tu_desc_next(p_desc);
+ }
+
+ if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
+ {
+ // notification endpoint
+ tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc;
+
+ TU_ASSERT( hcd_edpt_open(rhport, dev_addr, ep_desc) );
+ p_cdc->ep_notif = ep_desc->bEndpointAddress;
+
+ (*p_length) += p_desc[DESC_OFFSET_LEN];
+ p_desc = tu_desc_next(p_desc);
+ }
+
+ //------------- Data Interface (if any) -------------//
+ if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
+ (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
+ {
+ (*p_length) += p_desc[DESC_OFFSET_LEN];
+ p_desc = tu_desc_next(p_desc);
+
+ // data endpoints expected to be in pairs
+ for(uint32_t i=0; i<2; i++)
+ {
+ tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc;
+ TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
+ TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
+
+ TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc));
+
+ if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
+ {
+ p_cdc->ep_in = ep_desc->bEndpointAddress;
+ }else
+ {
+ p_cdc->ep_out = ep_desc->bEndpointAddress;
+ }
+
+ (*p_length) += p_desc[DESC_OFFSET_LEN];
+ p_desc = tu_desc_next( p_desc );
+ }
+ }
+
+ // FIXME move to seperate API : connect
+ tusb_control_request_t request =
+ {
+ .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT },
+ .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
+ .wValue = 0x03, // dtr on, cst on
+ .wIndex = p_cdc->itf_num,
+ .wLength = 0
+ };
+
+ TU_ASSERT( usbh_control_xfer(dev_addr, &request, NULL) );
+
+ return true;
+}
+
+void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
+{
+ (void) ep_addr;
+ tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes );
+}
+
+void cdch_close(uint8_t dev_addr)
+{
+ cdch_data_t * p_cdc = &cdch_data[dev_addr-1];
+ tu_memclr(p_cdc, sizeof(cdch_data_t));
+}
+
+#endif
diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h
index 59ad2bfa8..306420ce4 100644
--- a/src/class/cdc/cdc_host.h
+++ b/src/class/cdc/cdc_host.h
@@ -1,123 +1,123 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef _TUSB_CDC_HOST_H_
-#define _TUSB_CDC_HOST_H_
-
-#include "common/tusb_common.h"
-#include "host/usbh.h"
-#include "cdc.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// CDC APPLICATION PUBLIC API
-//--------------------------------------------------------------------+
-/** \ingroup ClassDriver_CDC Communication Device Class (CDC)
- * \addtogroup CDC_Serial Serial
- * @{
- * \defgroup CDC_Serial_Host Host
- * @{ */
-
-/** \brief Check if device support CDC Serial interface or not
- * \param[in] dev_addr device address
- * \retval true if device supports
- * \retval false if device does not support or is not mounted
- */
-bool tuh_cdc_serial_is_mounted(uint8_t dev_addr);
-
-/** \brief Check if the interface is currently busy or not
- * \param[in] dev_addr device address
- * \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe.
- * \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device
- * \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device
- * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer
- * can be scheduled. User needs to make sure the corresponding interface is mounted
- * (by \ref tuh_cdc_serial_is_mounted) before calling this function.
- */
-bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid);
-
-/** \brief Perform USB OUT transfer to device
- * \param[in] dev_addr device address
- * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
- * \param[in] length Number of bytes to be transferred via USB bus
- * \retval TUSB_ERROR_NONE on success
- * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
- * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
- * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
- * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
- * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
- */
-bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify);
-
-/** \brief Perform USB IN transfer to get data from device
- * \param[in] dev_addr device address
- * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
- * \param[in] length Number of bytes to be transferred via USB bus
- * \retval TUSB_ERROR_NONE on success
- * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
- * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
- * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
- * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
- * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
- */
-bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify);
-
-//--------------------------------------------------------------------+
-// CDC APPLICATION CALLBACKS
-//--------------------------------------------------------------------+
-
-/** \brief Callback function that is invoked when an transferring event occurred
- * \param[in] dev_addr Address of device
- * \param[in] event an value from \ref xfer_result_t
- * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe
- * \param[in] xferred_bytes Number of bytes transferred via USB bus
- * \note event can be one of following
- * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
- * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
- * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
- * \note
- */
-void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
-
-/// @} // group CDC_Serial_Host
-/// @}
-
-//--------------------------------------------------------------------+
-// Internal Class Driver API
-//--------------------------------------------------------------------+
-void cdch_init(void);
-bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length);
-void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
-void cdch_close(uint8_t dev_addr);
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_CDC_HOST_H_ */
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_CDC_HOST_H_
+#define _TUSB_CDC_HOST_H_
+
+#include "common/tusb_common.h"
+#include "host/usbh.h"
+#include "cdc.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// CDC APPLICATION PUBLIC API
+//--------------------------------------------------------------------+
+/** \ingroup ClassDriver_CDC Communication Device Class (CDC)
+ * \addtogroup CDC_Serial Serial
+ * @{
+ * \defgroup CDC_Serial_Host Host
+ * @{ */
+
+/** \brief Check if device support CDC Serial interface or not
+ * \param[in] dev_addr device address
+ * \retval true if device supports
+ * \retval false if device does not support or is not mounted
+ */
+bool tuh_cdc_serial_is_mounted(uint8_t dev_addr);
+
+/** \brief Check if the interface is currently busy or not
+ * \param[in] dev_addr device address
+ * \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe.
+ * \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device
+ * \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device
+ * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer
+ * can be scheduled. User needs to make sure the corresponding interface is mounted
+ * (by \ref tuh_cdc_serial_is_mounted) before calling this function.
+ */
+bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid);
+
+/** \brief Perform USB OUT transfer to device
+ * \param[in] dev_addr device address
+ * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
+ * \param[in] length Number of bytes to be transferred via USB bus
+ * \retval TUSB_ERROR_NONE on success
+ * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
+ * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
+ * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
+ * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
+ * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
+ */
+bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify);
+
+/** \brief Perform USB IN transfer to get data from device
+ * \param[in] dev_addr device address
+ * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
+ * \param[in] length Number of bytes to be transferred via USB bus
+ * \retval TUSB_ERROR_NONE on success
+ * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
+ * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
+ * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
+ * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
+ * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
+ */
+bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify);
+
+//--------------------------------------------------------------------+
+// CDC APPLICATION CALLBACKS
+//--------------------------------------------------------------------+
+
+/** \brief Callback function that is invoked when an transferring event occurred
+ * \param[in] dev_addr Address of device
+ * \param[in] event an value from \ref xfer_result_t
+ * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe
+ * \param[in] xferred_bytes Number of bytes transferred via USB bus
+ * \note event can be one of following
+ * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
+ * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
+ * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
+ * \note
+ */
+void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
+
+/// @} // group CDC_Serial_Host
+/// @}
+
+//--------------------------------------------------------------------+
+// Internal Class Driver API
+//--------------------------------------------------------------------+
+void cdch_init(void);
+bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length);
+void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+void cdch_close(uint8_t dev_addr);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CDC_HOST_H_ */