1 /* 2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 #include <stdbool.h> 10 #include "usb_types_cdc.h" 11 #include "esp_err.h" 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 typedef struct cdc_dev_s *cdc_acm_dev_hdl_t; 18 19 /** 20 * @brief Line Coding structure 21 * @see Table 17, USB CDC-PSTN specification rev. 1.2 22 */ 23 typedef struct { 24 uint32_t dwDTERate; // in bits per second 25 uint8_t bCharFormat; // 0: 1 stopbit, 1: 1.5 stopbits, 2: 2 stopbits 26 uint8_t bParityType; // 0: None, 1: Odd, 2: Even, 3: Mark, 4: Space 27 uint8_t bDataBits; // 5, 6, 7, 8 or 16 28 } __attribute__((packed)) cdc_acm_line_coding_t; 29 30 /** 31 * @brief UART State Bitmap 32 * @see Table 31, USB CDC-PSTN specification rev. 1.2 33 */ 34 typedef union { 35 struct { 36 uint16_t bRxCarrier : 1; // State of receiver carrier detection mechanism of device. This signal corresponds to V.24 signal 109 and RS-232 signal DCD. 37 uint16_t bTxCarrier : 1; // State of transmission carrier. This signal corresponds to V.24 signal 106 and RS-232 signal DSR. 38 uint16_t bBreak : 1; // State of break detection mechanism of the device. 39 uint16_t bRingSignal : 1; // State of ring signal detection of the device. 40 uint16_t bFraming : 1; // A framing error has occurred. 41 uint16_t bParity : 1; // A parity error has occurred. 42 uint16_t bOverRun : 1; // Received data has been discarded due to overrun in the device. 43 uint16_t reserved : 9; 44 }; 45 uint16_t val; 46 } cdc_acm_uart_state_t; 47 48 /** 49 * @brief CDC-ACM Device Event types to upper layer 50 * 51 */ 52 typedef enum { 53 CDC_ACM_HOST_ERROR, 54 CDC_ACM_HOST_SERIAL_STATE, 55 CDC_ACM_HOST_NETWORK_CONNECTION, 56 CDC_ACM_HOST_DEVICE_DISCONNECTED 57 } cdc_acm_host_dev_event_t; 58 59 /** 60 * @brief CDC-ACM Device Event data structure 61 * 62 */ 63 typedef struct { 64 cdc_acm_host_dev_event_t type; 65 union { 66 int error; // Error code from USB Host 67 cdc_acm_uart_state_t serial_state; // Serial (UART) state 68 bool network_connected; // Network connection event 69 } data; 70 } cdc_acm_host_dev_event_data_t; 71 72 /** 73 * @brief Data receive callback type 74 */ 75 typedef void (*cdc_acm_data_callback_t)(uint8_t* data, size_t data_len, void *user_arg); 76 77 /** 78 * @brief Device event callback type 79 * @see cdc_acm_host_dev_event_t 80 */ 81 typedef void (*cdc_acm_host_dev_callback_t)(cdc_acm_dev_hdl_t cdc_hdl, const cdc_acm_host_dev_event_data_t *event, void *user_ctx); 82 83 /** 84 * @brief Configuration structure of USB Host CDC-ACM driver 85 * 86 */ 87 typedef struct { 88 size_t driver_task_stack_size; /**< Stack size of the driver's task */ 89 unsigned driver_task_priority; /**< Priority of the driver's task */ 90 int xCoreID; /**< Core affinity of the driver's task */ 91 } cdc_acm_host_driver_config_t; 92 93 /** 94 * @brief Configuration structure of CDC-ACM device 95 * 96 */ 97 typedef struct { 98 uint32_t connection_timeout_ms; /**< Timeout for USB device connection in [ms] */ 99 size_t out_buffer_size; /**< Maximum size of USB bulk out transfer, set to 0 for read-only devices */ 100 cdc_acm_host_dev_callback_t event_cb; /**< Device's event callback function. Can be NULL */ 101 cdc_acm_data_callback_t data_cb; /**< Device's data RX callback function. Can be NULL for write-only devices */ 102 void *user_arg; /**< User's argument that will be passed to the callbacks */ 103 } cdc_acm_host_device_config_t; 104 105 /** 106 * @brief Install CDC-ACM driver 107 * 108 * - USB Host Library must already be installed before calling this function (via usb_host_install()) 109 * - This function should be called before calling any other CDC driver functions 110 * 111 * @param[in] driver_config Driver configuration structure. If set to NULL, a default configuration will be used. 112 * @return esp_err_t 113 */ 114 esp_err_t cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config); 115 116 /** 117 * @brief Uninstall CDC-ACM driver 118 * 119 * - Users must ensure that all CDC devices must be closed via cdc_acm_host_close() before calling this function 120 * 121 * @return esp_err_t 122 */ 123 esp_err_t cdc_acm_host_uninstall(void); 124 125 /** 126 * @brief Open CDC-ACM compliant device 127 * 128 * CDC-ACM compliant device must contain either an Interface Association Descriptor or CDC-Union descriptor, 129 * which are used for the driver's configuration. 130 * 131 * @param[in] vid Device's Vendor ID 132 * @param[in] pid Device's Product ID 133 * @param[in] interface_idx Index of device's interface used for CDC-ACM communication 134 * @param[in] dev_config Configuration structure of the device 135 * @param[out] cdc_hdl_ret CDC device handle 136 * @return esp_err_t 137 */ 138 esp_err_t cdc_acm_host_open(uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *cdc_hdl_ret); 139 140 /** 141 * @brief Open CDC-ACM non-compliant device 142 * 143 * CDC-ACM non-compliant device acts as CDC-ACM device but doesn't support all its features. 144 * User must provide the interface index that will be used (zero for non-composite devices). 145 * 146 * @param[in] vid Device's Vendor ID 147 * @param[in] pid Device's Product ID 148 * @param[in] interface_idx Index of device's interface used for CDC-ACM like communication 149 * @param[in] dev_config Configuration structure of the device 150 * @param[out] cdc_hdl_ret CDC device handle 151 * @return esp_err_t 152 */ 153 esp_err_t cdc_acm_host_open_vendor_specific(uint16_t vid, uint16_t pid, uint8_t interface_num, const cdc_acm_host_device_config_t *dev_config, cdc_acm_dev_hdl_t *cdc_hdl_ret); 154 155 /** 156 * @brief Close CDC device and release its resources 157 * 158 * @note All in-flight transfers will be prematurely canceled. 159 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 160 * @return esp_err_t 161 */ 162 esp_err_t cdc_acm_host_close(cdc_acm_dev_hdl_t cdc_hdl); 163 164 /** 165 * @brief Transmit data - blocking mode 166 * 167 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 168 * @param[in] data Data to be sent 169 * @param[in] data_len Data length 170 * @param[in] timeout_ms Timeout in [ms] 171 * @return esp_err_t 172 */ 173 esp_err_t cdc_acm_host_data_tx_blocking(cdc_acm_dev_hdl_t cdc_hdl, const uint8_t *data, size_t data_len, uint32_t timeout_ms); 174 175 /** 176 * @brief SetLineCoding function 177 * 178 * @see Chapter 6.3.10, USB CDC-PSTN specification rev. 1.2 179 * 180 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 181 * @param[in] line_coding Line Coding structure 182 * @return esp_err_t 183 */ 184 esp_err_t cdc_acm_host_line_coding_set(cdc_acm_dev_hdl_t cdc_hdl, const cdc_acm_line_coding_t *line_coding); 185 186 /** 187 * @brief GetLineCoding function 188 * 189 * @see Chapter 6.3.11, USB CDC-PSTN specification rev. 1.2 190 * 191 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 192 * @param[out] line_coding Line Coding structure to be filled 193 * @return esp_err_t 194 */ 195 esp_err_t cdc_acm_host_line_coding_get(cdc_acm_dev_hdl_t cdc_hdl, cdc_acm_line_coding_t *line_coding); 196 197 /** 198 * @brief SetControlLineState function 199 * 200 * @see Chapter 6.3.12, USB CDC-PSTN specification rev. 1.2 201 * 202 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 203 * @param[in] dtr Indicates to DCE if DTE is present or not. This signal corresponds to V.24 signal 108/2 and RS-232 signal Data Terminal Ready. 204 * @param[in] rts Carrier control for half duplex modems. This signal corresponds to V.24 signal 105 and RS-232 signal Request To Send. 205 * @return esp_err_t 206 */ 207 esp_err_t cdc_acm_host_set_control_line_state(cdc_acm_dev_hdl_t cdc_hdl, bool dtr, bool rts); 208 209 /** 210 * @brief SendBreak function 211 * 212 * This function will block until the duration_ms has passed. 213 * 214 * @see Chapter 6.3.13, USB CDC-PSTN specification rev. 1.2 215 * 216 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 217 * @param[in] duration_ms Duration of the Break signal in [ms] 218 * @return esp_err_t 219 */ 220 esp_err_t cdc_acm_host_send_break(cdc_acm_dev_hdl_t cdc_hdl, uint16_t duration_ms); 221 222 /** 223 * @brief Print CDC-ACM specific descriptors 224 * 225 * Descriptors are printed in human readable format to stdout. 226 * Intended for debugging and for CDC-ACM compliant devices only. 227 * 228 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 229 */ 230 void cdc_acm_host_desc_print(cdc_acm_dev_hdl_t cdc_hdl); 231 232 /** 233 * @brief Get protocols defined in USB-CDC interface descriptors 234 * 235 * @param cdc_hdl CDC handle obtained from cdc_acm_host_open() 236 * @param[out] comm Communication protocol 237 * @param[out] data Data protocol 238 * @return esp_err_t 239 */ 240 esp_err_t cdc_acm_host_protocols_get(cdc_acm_dev_hdl_t cdc_hdl, cdc_comm_protocol_t *comm, cdc_data_protocol_t *data); 241 242 #ifdef __cplusplus 243 } 244 class CdcAcmDevice 245 { 246 public: 247 // Operators CdcAcmDevice()248 CdcAcmDevice() : cdc_hdl(NULL){}; ~CdcAcmDevice()249 ~CdcAcmDevice() 250 { 251 // Close CDC-ACM device, if it wasn't explicitly closed 252 if (this->cdc_hdl != NULL) { 253 this->close(); 254 } 255 } 256 257 inline esp_err_t tx_blocking(uint8_t *data, size_t len, uint32_t timeout_ms = 100) 258 { 259 return cdc_acm_host_data_tx_blocking(this->cdc_hdl, data, len, timeout_ms); 260 } 261 open(uint16_t vid,uint16_t pid,uint8_t interface_idx,const cdc_acm_host_device_config_t * dev_config)262 inline esp_err_t open(uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t* dev_config) 263 { 264 return cdc_acm_host_open(vid, pid, interface_idx, dev_config, &this->cdc_hdl); 265 } 266 open_vendor_specific(uint16_t vid,uint16_t pid,uint8_t interface_idx,const cdc_acm_host_device_config_t * dev_config)267 inline esp_err_t open_vendor_specific(uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t* dev_config) 268 { 269 return cdc_acm_host_open_vendor_specific(vid, pid, interface_idx, dev_config, &this->cdc_hdl); 270 } 271 close()272 inline void close() 273 { 274 cdc_acm_host_close(this->cdc_hdl); 275 this->cdc_hdl = NULL; 276 } 277 line_coding_get(cdc_acm_line_coding_t * line_coding)278 inline esp_err_t line_coding_get(cdc_acm_line_coding_t *line_coding) 279 { 280 return cdc_acm_host_line_coding_get(this->cdc_hdl, line_coding); 281 } 282 line_coding_set(cdc_acm_line_coding_t * line_coding)283 inline esp_err_t line_coding_set(cdc_acm_line_coding_t *line_coding) 284 { 285 return cdc_acm_host_line_coding_set(this->cdc_hdl, line_coding); 286 } 287 set_control_line_state(bool dtr,bool rts)288 inline esp_err_t set_control_line_state(bool dtr, bool rts) 289 { 290 return cdc_acm_host_set_control_line_state(this->cdc_hdl, dtr, rts); 291 } 292 send_break(uint16_t duration_ms)293 inline esp_err_t send_break(uint16_t duration_ms) 294 { 295 return cdc_acm_host_send_break(this->cdc_hdl, duration_ms); 296 } 297 298 private: 299 CdcAcmDevice(const CdcAcmDevice &Copy); 300 CdcAcmDevice &operator= (const CdcAcmDevice &Copy); 301 bool operator== (const CdcAcmDevice ¶m) const; 302 bool operator!= (const CdcAcmDevice ¶m) const; 303 cdc_acm_dev_hdl_t cdc_hdl; 304 }; 305 #endif 306