Prechádzať zdrojové kódy

usb_host: Extend VCP example with more devices

Closes https://github.com/espressif/esp-idf/issues/9652
Closes https://github.com/espressif/esp-idf/issues/8951
Tomas Rezucha 3 rokov pred
rodič
commit
abdf7430e0

+ 8 - 6
examples/peripherals/usb/host/cdc/cdc_acm_vcp/README.md

@@ -5,20 +5,22 @@
 
 (See the README.md file in the upper level 'examples' directory for more information about examples.)
 
-This example shows how to extend CDC-ACM driver for Virtual Communication Port devices,
-such as CP210x or FTDI FT23x devices.
+This example shows how to extend CDC-ACM driver for Virtual Communication Port (VCP) devices,
+such as CP210x, FTDI FT23x or CP34x devices.
+
+The drivers are fetched from [IDF Component Registry](https://components.espressif.com/) together with VCP service that automatically loads correct driver for plugged-in device.
 
 ## How to use example
 
-1. Pick your USB-to-UART device by executing `idf.py menuconfig` and navigating to `Example Configuration -> USB-to-UART device type`
-2. Change baudrate and other line coding parameters in `cdc_acm_vcp.cpp` to match your needs
-3. Now you can use the CDC-ACM to API to control the device and send data. Data are received in `handle_rx` callback
+1. Connect your USB<->UART converter to ESP32-S2/S3, the device will be automatically enumerated and correct driver will be picked
+2. Change baudrate and other line coding parameters in [cdc_acm_vcp_example_main.cpp](main/cdc_acm_vcp_example_main.cpp) to match your needs
+3. Now you can use the usual CDC-ACM API to control the device and send data. Data are received in `handle_rx` callback
 4. Try disconnecting and then reconnecting of the USB device to experiment with USB hotplugging
 
 ### Hardware Required
 
 * ESP board with USB-OTG supported
-* Silicon Labs CP210x or FTDI FT23x USB to UART converter
+* Silicon Labs CP210x, FTDI FT23x or CP34x USB to UART converter
 
 Connect USB_D+, USB_D-, GND and +5V signals of your ESP chip to matching signals on USB to UART converter.
 

+ 4 - 3
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/CMakeLists.txt

@@ -1,3 +1,4 @@
-idf_component_register(SRCS "cdc_acm_vcp.cpp" "cp210x_usb.cpp" "ftdi_usb.cpp"
-                    INCLUDE_DIRS ".")
-target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
+idf_component_register(
+    SRCS "cdc_acm_vcp_example_main.cpp"
+    INCLUDE_DIRS "."
+    )

+ 0 - 15
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/Kconfig.projbuild

@@ -1,15 +0,0 @@
-menu "Example Configuration"
-
-    choice
-        prompt "USB-to-UART device type"
-        default EXAMPLE_USE_CP210X
-        help
-            Type of UART converter to use in this example.
-
-        config EXAMPLE_USE_FTDI
-            bool "FT232"
-        config EXAMPLE_USE_CP210X
-            bool "CP2012"
-    endchoice
-
-endmenu

+ 59 - 29
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cdc_acm_vcp.cpp → examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cdc_acm_vcp_example_main.cpp

@@ -6,15 +6,19 @@
 
 #include <stdio.h>
 #include <string.h>
-#include "sdkconfig.h"
-#include "cp210x_usb.hpp"
-#include "ftdi_usb.hpp"
-#include "usb/usb_host.h"
+
 #include "esp_log.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 
+#include "usb/cdc_acm_host.h"
+#include "usb/vcp_ch34x.hpp"
+#include "usb/vcp_cp210x.hpp"
+#include "usb/vcp_ftdi.hpp"
+#include "usb/vcp.hpp"
+#include "usb/usb_host.h"
+
 using namespace esp_usb;
 
 // Change these values to match your needs
@@ -23,16 +27,26 @@ using namespace esp_usb;
 #define EXAMPLE_PARITY       (0)      // 0: None, 1: Odd, 2: Even, 3: Mark, 4: Space
 #define EXAMPLE_DATA_BITS    (8)
 
-static const char *TAG = "VCP example";
-
-static SemaphoreHandle_t device_disconnected_sem;
+namespace {
+const char *TAG = "VCP example";
+SemaphoreHandle_t device_disconnected_sem;
 
-static void handle_rx(uint8_t *data, size_t data_len, void *arg)
+/**
+ * @brief Data received callback
+ *
+ * Just pass received data to stdout
+ */
+void handle_rx(uint8_t *data, size_t data_len, void *arg)
 {
     printf("%.*s", data_len, data);
 }
 
-static void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx)
+/**
+ * @brief Device event callback
+ *
+ * Apart from handling device disconnection it doesn't do anything useful
+ */
+void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx)
 {
     switch (event->type) {
         case CDC_ACM_HOST_ERROR:
@@ -43,13 +57,18 @@ static void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_
             xSemaphoreGive(device_disconnected_sem);
             break;
         case CDC_ACM_HOST_SERIAL_STATE:
-            ESP_LOGI(TAG, "serial state notif 0x%04X", event->data.serial_state.val);
+            ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val);
             break;
         case CDC_ACM_HOST_NETWORK_CONNECTION:
         default: break;
     }
 }
 
+/**
+ * @brief USB Host library handling task
+ *
+ * @param arg Unused
+ */
 void usb_lib_task(void *arg)
 {
     while (1) {
@@ -65,7 +84,13 @@ void usb_lib_task(void *arg)
         }
     }
 }
+}
 
+/**
+ * @brief Main application
+ *
+ * This function shows how you can use VCP drivers
+ */
 extern "C" void app_main(void)
 {
     device_disconnected_sem = xSemaphoreCreateBinary();
@@ -80,37 +105,36 @@ extern "C" void app_main(void)
     ESP_ERROR_CHECK(usb_host_install(&host_config));
 
     // Create a task that will handle USB library events
-    xTaskCreate(usb_lib_task, "usb_lib", 4096, NULL, 10, NULL);
+    BaseType_t task_created = xTaskCreate(usb_lib_task, "usb_lib", 4096, NULL, 10, NULL);
+    assert(task_created == pdTRUE);
 
     ESP_LOGI(TAG, "Installing CDC-ACM driver");
     ESP_ERROR_CHECK(cdc_acm_host_install(NULL));
 
+    // Register VCP drivers to VCP service.
+    VCP::register_driver<FT23x>();
+    VCP::register_driver<CP210x>();
+    VCP::register_driver<CH34x>();
+
+    // Do everything else in a loop, so we can demonstrate USB device reconnections
     while (true) {
         const cdc_acm_host_device_config_t dev_config = {
-            .connection_timeout_ms = 10000,
+            .connection_timeout_ms = 5000, // 5 seconds, enough time to plug the device in or experiment with timeout
             .out_buffer_size = 64,
             .event_cb = handle_event,
             .data_cb = handle_rx,
             .user_arg = NULL,
         };
 
-#if defined(CONFIG_EXAMPLE_USE_FTDI)
-        FT23x *vcp;
-        try {
-            ESP_LOGI(TAG, "Opening FT232 UART device");
-            vcp = FT23x::open_ftdi(FTDI_FT232_PID, &dev_config);
-        }
-#else
-        CP210x *vcp;
-        try {
-            ESP_LOGI(TAG, "Opening CP210X device");
-            vcp = CP210x::open_cp210x(CP210X_PID, &dev_config);
-        }
-#endif
-        catch (esp_err_t err) {
-            ESP_LOGE(TAG, "The required device was not opened.\nExiting...");
-            return;
+        // You don't need to know the device's VID and PID. Just plug in any device and the VCP service will pick correct (already registered) driver for the device
+        ESP_LOGI(TAG, "Opening any VCP device...");
+        auto vcp = std::unique_ptr<CdcAcmDevice>(VCP::open(&dev_config));
+
+        if (vcp == nullptr) {
+            ESP_LOGI(TAG, "Failed to open VCP device");
+            continue;
         }
+        vTaskDelay(10);
 
         ESP_LOGI(TAG, "Setting up line coding");
         cdc_acm_line_coding_t line_coding = {
@@ -129,8 +153,14 @@ extern "C" void app_main(void)
         ESP_ERROR_CHECK(vcp->tx_blocking((uint8_t *)"Test string", 12));
         */
 
+        // Send some dummy data
+        ESP_LOGI(TAG, "Sending data through CdcAcmDevice");
+        uint8_t data[] = "test_string";
+        ESP_ERROR_CHECK(vcp->tx_blocking(data, sizeof(data)));
+        ESP_ERROR_CHECK(vcp->set_control_line_state(true, true));
+
         // We are done. Wait for device disconnection and start over
+        ESP_LOGI(TAG, "Done. You can reconnect the VCP device to run again.");
         xSemaphoreTake(device_disconnected_sem, portMAX_DELAY);
-        delete vcp;
     }
 }

+ 0 - 82
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cp210x_usb.cpp

@@ -1,82 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#include "cp210x_usb.hpp"
-#include "usb/usb_types_ch9.h"
-#include "esp_log.h"
-#include "esp_check.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-
-#define SILICON_LABS_VID (0x10C4)
-#define CP210X_READ_REQ  (USB_BM_REQUEST_TYPE_TYPE_VENDOR | USB_BM_REQUEST_TYPE_RECIP_INTERFACE | USB_BM_REQUEST_TYPE_DIR_IN)
-#define CP210X_WRITE_REQ (USB_BM_REQUEST_TYPE_TYPE_VENDOR | USB_BM_REQUEST_TYPE_RECIP_INTERFACE | USB_BM_REQUEST_TYPE_DIR_OUT)
-
-namespace esp_usb {
-CP210x *CP210x::open_cp210x(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx)
-{
-    return new CP210x(pid, dev_config, interface_idx);
-}
-
-CP210x::CP210x(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx)
-    : intf(interface_idx)
-{
-    esp_err_t err;
-    err = this->open_vendor_specific(SILICON_LABS_VID, pid, this->intf, dev_config);
-    if (err != ESP_OK) {
-        throw(err);
-    }
-
-    // CP210X interfaces must be explicitly enabled
-    err = this->send_custom_request(CP210X_WRITE_REQ, CP210X_CMD_IFC_ENABLE, 1, this->intf, 0, NULL);
-    if (err != ESP_OK) {
-        throw(err);
-    }
-};
-
-esp_err_t CP210x::line_coding_get(cdc_acm_line_coding_t *line_coding)
-{
-    assert(line_coding);
-
-    ESP_RETURN_ON_ERROR(this->send_custom_request(CP210X_READ_REQ, CP210X_CMD_GET_BAUDRATE, 0, this->intf, sizeof(line_coding->dwDTERate), (uint8_t *)&line_coding->dwDTERate), "CP210X",);
-
-    uint8_t temp_data[2];
-    ESP_RETURN_ON_ERROR(this->send_custom_request(CP210X_READ_REQ, CP210X_CMD_GET_LINE_CTL, 0, this->intf, 2, temp_data), "CP210X",);
-    line_coding->bCharFormat = temp_data[0] & 0x0F;
-    line_coding->bParityType = (temp_data[0] & 0xF0) >> 4;
-    line_coding->bDataBits   = temp_data[1];
-
-    return ESP_OK;
-}
-
-esp_err_t CP210x::line_coding_set(cdc_acm_line_coding_t *line_coding)
-{
-    assert(line_coding);
-
-    if (line_coding->dwDTERate != 0) {
-        ESP_RETURN_ON_ERROR(this->send_custom_request(CP210X_WRITE_REQ, CP210X_CMD_SET_BAUDRATE, 0, this->intf, sizeof(line_coding->dwDTERate), (uint8_t *)&line_coding->dwDTERate), "CP210X",);
-    }
-
-    if (line_coding->bDataBits != 0) {
-        const uint16_t wValue = line_coding->bCharFormat | (line_coding->bParityType << 4) | (line_coding->bDataBits << 8);
-        return this->send_custom_request(CP210X_WRITE_REQ, CP210X_CMD_SET_LINE_CTL, wValue, this->intf, 0, NULL);
-    }
-    return ESP_OK;
-}
-
-esp_err_t CP210x::set_control_line_state(bool dtr, bool rts)
-{
-    const uint16_t wValue = (uint16_t)dtr | ((uint16_t)rts << 1) | 0x0300;
-    return this->send_custom_request(CP210X_WRITE_REQ, CP210X_CMD_SET_MHS, wValue, this->intf, 0, NULL);
-}
-
-esp_err_t CP210x::send_break(uint16_t duration_ms)
-{
-    ESP_RETURN_ON_ERROR(this->send_custom_request(CP210X_WRITE_REQ, CP210X_CMD_SET_BREAK, 1, this->intf, 0, NULL), "CP210x",);
-    vTaskDelay(pdMS_TO_TICKS(duration_ms));
-    return this->send_custom_request(CP210X_WRITE_REQ, CP210X_CMD_SET_BREAK, 0, this->intf, 0, NULL);
-}
-}

+ 0 - 114
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/cp210x_usb.hpp

@@ -1,114 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#pragma once
-
-#include "usb/cdc_acm_host.h"
-
-#define CP210X_PID       (0xEA60) // Single i.e. CP2101 - CP2104
-#define CP2105_PID       (0xEA70) // Dual
-#define CP2108_PID       (0xEA71) // Quad
-
-// @see AN571: CP210x Virtual COM Port Interface, chapter 5
-#define CP210X_CMD_IFC_ENABLE      (0x00) // Enable or disable the interface
-#define CP210X_CMD_SET_BAUDDIV     (0x01) // Set the baud rate divisor
-#define CP210X_CMD_GET_BAUDDIV     (0x02) // Get the baud rate divisor
-#define CP210X_CMD_SET_LINE_CTL    (0x03) // Set the line control
-#define CP210X_CMD_GET_LINE_CTL    (0x04) // Get the line control
-#define CP210X_CMD_SET_BREAK       (0x05) // Set a BREAK
-#define CP210X_CMD_IMM_CHAR        (0x06) // Send character out of order
-#define CP210X_CMD_SET_MHS         (0x07) // Set modem handshaking
-#define CP210X_CMD_GET_MDMSTS      (0x08) // Get modem status
-#define CP210X_CMD_SET_XON         (0x09) // Emulate XON
-#define CP210X_CMD_SET_XOFF        (0x0A) // Emulate XOFF
-#define CP210X_CMD_SET_EVENTMASK   (0x0B) // Set the event mask
-#define CP210X_CMD_GET_EVENTMASK   (0x0C) // Get the event mask
-#define CP210X_CMD_GET_EVENTSTATE  (0x16) // Get the event state
-#define CP210X_CMD_SET_RECEIVE     (0x17) // Set receiver max timeout
-#define CP210X_CMD_GET_RECEIVE     (0x18) // Get receiver max timeout
-#define CP210X_CMD_SET_CHAR        (0x0D) // Set special character individually
-#define CP210X_CMD_GET_CHARS       (0x0E) // Get special characters
-#define CP210X_CMD_GET_PROPS       (0x0F) // Get properties
-#define CP210X_CMD_GET_COMM_STATUS (0x10) // Get the serial status
-#define CP210X_CMD_RESET           (0x11) // Reset
-#define CP210X_CMD_PURGE           (0x12) // Purge
-#define CP210X_CMD_SET_FLOW        (0x13) // Set flow control
-#define CP210X_CMD_GET_FLOW        (0x14) // Get flow control
-#define CP210X_CMD_EMBED_EVENTS    (0x15) // Control embedding of events in the data stream
-#define CP210X_CMD_GET_BAUDRATE    (0x1D) // Get the baud rate
-#define CP210X_CMD_SET_BAUDRATE    (0x1E) // Set the baud rate
-#define CP210X_CMD_SET_CHARS       (0x19) // Set special characters
-#define CP210X_CMD_VENDOR_SPECIFIC (0xFF) // Read/write latch values
-
-namespace esp_usb {
-class CP210x : public CdcAcmDevice {
-public:
-    /**
-     * @brief Factory method for this CP210x driver
-     *
-     * @note USB Host library and CDC-ACM driver must be already installed
-     *
-     * @param[in] pid            PID eg. CP210X_PID
-     * @param[in] dev_config     CDC device configuration
-     * @param[in] interface_idx  Interface number
-     * @return CP210x            Pointer to created and opened CP210x device
-     */
-    static CP210x *open_cp210x(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx = 0);
-
-    /**
-     * @brief Get Line Coding method
-     *
-     * @see AN571: CP210x Virtual COM Port Interface chapters 5.6 and 5.8
-     * @note Overrides default implementation in CDC-ACM driver
-     * @param[out] line_coding Line Coding structure
-     * @return esp_err_t
-     */
-    esp_err_t line_coding_get(cdc_acm_line_coding_t *line_coding);
-
-    /**
-     * @brief Set Line Coding method
-     *
-     * @see AN571: CP210x Virtual COM Port Interface chapters 5.5 and 5.7
-     * @note Overrides default implementation in CDC-ACM driver
-     * @param[in] line_coding Line Coding structure
-     * @return esp_err_t
-     */
-    esp_err_t line_coding_set(cdc_acm_line_coding_t *line_coding);
-
-    /**
-     * @brief Set Control Line State method
-     *
-     * @see AN571: CP210x Virtual COM Port Interface chapter 5.9
-     * @note Overrides default implementation in CDC-ACM driver
-     * @note Both signals are active low
-     * @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 set_control_line_state(bool dtr, bool rts);
-
-    /**
-     * @brief Send Break method
-     *
-     * @see AN571: CP210x Virtual COM Port Interface chapter 5.20
-     * @note Overrides default implementation in CDC-ACM driver
-     * @param[in] duration_ms Duration of the break condition in [ms]
-     * @return esp_err_t
-     */
-    esp_err_t send_break(uint16_t duration_ms);
-
-private:
-    const uint8_t intf;
-
-    // Constructors are private, use factory method to create this object
-    CP210x();
-    CP210x(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx = 0);
-
-    // Make open functions from CdcAcmDevice class private
-    using CdcAcmDevice::open;
-    using CdcAcmDevice::open_vendor_specific;
-};
-} // namespace esp_usb

+ 0 - 175
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/ftdi_usb.cpp

@@ -1,175 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#include <string.h>
-#include "ftdi_usb.hpp"
-#include "usb/usb_types_ch9.h"
-#include "esp_log.h"
-#include "esp_check.h"
-
-#define FTDI_VID       (0x0403)
-#define FTDI_READ_REQ  (USB_BM_REQUEST_TYPE_TYPE_VENDOR | USB_BM_REQUEST_TYPE_DIR_IN)
-#define FTDI_WRITE_REQ (USB_BM_REQUEST_TYPE_TYPE_VENDOR | USB_BM_REQUEST_TYPE_DIR_OUT)
-
-namespace esp_usb {
-FT23x *FT23x::open_ftdi(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx)
-{
-    return new FT23x(pid, dev_config, interface_idx);
-}
-
-FT23x::FT23x(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx)
-    : intf(interface_idx), user_data_cb(dev_config->data_cb), user_event_cb(dev_config->event_cb),
-    user_arg(dev_config->user_arg), uart_state(0)
-{
-    cdc_acm_host_device_config_t ftdi_config;
-    memcpy(&ftdi_config, dev_config, sizeof(cdc_acm_host_device_config_t));
-    // FT23x reports modem status in first two bytes of RX data
-    // so here we override the RX handler with our own
-
-    if (dev_config->data_cb) {
-        ftdi_config.data_cb = ftdi_rx;
-        ftdi_config.user_arg = this;
-    }
-
-    if (dev_config->event_cb) {
-        ftdi_config.event_cb = ftdi_event;
-        ftdi_config.user_arg = this;
-    }
-
-    esp_err_t err;
-    err = this->open_vendor_specific(FTDI_VID, pid, this->intf, &ftdi_config);
-    if (err != ESP_OK) {
-        throw(err);
-    }
-
-    // FT23x interface must be first reset and configured (115200 8N1)
-    err = this->send_custom_request(FTDI_WRITE_REQ, FTDI_CMD_RESET, 0, this->intf + 1, 0, NULL);
-    if (err != ESP_OK) {
-        throw(err);
-    }
-
-    cdc_acm_line_coding_t line_coding = {
-        .dwDTERate = 115200,
-        .bCharFormat = 0,
-        .bParityType = 0,
-        .bDataBits = 8,
-    };
-    err = this->line_coding_set(&line_coding);
-    if (err != ESP_OK) {
-        throw(err);
-    }
-};
-
-esp_err_t FT23x::line_coding_set(cdc_acm_line_coding_t *line_coding)
-{
-    assert(line_coding);
-
-    if (line_coding->dwDTERate != 0) {
-        uint16_t wIndex, wValue;
-        calculate_baudrate(line_coding->dwDTERate, &wValue, &wIndex);
-        ESP_RETURN_ON_ERROR(this->send_custom_request(FTDI_WRITE_REQ, FTDI_CMD_SET_BAUDRATE, wValue, wIndex, 0, NULL), "FT23x",);
-    }
-
-    if (line_coding->bDataBits != 0) {
-        const uint16_t wValue = (line_coding->bDataBits) | (line_coding->bParityType << 8) | (line_coding->bCharFormat << 11);
-        return this->send_custom_request(FTDI_WRITE_REQ, FTDI_CMD_SET_LINE_CTL, wValue, this->intf, 0, NULL);
-    }
-    return ESP_OK;
-}
-
-esp_err_t FT23x::set_control_line_state(bool dtr, bool rts)
-{
-    ESP_RETURN_ON_ERROR(this->send_custom_request(FTDI_WRITE_REQ, FTDI_CMD_SET_MHS, dtr ? 0x11 : 0x10, this->intf, 0, NULL), "FT23x",); // DTR
-    return this->send_custom_request(FTDI_WRITE_REQ, FTDI_CMD_SET_MHS, rts ? 0x21 : 0x20, this->intf, 0, NULL); // RTS
-}
-
-void FT23x::ftdi_rx(uint8_t* data, size_t data_len, void *user_arg)
-{
-    FT23x *this_ftdi = (FT23x *)user_arg;
-
-    // Dispatch serial state if it has changed
-    if (this_ftdi->user_event_cb) {
-        cdc_acm_uart_state_t new_state;
-        new_state.val = 0;
-        new_state.bRxCarrier =  data[0] & 0x80; // DCD
-        new_state.bTxCarrier =  data[0] & 0x20; // DSR
-        new_state.bBreak =      data[1] & 0x10;
-        new_state.bRingSignal = data[0] & 0x40;
-        new_state.bFraming =    data[1] & 0x08;
-        new_state.bParity =     data[1] & 0x04;
-        new_state.bOverRun =    data[1] & 0x02;
-
-        if (this_ftdi->uart_state != new_state.val) {
-            cdc_acm_host_dev_event_data_t serial_event;
-            serial_event.type = CDC_ACM_HOST_SERIAL_STATE;
-            serial_event.data.serial_state = new_state;
-            this_ftdi->user_event_cb(&serial_event, this_ftdi->user_arg);
-            this_ftdi->uart_state = new_state.val;
-        }
-    }
-
-    // Dispatch data if any
-    if (data_len > 2) {
-        this_ftdi->user_data_cb(&data[2], data_len - 2, this_ftdi->user_arg);
-    }
-}
-
-void FT23x::ftdi_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx)
-{
-    FT23x *this_ftdi = (FT23x *)user_ctx;
-    this_ftdi->user_event_cb(event, this_ftdi->user_arg);
-}
-
-int FT23x::calculate_baudrate(uint32_t baudrate, uint16_t *wValue, uint16_t *wIndex)
-{
-    #define FTDI_BASE_CLK (3000000)
-
-    int baudrate_real;
-    if (baudrate > 2000000) {
-        // set to 3000000
-        *wValue = 0;
-        *wIndex = 0;
-        baudrate_real = 3000000;
-    } else if (baudrate >= 1000000) {
-        // set to 1000000
-        *wValue = 1;
-        *wIndex = 0;
-        baudrate_real = 1000000;
-    } else {
-        const float ftdi_fractal[] = {0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1};
-        const uint8_t ftdi_fractal_bits[] = {0, 0x03, 0x02, 0x04, 0x01, 0x05, 0x06, 0x07};
-        uint16_t divider_n = FTDI_BASE_CLK / baudrate; // integer value
-        int ftdi_fractal_idx = 0;
-        float divider = FTDI_BASE_CLK / (float)baudrate; // float value
-        float divider_fractal = divider - (float)divider_n;
-
-        // Find closest bigger FT23x fractal divider
-        for (ftdi_fractal_idx = 0; ftdi_fractal[ftdi_fractal_idx] <= divider_fractal; ftdi_fractal_idx++) {};
-
-        // Calculate baudrate errors for two closest fractal divisors
-        int diff1 = baudrate - (int)(FTDI_BASE_CLK / (divider_n + ftdi_fractal[ftdi_fractal_idx]));     // Greater than required baudrate
-        int diff2 = (int)(FTDI_BASE_CLK / (divider_n + ftdi_fractal[ftdi_fractal_idx - 1])) - baudrate; // Lesser than required baudrate
-
-        // Chose divider and fractal divider with smallest error
-        if (diff2 < diff1) {
-            ftdi_fractal_idx--;
-        } else {
-            if (ftdi_fractal_idx == 8) {
-                ftdi_fractal_idx = 0;
-                divider_n++;
-            }
-        }
-
-        baudrate_real = FTDI_BASE_CLK / (float)((float)divider_n + ftdi_fractal[ftdi_fractal_idx]);
-        *wValue = ((0x3FFFF) & divider_n) | (ftdi_fractal_bits[ftdi_fractal_idx] << 14);
-        *wIndex = ftdi_fractal_bits[ftdi_fractal_idx] >> 2;
-    }
-    ESP_LOGD("FT23x", "wValue: 0x%04X wIndex: 0x%04X", *wValue, *wIndex);
-    ESP_LOGI("FT23x", "Baudrate required: %d, set: %d", baudrate, baudrate_real);
-
-    return baudrate_real;
-}
-} // esp_usb

+ 0 - 126
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/ftdi_usb.hpp

@@ -1,126 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#pragma once
-
-#include "usb/cdc_acm_host.h"
-
-#define FTDI_FT232_PID       (0x6001)
-#define FTDI_FT231_PID       (0x6015)
-
-#define FTDI_CMD_RESET        (0x00)
-#define FTDI_CMD_SET_FLOW     (0x01)
-#define FTDI_CMD_SET_MHS      (0x02) // Modem hanshaking
-#define FTDI_CMD_SET_BAUDRATE (0x03)
-#define FTDI_CMD_SET_LINE_CTL (0x04)
-#define FTDI_CMD_GET_MDMSTS   (0x05) // Modem status
-
-namespace esp_usb {
-class FT23x : public CdcAcmDevice {
-public:
-    /**
-     * @brief Factory method for this FTDI driver
-     *
-     * @note USB Host library and CDC-ACM driver must be already installed
-     *
-     * @param[in] pid            PID eg. FTDI_FT232_PID
-     * @param[in] dev_config     CDC device configuration
-     * @param[in] interface_idx  Interface number
-     * @return FT23x             Pointer to created and opened FTDI device
-     */
-    static FT23x *open_ftdi(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx = 0);
-
-    /**
-     * @brief Set Line Coding method
-     *
-     * @note Overrides default implementation in CDC-ACM driver
-     * @param[in] line_coding Line Coding structure
-     * @return esp_err_t
-     */
-    esp_err_t line_coding_set(cdc_acm_line_coding_t *line_coding);
-
-    /**
-     * @brief Set Control Line State method
-     *
-     * @note Overrides default implementation in CDC-ACM driver
-     * @note Both signals are active low
-     * @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 set_control_line_state(bool dtr, bool rts);
-
-private:
-    /**
-     * @brief FT23x's RX data handler
-     *
-     * First two bytes are status bytes, the RX data start at data[2].
-     * Coding of status bytes:
-     * Byte 0:
-     *      Bit 0: Full Speed packet
-     *      Bit 1: High Speed packet
-     *      Bit 4: CTS
-     *      Bit 5: DSR
-     *      Bit 6: RI
-     *      Bit 7: DCD
-     * Byte 1:
-     *      Bit 1: RX overflow
-     *      Bit 2: Parity error
-     *      Bit 3: Framing error
-     *      Bit 4: Break received
-     *      Bit 5: Transmitter holding register empty
-     *      Bit 6: Transmitter empty
-     *
-     * @todo When CTS is asserted, this driver should stop sending data.
-     *
-     * @param[in] data     Received data
-     * @param[in] data_len Received data length
-     * @param[in] user_arg Pointer to FT23x class
-     */
-    static void ftdi_rx(uint8_t* data, size_t data_len, void *user_arg);
-
-    // Just a wrapper to recover user's argument
-    static void ftdi_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx);
-
-    /**
-     * @brief Construct a new calculate baudrate object
-     *
-     * A Baud rate for the FT232R, FT2232 (UART mode) or FT232B is generated using the chips
-     * internal 48MHz clock. This is input to Baud rate generator circuitry where it is then divided by 16
-     * and fed into a prescaler as a 3MHz reference clock. This 3MHz reference clock is then divided
-     * down to provide the required Baud rate for the device's on chip UART. The value of the Baud rate
-     * divisor is an integer plus a sub-integer prescaler.
-     * Allowed values for the Baud rate divisor are:
-     * Divisor = n + 0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875; where n is an integer between 2 and
-     * 16384 (214).
-     *
-     * Note: Divisor = 1 and Divisor = 0 are special cases. A divisor of 0 will give 3 MBaud, and a divisor
-     * of 1 will give 2 MBaud. Sub-integer divisors between 0 and 2 are not allowed.
-     * Therefore the value of the divisor needed for a given Baud rate is found by dividing 3000000 by the
-     * required Baud rate.
-     *
-     * @see FTDI AN232B-05 Configuring FT232R, FT2232 and FT232B Baud Rates
-     * @param[in]  baudrate
-     * @param[out] wValue
-     * @param[out] wIndex
-     */
-    static int calculate_baudrate(uint32_t baudrate, uint16_t *wValue, uint16_t *wIndex);
-
-    // Constructors are private, use factory method open_ftdi() to create this object
-    FT23x();
-    FT23x(uint16_t pid, const cdc_acm_host_device_config_t *dev_config, uint8_t interface_idx = 0);
-
-    // Make open functions from CdcAcmDevice class private
-    using CdcAcmDevice::open;
-    using CdcAcmDevice::open_vendor_specific;
-
-    const uint8_t intf;
-    const cdc_acm_data_callback_t user_data_cb;
-    const cdc_acm_host_dev_callback_t user_event_cb;
-    void *user_arg;
-    uint16_t uart_state;
-};
-} // namespace esp_usb

+ 5 - 2
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/idf_component.yml

@@ -1,4 +1,7 @@
 ## IDF Component Manager Manifest File
 dependencies:
-  usb_host_cdc_acm: "1.*"
-  idf: ">=4.4"
+  usb_host_ch34x_vcp: "^1"
+  usb_host_cp210x_vcp: "^1"
+  usb_host_ftdi_vcp: "^1"
+  usb_host_vcp: "^1"
+  idf: ">=5.1.0"