diff options
| author | Peter Lawrence <[email protected]> | 2020-03-15 18:28:13 -0500 |
|---|---|---|
| committer | Peter Lawrence <[email protected]> | 2020-03-15 18:28:13 -0500 |
| commit | e7efcb6fd57b689d25a3b42d01c14ffe39e76500 (patch) | |
| tree | 20e9d5b48207299aadeaf8d37bcfe826608997c9 /src/class/cdc | |
| parent | 53732805b76882b3e0eba561ce854e0a95dd6dfe (diff) | |
| parent | a0eb8a26517040850a0e4185aef398183b04ddc7 (diff) | |
merge with current master
Diffstat (limited to 'src/class/cdc')
| -rw-r--r-- | src/class/cdc/cdc.h | 810 | ||||
| -rw-r--r-- | src/class/cdc/cdc_device.c | 839 | ||||
| -rw-r--r-- | src/class/cdc/cdc_device.h | 426 | ||||
| -rw-r--r-- | src/class/cdc/cdc_host.c | 450 | ||||
| -rw-r--r-- | src/class/cdc/cdc_host.h | 246 |
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_ */ |
