342 lines
12 KiB
C++
342 lines
12 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include "usb/usb_host.h"
|
|
#include "usb_types_cdc.h"
|
|
#include "esp_err.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct cdc_dev_s *cdc_acm_dev_hdl_t;
|
|
|
|
/**
|
|
* @brief Line Coding structure
|
|
* @see Table 17, USB CDC-PSTN specification rev. 1.2
|
|
*/
|
|
typedef struct {
|
|
uint32_t dwDTERate; // in bits per second
|
|
uint8_t bCharFormat; // 0: 1 stopbit, 1: 1.5 stopbits, 2: 2 stopbits
|
|
uint8_t bParityType; // 0: None, 1: Odd, 2: Even, 3: Mark, 4: Space
|
|
uint8_t bDataBits; // 5, 6, 7, 8 or 16
|
|
} __attribute__((packed)) cdc_acm_line_coding_t;
|
|
|
|
/**
|
|
* @brief UART State Bitmap
|
|
* @see Table 31, USB CDC-PSTN specification rev. 1.2
|
|
*/
|
|
typedef union {
|
|
struct {
|
|
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.
|
|
uint16_t bTxCarrier : 1; // State of transmission carrier. This signal corresponds to V.24 signal 106 and RS-232 signal DSR.
|
|
uint16_t bBreak : 1; // State of break detection mechanism of the device.
|
|
uint16_t bRingSignal : 1; // State of ring signal detection of the device.
|
|
uint16_t bFraming : 1; // A framing error has occurred.
|
|
uint16_t bParity : 1; // A parity error has occurred.
|
|
uint16_t bOverRun : 1; // Received data has been discarded due to overrun in the device.
|
|
uint16_t reserved : 9;
|
|
};
|
|
uint16_t val;
|
|
} cdc_acm_uart_state_t;
|
|
|
|
/**
|
|
* @brief CDC-ACM Device Event types to upper layer
|
|
*
|
|
*/
|
|
typedef enum {
|
|
CDC_ACM_HOST_ERROR,
|
|
CDC_ACM_HOST_SERIAL_STATE,
|
|
CDC_ACM_HOST_NETWORK_CONNECTION,
|
|
CDC_ACM_HOST_DEVICE_DISCONNECTED
|
|
} cdc_acm_host_dev_event_t;
|
|
|
|
/**
|
|
* @brief CDC-ACM Device Event data structure
|
|
*
|
|
*/
|
|
typedef struct {
|
|
cdc_acm_host_dev_event_t type;
|
|
union {
|
|
int error; //!< Error code from USB Host
|
|
cdc_acm_uart_state_t serial_state; //!< Serial (UART) state
|
|
bool network_connected; //!< Network connection event
|
|
cdc_acm_dev_hdl_t cdc_hdl; //!< Disconnection event
|
|
} data;
|
|
} cdc_acm_host_dev_event_data_t;
|
|
|
|
/**
|
|
* @brief New USB device callback
|
|
*
|
|
* Provides already opened usb_dev, that will be closed after this callback returns.
|
|
* This is useful for peeking device's descriptors, e.g. peeking VID/PID and loading proper driver.
|
|
*
|
|
* @attention This callback is called from USB Host context, so the CDC device can't be opened here.
|
|
*/
|
|
typedef void (*cdc_acm_new_dev_callback_t)(usb_device_handle_t usb_dev);
|
|
|
|
/**
|
|
* @brief Data receive callback type
|
|
*/
|
|
typedef void (*cdc_acm_data_callback_t)(uint8_t *data, size_t data_len, void *user_arg);
|
|
|
|
/**
|
|
* @brief Device event callback type
|
|
* @see cdc_acm_host_dev_event_data_t
|
|
*/
|
|
typedef void (*cdc_acm_host_dev_callback_t)(const cdc_acm_host_dev_event_data_t *event, void *user_ctx);
|
|
|
|
/**
|
|
* @brief Configuration structure of USB Host CDC-ACM driver
|
|
*
|
|
*/
|
|
typedef struct {
|
|
size_t driver_task_stack_size; /**< Stack size of the driver's task */
|
|
unsigned driver_task_priority; /**< Priority of the driver's task */
|
|
int xCoreID; /**< Core affinity of the driver's task */
|
|
cdc_acm_new_dev_callback_t new_dev_cb; /**< New USB device connected callback. Can be NULL. */
|
|
} cdc_acm_host_driver_config_t;
|
|
|
|
/**
|
|
* @brief Configuration structure of CDC-ACM device
|
|
*
|
|
*/
|
|
typedef struct {
|
|
uint32_t connection_timeout_ms; /**< Timeout for USB device connection in [ms] */
|
|
size_t out_buffer_size; /**< Maximum size of USB bulk out transfer, set to 0 for read-only devices */
|
|
cdc_acm_host_dev_callback_t event_cb; /**< Device's event callback function. Can be NULL */
|
|
cdc_acm_data_callback_t data_cb; /**< Device's data RX callback function. Can be NULL for write-only devices */
|
|
void *user_arg; /**< User's argument that will be passed to the callbacks */
|
|
} cdc_acm_host_device_config_t;
|
|
|
|
/**
|
|
* @brief Install CDC-ACM driver
|
|
*
|
|
* - USB Host Library must already be installed before calling this function (via usb_host_install())
|
|
* - This function should be called before calling any other CDC driver functions
|
|
*
|
|
* @param[in] driver_config Driver configuration structure. If set to NULL, a default configuration will be used.
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config);
|
|
|
|
/**
|
|
* @brief Uninstall CDC-ACM driver
|
|
*
|
|
* - Users must ensure that all CDC devices must be closed via cdc_acm_host_close() before calling this function
|
|
*
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_uninstall(void);
|
|
|
|
/**
|
|
* @brief Open CDC-ACM compliant device
|
|
*
|
|
* CDC-ACM compliant device must contain either an Interface Association Descriptor or CDC-Union descriptor,
|
|
* which are used for the driver's configuration.
|
|
*
|
|
* @param[in] vid Device's Vendor ID
|
|
* @param[in] pid Device's Product ID
|
|
* @param[in] interface_idx Index of device's interface used for CDC-ACM communication
|
|
* @param[in] dev_config Configuration structure of the device
|
|
* @param[out] cdc_hdl_ret CDC device handle
|
|
* @return esp_err_t
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* @brief Open CDC-ACM non-compliant device
|
|
*
|
|
* CDC-ACM non-compliant device acts as CDC-ACM device but doesn't support all its features.
|
|
* User must provide the interface index that will be used (zero for non-composite devices).
|
|
*
|
|
* @param[in] vid Device's Vendor ID
|
|
* @param[in] pid Device's Product ID
|
|
* @param[in] interface_idx Index of device's interface used for CDC-ACM like communication
|
|
* @param[in] dev_config Configuration structure of the device
|
|
* @param[out] cdc_hdl_ret CDC device handle
|
|
* @return esp_err_t
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* @brief Close CDC device and release its resources
|
|
*
|
|
* @note All in-flight transfers will be prematurely canceled.
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_close(cdc_acm_dev_hdl_t cdc_hdl);
|
|
|
|
/**
|
|
* @brief Transmit data - blocking mode
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @param[in] data Data to be sent
|
|
* @param[in] data_len Data length
|
|
* @param[in] timeout_ms Timeout in [ms]
|
|
* @return esp_err_t
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* @brief SetLineCoding function
|
|
*
|
|
* @see Chapter 6.3.10, USB CDC-PSTN specification rev. 1.2
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @param[in] line_coding Line Coding structure
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_line_coding_set(cdc_acm_dev_hdl_t cdc_hdl, const cdc_acm_line_coding_t *line_coding);
|
|
|
|
/**
|
|
* @brief GetLineCoding function
|
|
*
|
|
* @see Chapter 6.3.11, USB CDC-PSTN specification rev. 1.2
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @param[out] line_coding Line Coding structure to be filled
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_line_coding_get(cdc_acm_dev_hdl_t cdc_hdl, cdc_acm_line_coding_t *line_coding);
|
|
|
|
/**
|
|
* @brief SetControlLineState function
|
|
*
|
|
* @see Chapter 6.3.12, USB CDC-PSTN specification rev. 1.2
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @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.
|
|
* @param[in] rts Carrier control for half duplex modems. This signal corresponds to V.24 signal 105 and RS-232 signal Request To Send.
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_set_control_line_state(cdc_acm_dev_hdl_t cdc_hdl, bool dtr, bool rts);
|
|
|
|
/**
|
|
* @brief SendBreak function
|
|
*
|
|
* This function will block until the duration_ms has passed.
|
|
*
|
|
* @see Chapter 6.3.13, USB CDC-PSTN specification rev. 1.2
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @param[in] duration_ms Duration of the Break signal in [ms]
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_send_break(cdc_acm_dev_hdl_t cdc_hdl, uint16_t duration_ms);
|
|
|
|
/**
|
|
* @brief Print device's descriptors
|
|
*
|
|
* Device and full Configuration descriptors are printed in human readable format to stdout.
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
*/
|
|
void cdc_acm_host_desc_print(cdc_acm_dev_hdl_t cdc_hdl);
|
|
|
|
/**
|
|
* @brief Get protocols defined in USB-CDC interface descriptors
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @param[out] comm Communication protocol
|
|
* @param[out] data Data protocol
|
|
* @return esp_err_t
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* @brief Send command to CTRL endpoint
|
|
*
|
|
* Sends Control transfer as described in USB specification chapter 9.
|
|
* This function can be used by device drivers that use custom/vendor specific commands.
|
|
* These commands can either extend or replace commands defined in USB CDC-PSTN specification rev. 1.2.
|
|
*
|
|
* @param cdc_hdl CDC handle obtained from cdc_acm_host_open()
|
|
* @param[in] bmRequestType Field of USB control request
|
|
* @param[in] bRequest Field of USB control request
|
|
* @param[in] wValue Field of USB control request
|
|
* @param[in] wIndex Field of USB control request
|
|
* @param[in] wLength Field of USB control request
|
|
* @param[inout] data Field of USB control request
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t cdc_acm_host_send_custom_request(cdc_acm_dev_hdl_t cdc_hdl, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t *data);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
class CdcAcmDevice {
|
|
public:
|
|
// Operators
|
|
CdcAcmDevice() : cdc_hdl(NULL) {};
|
|
virtual ~CdcAcmDevice()
|
|
{
|
|
// Close CDC-ACM device, if it wasn't explicitly closed
|
|
if (this->cdc_hdl != NULL) {
|
|
this->close();
|
|
}
|
|
}
|
|
|
|
inline esp_err_t tx_blocking(uint8_t *data, size_t len, uint32_t timeout_ms = 100)
|
|
{
|
|
return cdc_acm_host_data_tx_blocking(this->cdc_hdl, data, len, timeout_ms);
|
|
}
|
|
|
|
inline esp_err_t open(uint16_t vid, uint16_t pid, uint8_t interface_idx, const cdc_acm_host_device_config_t *dev_config)
|
|
{
|
|
return cdc_acm_host_open(vid, pid, interface_idx, dev_config, &this->cdc_hdl);
|
|
}
|
|
|
|
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)
|
|
{
|
|
return cdc_acm_host_open_vendor_specific(vid, pid, interface_idx, dev_config, &this->cdc_hdl);
|
|
}
|
|
|
|
inline esp_err_t close()
|
|
{
|
|
const esp_err_t err = cdc_acm_host_close(this->cdc_hdl);
|
|
if (err == ESP_OK) {
|
|
this->cdc_hdl = NULL;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
virtual inline esp_err_t line_coding_get(cdc_acm_line_coding_t *line_coding) const
|
|
{
|
|
return cdc_acm_host_line_coding_get(this->cdc_hdl, line_coding);
|
|
}
|
|
|
|
virtual inline esp_err_t line_coding_set(cdc_acm_line_coding_t *line_coding)
|
|
{
|
|
return cdc_acm_host_line_coding_set(this->cdc_hdl, line_coding);
|
|
}
|
|
|
|
virtual inline esp_err_t set_control_line_state(bool dtr, bool rts)
|
|
{
|
|
return cdc_acm_host_set_control_line_state(this->cdc_hdl, dtr, rts);
|
|
}
|
|
|
|
virtual inline esp_err_t send_break(uint16_t duration_ms)
|
|
{
|
|
return cdc_acm_host_send_break(this->cdc_hdl, duration_ms);
|
|
}
|
|
|
|
inline esp_err_t send_custom_request(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t *data)
|
|
{
|
|
return cdc_acm_host_send_custom_request(this->cdc_hdl, bmRequestType, bRequest, wValue, wIndex, wLength, data);
|
|
}
|
|
|
|
private:
|
|
CdcAcmDevice &operator= (const CdcAcmDevice &Copy);
|
|
bool operator== (const CdcAcmDevice ¶m) const;
|
|
bool operator!= (const CdcAcmDevice ¶m) const;
|
|
cdc_acm_dev_hdl_t cdc_hdl;
|
|
};
|
|
#endif
|