Explorar o código

Merge branch 'feature/usb_v5_qol' into 'master'

usb: USB IDF v5 update

Closes IDF-4690 and IDF-5767

See merge request espressif/esp-idf!19875
Tomas Rezucha %!s(int64=3) %!d(string=hai) anos
pai
achega
cf59a8a2bd
Modificáronse 46 ficheiros con 29 adicións e 4822 borrados
  1. 0 8
      .gitlab/ci/target-test.yml
  2. 0 4
      components/usb/CMakeLists.txt
  3. 3 3
      components/usb/hcd.c
  4. 0 1
      components/usb/test/CMakeLists.txt
  5. 4 4
      components/usb/test/common/test_usb_mock_classes.c
  6. 1 1
      components/usb/usbh.c
  7. 3 5
      docs/en/api-reference/peripherals/usb_host.rst
  8. 0 2
      docs/en/contribute/esp-idf-tests-with-pytest.rst
  9. 0 1
      examples/peripherals/usb/host/cdc/cdc_acm_bg96/CMakeLists.txt
  10. 2 0
      examples/peripherals/usb/host/cdc/cdc_acm_bg96/main/idf_component.yml
  11. 0 1
      examples/peripherals/usb/host/cdc/cdc_acm_host/CMakeLists.txt
  12. 4 0
      examples/peripherals/usb/host/cdc/cdc_acm_host/main/idf_component.yml
  13. 0 1
      examples/peripherals/usb/host/cdc/cdc_acm_vcp/CMakeLists.txt
  14. 4 0
      examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/idf_component.yml
  15. 0 18
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/CMakeLists.txt
  16. 0 46
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/README.md
  17. 0 1223
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/cdc_acm_host.c
  18. 0 343
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/include/usb/cdc_acm_host.h
  19. 0 206
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/include/usb/usb_types_cdc.h
  20. 0 3
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/CMakeLists.txt
  21. 0 447
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/test_cdc_acm_host.c
  22. 0 71
      examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/usb_device.c
  23. 0 9
      examples/peripherals/usb/host/msc/components/msc/CMakeLists.txt
  24. 0 32
      examples/peripherals/usb/host/msc/components/msc/README.md
  25. 0 169
      examples/peripherals/usb/host/msc/components/msc/include/msc_host.h
  26. 0 44
      examples/peripherals/usb/host/msc/components/msc/include/msc_host_vfs.h
  27. 0 39
      examples/peripherals/usb/host/msc/components/msc/private_include/diskio_usb.h
  28. 0 61
      examples/peripherals/usb/host/msc/components/msc/private_include/msc_common.h
  29. 0 56
      examples/peripherals/usb/host/msc/components/msc/private_include/msc_scsi_bot.h
  30. 0 118
      examples/peripherals/usb/host/msc/components/msc/src/diskio_usb.c
  31. 0 553
      examples/peripherals/usb/host/msc/components/msc/src/msc_host.c
  32. 0 124
      examples/peripherals/usb/host/msc/components/msc/src/msc_host_vfs.c
  33. 0 434
      examples/peripherals/usb/host/msc/components/msc/src/msc_scsi_bot.c
  34. 0 3
      examples/peripherals/usb/host/msc/components/msc/test/CMakeLists.txt
  35. 0 302
      examples/peripherals/usb/host/msc/components/msc/test/msc_device.c
  36. 0 19
      examples/peripherals/usb/host/msc/components/msc/test/test_common.h
  37. 0 325
      examples/peripherals/usb/host/msc/components/msc/test/test_msc.c
  38. 1 2
      examples/peripherals/usb/host/msc/main/CMakeLists.txt
  39. 4 0
      examples/peripherals/usb/host/msc/main/idf_component.yml
  40. 3 4
      examples/peripherals/usb/host/msc/main/msc_example_main.c
  41. 0 11
      tools/test_apps/peripherals/usb/CMakeLists.txt
  42. 0 26
      tools/test_apps/peripherals/usb/README.md
  43. 0 3
      tools/test_apps/peripherals/usb/main/CMakeLists.txt
  44. 0 44
      tools/test_apps/peripherals/usb/main/usb_test_main.c
  45. 0 40
      tools/test_apps/peripherals/usb/pytest_usb_host.py
  46. 0 16
      tools/test_apps/peripherals/usb/sdkconfig.defaults

+ 0 - 8
.gitlab/ci/target-test.yml

@@ -423,14 +423,6 @@ test_app_test_pytest_esp32c3_generic:
     - build_pytest_test_apps_esp32c3
   tags: [ esp32c3, generic ]
 
-test_app_test_pytest_esp32s2_usb_host:
-  extends:
-    - .pytest_test_apps_dir_template
-    - .rules:test:custom_test-esp32s2
-  needs:
-    - build_pytest_test_apps_esp32s2
-  tags: [ esp32s2, usb_host ]
-
 test_app_test_pytest_esp32s3_mspi_f8r8:
   extends:
     - .pytest_test_apps_dir_template

+ 0 - 4
components/usb/CMakeLists.txt

@@ -23,7 +23,3 @@ idf_component_register(SRCS ${srcs}
                        PRIV_INCLUDE_DIRS ${priv_include}
                        PRIV_REQUIRES ${priv_require}
                        )
-
-if(CONFIG_USB_OTG_SUPPORTED)
-    target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
-endif()

+ 3 - 3
components/usb/hcd.c

@@ -2342,7 +2342,7 @@ static inline void _buffer_parse_ctrl(dma_buffer_block_t *buffer)
     //Update URB status
     transfer->status = USB_TRANSFER_STATUS_COMPLETED;
     //Clear the descriptor list
-    memset(buffer->xfer_desc_list, XFER_LIST_LEN_CTRL, sizeof(usbh_ll_dma_qtd_t));
+    memset(buffer->xfer_desc_list, 0, XFER_LIST_LEN_CTRL * sizeof(usbh_ll_dma_qtd_t));
 }
 
 static inline void _buffer_parse_bulk(dma_buffer_block_t *buffer)
@@ -2358,7 +2358,7 @@ static inline void _buffer_parse_bulk(dma_buffer_block_t *buffer)
     //Update URB's status
     transfer->status = USB_TRANSFER_STATUS_COMPLETED;
     //Clear the descriptor list
-    memset(buffer->xfer_desc_list, XFER_LIST_LEN_BULK, sizeof(usbh_ll_dma_qtd_t));
+    memset(buffer->xfer_desc_list, 0, XFER_LIST_LEN_BULK * sizeof(usbh_ll_dma_qtd_t));
 }
 
 static inline void _buffer_parse_intr(dma_buffer_block_t *buffer, bool is_in, int mps)
@@ -2408,7 +2408,7 @@ static inline void _buffer_parse_intr(dma_buffer_block_t *buffer, bool is_in, in
     //Update URB's status
     transfer->status = USB_TRANSFER_STATUS_COMPLETED;
     //Clear the descriptor list
-    memset(buffer->xfer_desc_list, XFER_LIST_LEN_INTR, sizeof(usbh_ll_dma_qtd_t));
+    memset(buffer->xfer_desc_list, 0, XFER_LIST_LEN_INTR * sizeof(usbh_ll_dma_qtd_t));
 }
 
 static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in)

+ 0 - 1
components/usb/test/CMakeLists.txt

@@ -10,4 +10,3 @@ idf_component_register(
                     PRIV_INCLUDE_DIRS "../private_include" "common" "hcd" "usb_host"
                     PRIV_REQUIRES cmock usb test_utils
                     )
-target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

+ 4 - 4
components/usb/test/common/test_usb_mock_classes.c

@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#include <stdint.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include "usb/usb_types_ch9.h"
@@ -83,15 +83,15 @@ bool mock_msc_scsi_check_csw(mock_msc_bulk_csw_t *csw, uint32_t tag_expect)
     bool no_issues = true;
     if (csw->dCSWSignature != 0x53425355) {
         no_issues = false;
-        printf("Warning: csw signature corrupt (0x%X)\n", csw->dCSWSignature);
+        printf("Warning: csw signature corrupt (0x%"PRIX32")\n", csw->dCSWSignature);
     }
     if (csw->dCSWTag != tag_expect) {
         no_issues = false;
-        printf("Warning: csw tag unexpected! Expected %d got %d\n", tag_expect, csw->dCSWTag);
+        printf("Warning: csw tag unexpected! Expected %"PRIu32" got %"PRIu32"\n", tag_expect, csw->dCSWTag);
     }
     if (csw->dCSWDataResidue) {
         no_issues = false;
-        printf("Warning: csw indicates data residue of %d bytes!\n", csw->dCSWDataResidue);
+        printf("Warning: csw indicates data residue of %"PRIu32" bytes!\n", csw->dCSWDataResidue);
     }
     if (csw->bCSWStatus) {
         no_issues = false;

+ 1 - 1
components/usb/usbh.c

@@ -407,7 +407,7 @@ esp_err_t usbh_process(void)
         Exit critical section to handle device action flags in their listed order
         --------------------------------------------------------------------- */
         USBH_EXIT_CRITICAL();
-        ESP_LOGD(USBH_TAG, "Processing actions 0x%x", action_flags);
+        ESP_LOGD(USBH_TAG, "Processing actions 0x%"PRIx32"", action_flags);
         //Sanity check. If the device is being freed, there must not be any other action flags set
         assert(!(action_flags & DEV_FLAG_ACTION_FREE) || action_flags == DEV_FLAG_ACTION_FREE);
 

+ 3 - 5
docs/en/api-reference/peripherals/usb_host.rst

@@ -1,9 +1,6 @@
 USB Host
 ========
 
-.. warning::
-    The USB Host Library API is a beta version thus is subject to change.
-
 The document provides information regarding the USB Host Library. This document is split into the following sections:
 
 .. contents:: Sections
@@ -365,14 +362,15 @@ The USB Host Stack provides a number examples that implement host class drivers
 CDC-ACM
 """""""
 
-* A host class driver for the Communication Device Class (Abstract Control Model) is currently implemented as an example component (found via :example:`peripherals/usb/host/cdc/common/cdc_acm_host`).
+* A host class driver for the Communication Device Class (Abstract Control Model) is deployed to `IDF component registry <https://components.espressif.com/component/espressif/usb_host_cdc_acm>`__.
 * The :example:`peripherals/usb/host/cdc/cdc_acm_host` example uses the CDC-ACM host driver component to communicate with CDC-ACM devices
 * The :example:`peripherals/usb/host/cdc/cdc_acm_bg96` example uses the CDC-ACM host driver component to communicate with non-compliant CDC-ACM devices (i.e., vendor-specific classes that support a subset of CDC-ACM features) such as the Quectel BG96 modem.
+* The :example:`peripherals/usb/host/cdc/cdc_acm_vcp` example shows how can you extend the CDC-ACM host driver to interface Virtual COM Port devices.
 
 MSC
 """
 
-* A host class driver for the Mass Storage Class (Bulk-Only Transport) is current implemented as an example found via :example:`peripherals/usb/host/msc`.
+* A host class driver for the Mass Storage Class (Bulk-Only Transport) is deployed to `IDF component registry <https://components.espressif.com/component/espressif/usb_host_msc>`__. You can find its example in :example:`peripherals/usb/host/msc`.
 
 
 .. -------------------------------------------------- API Reference ----------------------------------------------------

+ 0 - 2
docs/en/contribute/esp-idf-tests-with-pytest.rst

@@ -270,8 +270,6 @@ Advanced Examples
 Multi Dut Tests with the Same App
 """""""""""""""""""""""""""""""""
 
-This code example is taken from :idf_file:`pytest_usb_host.py <tools/test_apps/peripherals/usb/pytest_usb_host.py>`.
-
 .. code:: python
 
     @pytest.mark.esp32s2

+ 0 - 1
examples/peripherals/usb/host/cdc/cdc_acm_bg96/CMakeLists.txt

@@ -4,6 +4,5 @@
 # CMakeLists in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.16)
 
-set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/peripherals/usb/host/cdc/common)
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(cdc_acm_host_bg96)

+ 2 - 0
examples/peripherals/usb/host/cdc/cdc_acm_bg96/main/idf_component.yml

@@ -1,3 +1,5 @@
+## IDF Component Manager Manifest File
 dependencies:
   idf: ">=4.4"
   igrr/libnmea: "^0.1.1"
+  usb_host_cdc_acm: "1.*"

+ 0 - 1
examples/peripherals/usb/host/cdc/cdc_acm_host/CMakeLists.txt

@@ -4,6 +4,5 @@
 # CMakeLists in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.16)
 
-set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/peripherals/usb/host/cdc/common)
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(cdc_acm_host)

+ 4 - 0
examples/peripherals/usb/host/cdc/cdc_acm_host/main/idf_component.yml

@@ -0,0 +1,4 @@
+## IDF Component Manager Manifest File
+dependencies:
+  usb_host_cdc_acm: "1.*"
+  idf: ">=4.4"

+ 0 - 1
examples/peripherals/usb/host/cdc/cdc_acm_vcp/CMakeLists.txt

@@ -4,6 +4,5 @@
 # CMakeLists in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.16)
 
-set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/peripherals/usb/host/cdc/common)
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(cdc_acm_vcp)

+ 4 - 0
examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/idf_component.yml

@@ -0,0 +1,4 @@
+## IDF Component Manager Manifest File
+dependencies:
+  usb_host_cdc_acm: "1.*"
+  idf: ">=4.4"

+ 0 - 18
examples/peripherals/usb/host/cdc/common/cdc_acm_host/CMakeLists.txt

@@ -1,18 +0,0 @@
-set(srcs)
-set(include)
-# As CONFIG_USB_OTG_SUPPORTED comes from Kconfig, it is not evaluated yet
-# when components are being registered.
-set(require usb)
-
-if(CONFIG_USB_OTG_SUPPORTED)
-    list(APPEND srcs "cdc_acm_host.c")
-    list(APPEND include "include")
-endif()
-
-idf_component_register(SRCS ${srcs}
-                       INCLUDE_DIRS ${include}
-                       REQUIRES ${require}
-                       )
-if(CONFIG_USB_OTG_SUPPORTED)
-    target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
-endif()

+ 0 - 46
examples/peripherals/usb/host/cdc/common/cdc_acm_host/README.md

@@ -1,46 +0,0 @@
-# USB Host CDC-ACM Class Driver
-
-This directory contains an implementation of a USB CDC-ACM Host Class Driver that is implemented on top of the [USB Host Library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_host.html).
-
-## Supported Devices
-
-The CDC-ACM Host driver supports the following types of CDC devices:
-
-1. CDC-ACM devices
-2. CDC-like vendor specific devices (usually found on USB to UART bridge devices)
-
-### CDC-ACM Devices
-
-The CDC-ACM Class driver supports CDC-ACM devices that meet the following requirements:
-- The device class code must be set to the CDC class `0x02` or implement Interface Association Descriptor (IAD)
-- The CDC-ACM must contain the following interfaces:
-    - A Communication Class Interface containing a management element (EP0) and may also contain a notification element (an interrupt endpoint). The driver will check this interface for CDC Functional Descriptors.
-    - A Data Class Interface with two BULK endpoints (IN and OUT). Other transfer types are not supported by the driver
-
-### CDC-Like Vendor Specific Devices
-
-The CDC-ACM Class driver supports CDC-like devices that meet the following requirements:
-- The device class code must be set to the vendor specific class code `0xFF`
-- The device needs to provide and interface containing the following endpoints:
-    - (Mandatory) Two Bulk endpoints (IN and OUT) for data
-    - (Optional) An interrupt endpoint (IN) for the notification element
-
-For CDC-like devices, users are responsible for ensuring that they only call APIs (e.g., `cdc_acm_host_send_break()`) that are supported by the target device.
-
-
-## Usage
-
-The following steps outline the typical API call pattern of the CDC-ACM Class Driver
-
-1. Install the USB Host Library via `usb_host_install()`
-2. Install the CDC-ACM driver via `cdc_acm_host_install()`
-3. Call `cdc_acm_host_open()`/`cdc_acm_host_open_vendor_specific()` to open a target CDC-ACM/CDC-like device. These functions will block until the target device is connected
-4. To transmit data, call `cdc_acm_host_data_tx_blocking()`
-5. When data is received, the driver will automatically run the receive data callback
-6. An opened device can be closed via `cdc_acm_host_close()`
-7. The CDC-ACM driver can be uninstalled via `cdc_acm_host_uninstall()`
-
-## Examples
-
-- For an example with a CDC-ACM device, refer to [cdc_acm_host](../../cdc_acm_host)
-- For an example with a CDC-like device, refer to [cdc_acm_host_bg96](../../cdc_acm_bg96)

+ 0 - 1223
examples/peripherals/usb/host/cdc/common/cdc_acm_host/cdc_acm_host.c

@@ -1,1223 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include "esp_log.h"
-#include <stdio.h>
-#include <string.h>
-#include <sys/queue.h>
-#include "usb/usb_host.h"
-#include "usb/cdc_acm_host.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "freertos/semphr.h"
-#include "freertos/event_groups.h"
-#include "esp_check.h"
-#include "esp_system.h"
-
-#define TAG "cdc_acm"
-
-// CDC devices often implement Interface Association Descriptor (IAD). Parse IAD only when
-// bDeviceClass = 0xEF (Miscellaneous Device Class), bDeviceSubClass = 0x02 (Common Class), bDeviceProtocol = 0x01 (Interface Association Descriptor)
-// @see USB Interface Association Descriptor: Device Class Code and Use Model rev 1.0, Table 1-1
-#define USB_SUBCLASS_COMMON        0x02
-#define USB_DEVICE_PROTOCOL_IAD    0x01
-
-// CDC-ACM spinlock
-static portMUX_TYPE cdc_acm_lock = portMUX_INITIALIZER_UNLOCKED;
-#define CDC_ACM_ENTER_CRITICAL()   portENTER_CRITICAL(&cdc_acm_lock)
-#define CDC_ACM_EXIT_CRITICAL()    portEXIT_CRITICAL(&cdc_acm_lock)
-
-// CDC-ACM events
-#define CDC_ACM_TEARDOWN          BIT0
-#define CDC_ACM_TEARDOWN_COMPLETE BIT1
-
-// CDC-ACM check macros
-#define CDC_ACM_CHECK(cond, ret_val) ({                                     \
-            if (!(cond)) {                                                  \
-                return (ret_val);                                           \
-            }                                                               \
-})
-
-#define CDC_ACM_CHECK_FROM_CRIT(cond, ret_val) ({                           \
-            if (!(cond)) {                                                  \
-                CDC_ACM_EXIT_CRITICAL();                                    \
-                return ret_val;                                             \
-            }                                                               \
-})
-
-// CDC-ACM driver object
-typedef struct {
-    usb_host_client_handle_t cdc_acm_client_hdl;        /*!< USB Host handle reused for all CDC-ACM devices in the system */
-    SemaphoreHandle_t open_close_mutex;
-    EventGroupHandle_t event_group;
-    cdc_acm_new_dev_callback_t new_dev_cb;
-    SLIST_HEAD(list_dev, cdc_dev_s) cdc_devices_list;   /*!< List of open pseudo devices */
-} cdc_acm_obj_t;
-
-static cdc_acm_obj_t *p_cdc_acm_obj = NULL;
-
-/**
- * @brief Default CDC-ACM driver configuration
- *
- * This configuration is used when user passes NULL to config pointer during device open.
- */
-static const cdc_acm_host_driver_config_t cdc_acm_driver_config_default = {
-    .driver_task_stack_size = 4096,
-    .driver_task_priority = 10,
-    .xCoreID = 0,
-    .new_dev_cb = NULL,
-};
-
-/**
- * @brief USB CDC PSTN Call Descriptor
- *
- * @see Table 3, USB CDC-PSTN specification rev. 1.2
- */
-typedef struct {
-    uint8_t bFunctionLength;
-    const uint8_t bDescriptorType;
-    const cdc_desc_subtype_t bDescriptorSubtype;
-    union {
-        struct {
-            uint8_t call_management:   1; // Device handles call management itself
-            uint8_t call_over_data_if: 1; // Device sends/receives call management information over Data Class interface
-            uint8_t reserved: 6;
-        };
-        uint8_t val;
-    } bmCapabilities;
-    uint8_t bDataInterface; // Interface number of Data Class interface optionally used for call management
-} __attribute__((packed)) cdc_acm_call_desc_t;
-
-/**
- * @brief USB CDC PSTN Abstract Control Model Descriptor
- *
- * @see Table 4, USB CDC-PSTN specification rev. 1.2
- */
-typedef struct {
-    uint8_t bFunctionLength;
-    const uint8_t bDescriptorType;
-    const cdc_desc_subtype_t bDescriptorSubtype;
-    union {
-        struct {
-            uint8_t feature:    1; // Device supports Set/Clear/Get_Comm_Feature requests
-            uint8_t serial:     1; // Device supports Set/Get_Line_Coding, Set_Control_Line_State and Serial_State request and notifications
-            uint8_t send_break: 1; // Device supports Send_Break request
-            uint8_t network:    1; // Device supports Network_Connection notification
-            uint8_t reserved:   4;
-        };
-        uint8_t val;
-    } bmCapabilities;
-} __attribute__((packed)) cdc_acm_acm_desc_t;
-
-typedef struct cdc_dev_s cdc_dev_t;
-struct cdc_dev_s{
-    usb_device_handle_t dev_hdl;          // USB device handle
-    void *cb_arg;                         // Common argument for user's callbacks (data IN and Notification)
-    struct {
-        usb_transfer_t *out_xfer;         // OUT data transfer
-        usb_transfer_t *in_xfer;          // IN data transfer
-        cdc_acm_data_callback_t in_cb;    // User's callback for async (non-blocking) data IN
-        const usb_intf_desc_t *intf_desc; // Pointer to data interface descriptor
-        SemaphoreHandle_t out_mux;        // OUT mutex
-    } data;
-
-    struct {
-        usb_transfer_t *xfer;             // IN notification transfer
-        const usb_intf_desc_t *intf_desc; // Pointer to notification interface descriptor, can be NULL if there is no notification channel in the device
-        cdc_acm_host_dev_callback_t cb;   // User's callback for device events
-    } notif;                              // Structure with Notif pipe data
-
-    usb_transfer_t *ctrl_transfer;        // CTRL (endpoint 0) transfer
-    SemaphoreHandle_t ctrl_mux;           // CTRL mutex
-    cdc_acm_uart_state_t serial_state;    // Serial State
-    cdc_comm_protocol_t comm_protocol;
-    cdc_data_protocol_t data_protocol;
-    int             num_cdc_intf_desc;    // Number of CDC Interface descriptors in following array
-    const usb_standard_desc_t **cdc_intf_desc;   // CDC Interface descriptors
-    SLIST_ENTRY(cdc_dev_s) list_entry;
-};
-
-/**
- * @brief Notification received callback
- *
- * Notification (interrupt) IN transfer is submitted at the end of this function to ensure periodic poll of IN endpoint.
- *
- * @param[in] transfer Transfer that triggered the callback
- */
-static void notif_xfer_cb(usb_transfer_t *transfer);
-
-/**
- * @brief Data received callback
- *
- * Data (bulk) IN transfer is submitted at the end of this function to ensure continuous poll of IN endpoint.
- *
- * @param[in] transfer Transfer that triggered the callback
- */
-static void in_xfer_cb(usb_transfer_t *transfer);
-
-/**
- * @brief Data send callback
- *
- * Reused for bulk OUT and CTRL transfers
- *
- * @param[in] transfer Transfer that triggered the callback
- */
-static void out_xfer_cb(usb_transfer_t *transfer);
-
-/**
- * @brief USB Host Client event callback
- *
- * Handling of USB device connection/disconnection to/from root HUB.
- *
- * @param[in] event_msg Event message type
- * @param[in] arg Caller's argument (not used in this driver)
- */
-static void usb_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg);
-
-/**
- * @brief Send CDC specific request
- *
- * Helper function that will send CDC specific request to default endpoint.
- * Both IN and OUT requests are sent through this API, depending on the in_transfer parameter.
- *
- * @see  Chapter 6.2, USB CDC specification rev. 1.2
- * @note CDC specific requests are only supported by devices that have dedicated management element.
- *
- * @param[in] cdc_dev Pointer to CDC device
- * @param[in] in_transfer Direction of data phase. true: IN, false: OUT
- * @param[in] request CDC request code
- * @param[inout] data Pointer to data buffer. Input for OUT transfers, output for IN transfers.
- * @param[in] data_len Length of data buffer
- * @param[in] value Value to be set in bValue of Setup packet
- * @return esp_err_t
- */
-static esp_err_t send_cdc_request(cdc_dev_t *cdc_dev, bool in_transfer, cdc_request_code_t request, uint8_t *data, uint16_t data_len, uint16_t value);
-
-/**
- * @brief CDC-ACM driver handling task
- *
- * USB host client registration and deregistration is handled here.
- *
- * @param[in] arg User's argument. Handle of a task that started this task.
- */
-static void cdc_acm_client_task(void *arg)
-{
-    vTaskSuspend(NULL); // Task will be resumed from cdc_acm_host_install()
-    cdc_acm_obj_t *cdc_acm_obj = p_cdc_acm_obj; // Make local copy of the driver's handle
-    assert(cdc_acm_obj->cdc_acm_client_hdl);
-
-    // Start handling client's events
-    while (1) {
-        usb_host_client_handle_events(cdc_acm_obj->cdc_acm_client_hdl, portMAX_DELAY);
-        EventBits_t events = xEventGroupGetBits(cdc_acm_obj->event_group);
-        if (events & CDC_ACM_TEARDOWN) {
-            break;
-        }
-    }
-
-    ESP_LOGD(TAG, "Deregistering client");
-    ESP_ERROR_CHECK(usb_host_client_deregister(cdc_acm_obj->cdc_acm_client_hdl));
-    xEventGroupSetBits(cdc_acm_obj->event_group, CDC_ACM_TEARDOWN_COMPLETE);
-    vTaskDelete(NULL);
-}
-
-/**
- * @brief Cancel transfer and reset endpoint
- *
- * This function will cancel ongoing transfer a reset its endpoint to ready state.
- *
- * @param[in] dev_hdl USB device handle
- * @param[in] transfer Transfer to be cancelled
- * @return esp_err_t
- */
-static esp_err_t cdc_acm_reset_transfer_endpoint(usb_device_handle_t dev_hdl, usb_transfer_t *transfer)
-{
-    assert(dev_hdl);
-    assert(transfer);
-
-    ESP_RETURN_ON_ERROR(usb_host_endpoint_halt(dev_hdl, transfer->bEndpointAddress), TAG,);
-    ESP_RETURN_ON_ERROR(usb_host_endpoint_flush(dev_hdl, transfer->bEndpointAddress), TAG,);
-    usb_host_endpoint_clear(dev_hdl, transfer->bEndpointAddress);
-    return ESP_OK;
-}
-
-/**
- * @brief Start CDC device
- *
- * After this call, USB host peripheral will continuously poll IN endpoints.
- *
- * @param cdc_dev
- * @param[in] event_cb  Device event callback
- * @param[in] in_cb     Data received callback
- * @param[in] user_arg  Optional user's argument, that will be passed to the callbacks
- * @return esp_err_t
- */
-static esp_err_t cdc_acm_start(cdc_dev_t *cdc_dev, cdc_acm_host_dev_callback_t event_cb, cdc_acm_data_callback_t in_cb, void *user_arg)
-{
-    esp_err_t ret = ESP_OK;
-    assert(cdc_dev);
-
-    CDC_ACM_ENTER_CRITICAL();
-    cdc_dev->notif.cb = event_cb;
-    cdc_dev->data.in_cb = in_cb;
-    cdc_dev->cb_arg = user_arg;
-    CDC_ACM_EXIT_CRITICAL();
-
-    // Claim data interface and start polling its IN endpoint
-    ESP_GOTO_ON_ERROR(usb_host_interface_claim(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl, cdc_dev->data.intf_desc->bInterfaceNumber, 0), err, TAG,);
-    ESP_LOGD("CDC_ACM", "Submitting poll for BULK IN transfer");
-    ESP_ERROR_CHECK(usb_host_transfer_submit(cdc_dev->data.in_xfer));
-
-    // If notification are supported, claim its interface and start polling its IN endpoint
-    if (cdc_dev->notif.intf_desc != NULL) {
-        if (cdc_dev->notif.intf_desc != cdc_dev->data.intf_desc) {
-            ESP_GOTO_ON_ERROR(usb_host_interface_claim(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl,
-                                                     cdc_dev->notif.intf_desc->bInterfaceNumber, 0), err, TAG,);
-        }
-        ESP_LOGD("CDC_ACM", "Submitting poll for INTR IN transfer");
-        ESP_ERROR_CHECK(usb_host_transfer_submit(cdc_dev->notif.xfer));
-    }
-
-    // Everything OK, add the device into list and return
-    CDC_ACM_ENTER_CRITICAL();
-    SLIST_INSERT_HEAD(&p_cdc_acm_obj->cdc_devices_list, cdc_dev, list_entry);
-    CDC_ACM_EXIT_CRITICAL();
-    return ret;
-
-err:
-    usb_host_interface_release(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl, cdc_dev->data.intf_desc->bInterfaceNumber);
-    if (cdc_dev->notif.intf_desc != NULL) {
-        usb_host_interface_release(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl, cdc_dev->notif.intf_desc->bInterfaceNumber);
-    }
-    return ret;
-}
-
-static void cdc_acm_transfers_free(cdc_dev_t *cdc_dev);
-/**
- * @brief Helper function that releases resources claimed by CDC device
- *
- * Close underlying USB device, free device driver memory
- *
- * @note All interfaces claimed by this device must be release before calling this function
- * @param cdc_dev CDC device handle to be removed
- */
-static void cdc_acm_device_remove(cdc_dev_t *cdc_dev)
-{
-    assert(cdc_dev);
-    cdc_acm_transfers_free(cdc_dev);
-    free(cdc_dev->cdc_intf_desc);
-    // We don't check the error code of usb_host_device_close, as the close might fail, if someone else is still using the device (not all interfaces are released)
-    usb_host_device_close(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl); // Gracefully continue on error
-    free(cdc_dev);
-}
-
-/**
- * @brief Open USB device with requested VID/PID
- *
- * This function has two regular return paths:
- * 1. USB device with matching VID/PID is already opened by this driver: allocate new CDC device on top of the already opened USB device.
- * 2. USB device with matching VID/PID is NOT opened by this driver yet: poll USB connected devices until it is found.
- *
- * @note This function will block for timeout_ms, if the device is not enumerated at the moment of calling this function.
- * @param[in] vid Vendor ID
- * @param[in] pid Product ID
- * @param[in] timeout_ms Connection timeout [ms]
- * @param[out] dev CDC-ACM device
- * @return esp_err_t
- */
-static esp_err_t cdc_acm_find_and_open_usb_device(uint16_t vid, uint16_t pid, int timeout_ms, cdc_dev_t **dev)
-{
-    assert(p_cdc_acm_obj);
-    assert(dev);
-
-    *dev = calloc(1, sizeof(cdc_dev_t));
-    if (*dev == NULL) {
-        return ESP_ERR_NO_MEM;
-    }
-
-    // First, check list of already opened CDC devices
-    ESP_LOGD(TAG, "Checking list of opened USB devices");
-    cdc_dev_t *cdc_dev;
-    SLIST_FOREACH(cdc_dev, &p_cdc_acm_obj->cdc_devices_list, list_entry) {
-        const usb_device_desc_t *device_desc;
-        ESP_ERROR_CHECK(usb_host_get_device_descriptor(cdc_dev->dev_hdl, &device_desc));
-        if (device_desc->idVendor == vid && device_desc->idProduct == pid) {
-            // Return path 1:
-            (*dev)->dev_hdl = cdc_dev->dev_hdl;
-            return ESP_OK;
-        }
-    }
-
-    // Second, poll connected devices until new device is connected or timeout
-    TickType_t timeout_ticks = (timeout_ms == 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
-    TimeOut_t connection_timeout;
-    vTaskSetTimeOutState(&connection_timeout);
-
-    while (true) {
-        ESP_LOGD(TAG, "Checking list of connected USB devices");
-        uint8_t dev_addr_list[10];
-        int num_of_devices;
-        ESP_ERROR_CHECK(usb_host_device_addr_list_fill(sizeof(dev_addr_list), dev_addr_list, &num_of_devices));
-
-        // Go through device address list and find the one we are looking for
-        for (int i = 0; i < num_of_devices; i++) {
-            usb_device_handle_t current_device;
-            // Open USB device
-            if (usb_host_device_open(p_cdc_acm_obj->cdc_acm_client_hdl, dev_addr_list[i], &current_device) != ESP_OK) {
-                continue; // In case we failed to open this device, continue with next one in the list
-            }
-            assert(current_device);
-            const usb_device_desc_t *device_desc;
-            ESP_ERROR_CHECK(usb_host_get_device_descriptor(current_device, &device_desc));
-            if (device_desc->idVendor == vid && device_desc->idProduct == pid) {
-                // Return path 2:
-                (*dev)->dev_hdl = current_device;
-                return ESP_OK;
-            }
-            usb_host_device_close(p_cdc_acm_obj->cdc_acm_client_hdl, current_device);
-        }
-
-        if (xTaskCheckForTimeOut(&connection_timeout, &timeout_ticks) != pdFALSE) {
-            break; // Timeout elapsed and the device is not connected
-        }
-        vTaskDelay(pdMS_TO_TICKS(50));
-    }
-
-    // Timeout was reached, clean-up
-    free(*dev);
-    *dev = NULL;
-    return ESP_ERR_NOT_FOUND;
-}
-
-esp_err_t cdc_acm_host_install(const cdc_acm_host_driver_config_t *driver_config)
-{
-    CDC_ACM_CHECK(!p_cdc_acm_obj, ESP_ERR_INVALID_STATE);
-
-    // Check driver configuration, use default if NULL is passed
-    if (driver_config == NULL) {
-        driver_config = &cdc_acm_driver_config_default;
-    }
-
-    // Allocate all we need for this driver
-    esp_err_t ret;
-    cdc_acm_obj_t *cdc_acm_obj = heap_caps_calloc(1, sizeof(cdc_acm_obj_t), MALLOC_CAP_DEFAULT);
-    EventGroupHandle_t event_group = xEventGroupCreate();
-    SemaphoreHandle_t mutex = xSemaphoreCreateMutex();
-    TaskHandle_t driver_task_h = NULL;
-    xTaskCreatePinnedToCore(
-            cdc_acm_client_task, "USB-CDC", driver_config->driver_task_stack_size, NULL,
-            driver_config->driver_task_priority, &driver_task_h, driver_config->xCoreID);
-
-    if (cdc_acm_obj == NULL || driver_task_h == NULL || event_group == NULL || mutex == NULL) {
-        ret = ESP_ERR_NO_MEM;
-        goto err;
-    }
-
-    // Register USB Host client
-    usb_host_client_handle_t usb_client = NULL;
-    const usb_host_client_config_t client_config = {
-        .is_synchronous = false,
-        .max_num_event_msg = 3,
-        .async.client_event_callback = usb_event_cb,
-        .async.callback_arg = NULL
-    };
-    ESP_GOTO_ON_ERROR(usb_host_client_register(&client_config, &usb_client), err, TAG, "Failed to register USB host client");
-
-    // Initialize CDC-ACM driver structure
-    SLIST_INIT(&(cdc_acm_obj->cdc_devices_list));
-    cdc_acm_obj->event_group = event_group;
-    cdc_acm_obj->open_close_mutex = mutex;
-    cdc_acm_obj->cdc_acm_client_hdl = usb_client;
-    cdc_acm_obj->new_dev_cb = driver_config->new_dev_cb;
-
-    // Between 1st call of this function and following section, another task might try to install this driver:
-    // Make sure that there is only one instance of this driver in the system
-    CDC_ACM_ENTER_CRITICAL();
-    if (p_cdc_acm_obj) {
-        // Already created
-        ret = ESP_ERR_INVALID_STATE;
-        CDC_ACM_EXIT_CRITICAL();
-        goto client_err;
-    } else {
-        p_cdc_acm_obj = cdc_acm_obj;
-    }
-    CDC_ACM_EXIT_CRITICAL();
-
-    // Everything OK: Start CDC-Driver task and return
-    vTaskResume(driver_task_h);
-    return ESP_OK;
-
-client_err:
-    usb_host_client_deregister(usb_client);
-err: // Clean-up
-    free(cdc_acm_obj);
-    if (event_group) {
-        vEventGroupDelete(event_group);
-    }
-    if (driver_task_h) {
-        vTaskDelete(driver_task_h);
-    }
-    if (mutex) {
-        vSemaphoreDelete(mutex);
-    }
-    return ret;
-}
-
-esp_err_t cdc_acm_host_uninstall()
-{
-    esp_err_t ret;
-
-    CDC_ACM_ENTER_CRITICAL();
-    CDC_ACM_CHECK_FROM_CRIT(p_cdc_acm_obj, ESP_ERR_INVALID_STATE);
-    cdc_acm_obj_t *cdc_acm_obj = p_cdc_acm_obj; // Save Driver's handle to temporary handle
-    CDC_ACM_EXIT_CRITICAL();
-
-    xSemaphoreTake(p_cdc_acm_obj->open_close_mutex, portMAX_DELAY); // Wait for all open/close calls to finish
-
-    CDC_ACM_ENTER_CRITICAL();
-    if (SLIST_EMPTY(&p_cdc_acm_obj->cdc_devices_list)) { // Check that device list is empty (all devices closed)
-        p_cdc_acm_obj = NULL; // NULL static driver pointer: No open/close calls form this point
-    } else {
-        ret = ESP_ERR_INVALID_STATE;
-        CDC_ACM_EXIT_CRITICAL();
-        goto unblock;
-    }
-    CDC_ACM_EXIT_CRITICAL();
-
-    // Signal to CDC task to stop, unblock it and wait for its deletion
-    xEventGroupSetBits(cdc_acm_obj->event_group, CDC_ACM_TEARDOWN);
-    usb_host_client_unblock(cdc_acm_obj->cdc_acm_client_hdl);
-    ESP_GOTO_ON_FALSE(
-        xEventGroupWaitBits(cdc_acm_obj->event_group, CDC_ACM_TEARDOWN_COMPLETE, pdFALSE, pdFALSE, pdMS_TO_TICKS(100)),
-        ESP_ERR_NOT_FINISHED, unblock, TAG,);
-
-    // Free remaining resources and return
-    vEventGroupDelete(cdc_acm_obj->event_group);
-    xSemaphoreGive(cdc_acm_obj->open_close_mutex);
-    vSemaphoreDelete(cdc_acm_obj->open_close_mutex);
-    free(cdc_acm_obj);
-    return ESP_OK;
-
-unblock:
-    xSemaphoreGive(cdc_acm_obj->open_close_mutex);
-    return ret;
-}
-
-/**
- * @brief Free USB transfers used by this device
- *
- * @note There can be no transfers in flight, at the moment of calling this function.
- * @param[in] cdc_dev Pointer to CDC device
- */
-static void cdc_acm_transfers_free(cdc_dev_t *cdc_dev)
-{
-    assert(cdc_dev);
-    usb_host_transfer_free(cdc_dev->notif.xfer);
-    usb_host_transfer_free(cdc_dev->data.in_xfer);
-    if (cdc_dev->data.out_xfer != NULL) {
-        if (cdc_dev->data.out_xfer->context != NULL) {
-            vSemaphoreDelete((SemaphoreHandle_t)cdc_dev->data.out_xfer->context);
-        }
-        if (cdc_dev->data.out_mux != NULL) {
-            vSemaphoreDelete(cdc_dev->data.out_mux);
-        }
-        usb_host_transfer_free(cdc_dev->data.out_xfer);
-    }
-    if (cdc_dev->ctrl_transfer != NULL) {
-        if (cdc_dev->ctrl_transfer->context != NULL) {
-            vSemaphoreDelete((SemaphoreHandle_t)cdc_dev->ctrl_transfer->context);
-        }
-        if (cdc_dev->ctrl_mux != NULL) {
-            vSemaphoreDelete(cdc_dev->ctrl_mux);
-        }
-        usb_host_transfer_free(cdc_dev->ctrl_transfer);
-    }
-}
-
-/**
- * @brief Allocate CDC transfers
- *
- * @param[in] cdc_dev       Pointer to CDC device
- * @param[in] notif_ep_desc Pointer to notification EP descriptor
- * @param[in] in_ep_desc-   Pointer to data IN EP descriptor
- * @param[in] out_ep_desc   Pointer to data OUT EP descriptor
- * @param[in] out_buf_len   Length of data OUT buffer
- * @return esp_err_t
- */
-static esp_err_t cdc_acm_transfers_allocate(cdc_dev_t *cdc_dev, const usb_ep_desc_t *notif_ep_desc, const usb_ep_desc_t *in_ep_desc, const usb_ep_desc_t *out_ep_desc, size_t out_buf_len)
-{
-    esp_err_t ret;
-
-    // 1. Setup notification transfer if it is supported
-    if (notif_ep_desc) {
-        ESP_GOTO_ON_ERROR(
-            usb_host_transfer_alloc(USB_EP_DESC_GET_MPS(notif_ep_desc), 0, &cdc_dev->notif.xfer),
-            err, TAG,);
-        cdc_dev->notif.xfer->device_handle = cdc_dev->dev_hdl;
-        cdc_dev->notif.xfer->bEndpointAddress = notif_ep_desc->bEndpointAddress;
-        cdc_dev->notif.xfer->callback = notif_xfer_cb;
-        cdc_dev->notif.xfer->context = cdc_dev;
-        cdc_dev->notif.xfer->num_bytes = USB_EP_DESC_GET_MPS(notif_ep_desc);
-    }
-
-    // 2. Setup control transfer
-    usb_device_info_t dev_info;
-    ESP_ERROR_CHECK(usb_host_device_info(cdc_dev->dev_hdl, &dev_info));
-    ESP_GOTO_ON_ERROR(
-        usb_host_transfer_alloc(dev_info.bMaxPacketSize0, 0, &cdc_dev->ctrl_transfer),
-        err, TAG,);
-    cdc_dev->ctrl_transfer->timeout_ms = 1000;
-    cdc_dev->ctrl_transfer->bEndpointAddress = 0;
-    cdc_dev->ctrl_transfer->device_handle = cdc_dev->dev_hdl;
-    cdc_dev->ctrl_transfer->context = cdc_dev;
-    cdc_dev->ctrl_transfer->callback = out_xfer_cb;
-    cdc_dev->ctrl_transfer->context = xSemaphoreCreateBinary();
-    ESP_GOTO_ON_FALSE(cdc_dev->ctrl_transfer->context, ESP_ERR_NO_MEM, err, TAG,);
-    cdc_dev->ctrl_mux = xSemaphoreCreateMutex();
-    ESP_GOTO_ON_FALSE(cdc_dev->ctrl_mux, ESP_ERR_NO_MEM, err, TAG,);
-
-    // 3. Setup IN data transfer
-    ESP_GOTO_ON_ERROR(
-        usb_host_transfer_alloc(USB_EP_DESC_GET_MPS(in_ep_desc), 0, &cdc_dev->data.in_xfer),
-        err, TAG,
-    );
-    assert(cdc_dev->data.in_xfer);
-    cdc_dev->data.in_xfer->callback = in_xfer_cb;
-    cdc_dev->data.in_xfer->num_bytes = USB_EP_DESC_GET_MPS(in_ep_desc);
-    cdc_dev->data.in_xfer->bEndpointAddress = in_ep_desc->bEndpointAddress;
-    cdc_dev->data.in_xfer->device_handle = cdc_dev->dev_hdl;
-    cdc_dev->data.in_xfer->context = cdc_dev;
-
-    // 4. Setup OUT bulk transfer (if it is required (out_buf_len > 0))
-    if (out_buf_len != 0) {
-        ESP_GOTO_ON_ERROR(
-            usb_host_transfer_alloc(out_buf_len, 0, &cdc_dev->data.out_xfer),
-            err, TAG,
-        );
-        assert(cdc_dev->data.out_xfer);
-        cdc_dev->data.out_xfer->device_handle = cdc_dev->dev_hdl;
-        cdc_dev->data.out_xfer->context = xSemaphoreCreateBinary();
-        ESP_GOTO_ON_FALSE(cdc_dev->data.out_xfer->context, ESP_ERR_NO_MEM, err, TAG,);
-        cdc_dev->data.out_mux = xSemaphoreCreateMutex();
-        ESP_GOTO_ON_FALSE(cdc_dev->data.out_mux, ESP_ERR_NO_MEM, err, TAG,);
-        cdc_dev->data.out_xfer->bEndpointAddress = out_ep_desc->bEndpointAddress;
-        cdc_dev->data.out_xfer->callback = out_xfer_cb;
-    }
-    return ESP_OK;
-
-err:
-    cdc_acm_transfers_free(cdc_dev);
-    return ret;
-}
-
-/**
- * @brief Find CDC interface descriptor and its endpoint descriptors
- *
- * @note This function is called in open procedure of CDC compliant devices only.
- * @param[in]  cdc_dev  Pointer to CDC device
- * @param[in]  intf_idx Index of CDC interface that should be used for this device
- * @param[out] notif_ep Pointer to notification EP descriptor
- * @param[out] in_ep    Pointer to data IN EP descriptor
- * @param[out] out_ep   Pointer to data OUT EP descriptor
- * @return esp_err_t
- */
-static esp_err_t cdc_acm_find_intf_and_ep_desc(cdc_dev_t *cdc_dev, uint8_t intf_idx, const usb_ep_desc_t **notif_ep, const usb_ep_desc_t **in_ep, const usb_ep_desc_t **out_ep)
-{
-    bool interface_found = false;
-    const usb_config_desc_t *config_desc;
-    const usb_device_desc_t *device_desc;
-    int data_intf_idx, notif_intf_idx;
-    int desc_offset = 0;
-
-    // Get required descriptors
-    ESP_ERROR_CHECK(usb_host_get_device_descriptor(cdc_dev->dev_hdl, &device_desc));
-    ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(cdc_dev->dev_hdl, &config_desc));
-
-    if ((device_desc->bDeviceClass == USB_CLASS_MISC) && (device_desc->bDeviceSubClass == USB_SUBCLASS_COMMON) &&
-        (device_desc->bDeviceProtocol == USB_DEVICE_PROTOCOL_IAD)) {
-        // This is a composite device, that uses Interface Association Descriptor
-        const usb_standard_desc_t *this_desc = (const usb_standard_desc_t *)config_desc;
-        do {
-            this_desc = usb_parse_next_descriptor_of_type(
-                this_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, &desc_offset);
-
-            if (this_desc == NULL)
-                break; // Reached end of configuration descriptor
-
-            const usb_iad_desc_t *iad_desc = (const usb_iad_desc_t *)this_desc;
-            if (iad_desc->bFirstInterface == intf_idx) {
-                // IAD with correct interface number was found: Check Class/Subclass codes, save Interface indexes
-                assert(iad_desc->bInterfaceCount == 2);
-                assert(iad_desc->bFunctionClass == USB_CLASS_COMM);
-                assert(iad_desc->bFunctionSubClass == USB_CDC_SUBCLASS_ACM);
-                notif_intf_idx = iad_desc->bFirstInterface;
-                data_intf_idx = iad_desc->bFirstInterface + 1;
-                interface_found = true;
-            }
-        } while (!interface_found);
-    } else if ((device_desc->bDeviceClass == USB_CLASS_COMM) && (intf_idx == 0)) {
-        // This is a Communication Device Class
-        notif_intf_idx = 0;
-        data_intf_idx = 1;
-        interface_found = true;
-    }
-
-    // Save found interfaces descriptors:
-    if (interface_found) {
-        // Notification IF and EP
-        cdc_dev->notif.intf_desc = usb_parse_interface_descriptor(config_desc, notif_intf_idx, 0, &desc_offset);
-        assert(cdc_dev->notif.intf_desc);
-
-        // CDC specific descriptors should be right after CDC-Communication interface descriptor
-        // Note: That's why we use usb_parse_next_descriptor instead of usb_parse_next_descriptor_of_type.
-        // The latter could return CDC specific descriptors that don't belong to this interface
-        const usb_standard_desc_t *cdc_desc = (usb_standard_desc_t *)cdc_dev->notif.intf_desc;
-        do {
-            cdc_desc = usb_parse_next_descriptor(cdc_desc, config_desc->wTotalLength, &desc_offset);
-            if ((cdc_desc == NULL) || (cdc_desc->bDescriptorType != ((USB_CLASS_COMM << 4) | USB_B_DESCRIPTOR_TYPE_INTERFACE )))
-                break; // We found all CDC specific descriptors
-            cdc_dev->num_cdc_intf_desc++;
-            cdc_dev->cdc_intf_desc =
-                realloc(cdc_dev->cdc_intf_desc, cdc_dev->num_cdc_intf_desc * (sizeof(usb_standard_desc_t *)));
-            assert(cdc_dev->cdc_intf_desc);
-            cdc_dev->cdc_intf_desc[cdc_dev->num_cdc_intf_desc - 1] = cdc_desc;
-        } while (1);
-        *notif_ep = usb_parse_endpoint_descriptor_by_index(cdc_dev->notif.intf_desc, 0, config_desc->wTotalLength, &desc_offset);
-        assert(notif_ep);
-
-        // Data IF and EP
-        cdc_dev->data.intf_desc = usb_parse_interface_descriptor(config_desc, data_intf_idx, 0, &desc_offset);
-        assert(cdc_dev->data.intf_desc);
-        int temp_offset = desc_offset;
-        for (int i = 0; i < 2; i++) {
-            const usb_ep_desc_t *this_ep = usb_parse_endpoint_descriptor_by_index(cdc_dev->data.intf_desc, i, config_desc->wTotalLength, &desc_offset);
-            assert(this_ep);
-            if (USB_EP_DESC_GET_EP_DIR(this_ep)) {
-                *in_ep = this_ep;
-            } else {
-                *out_ep = this_ep;
-            }
-            desc_offset = temp_offset;
-        }
-        return ESP_OK;
-    }
-    return ESP_ERR_NOT_FOUND;
-}
-
-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)
-{
-    esp_err_t ret;
-    CDC_ACM_CHECK(p_cdc_acm_obj, ESP_ERR_INVALID_STATE);
-    CDC_ACM_CHECK(dev_config, ESP_ERR_INVALID_ARG);
-    CDC_ACM_CHECK(cdc_hdl_ret, ESP_ERR_INVALID_ARG);
-
-    xSemaphoreTake(p_cdc_acm_obj->open_close_mutex, portMAX_DELAY);
-    // Find underlying USB device
-    cdc_dev_t *cdc_dev;
-    ESP_GOTO_ON_ERROR(
-        cdc_acm_find_and_open_usb_device(vid, pid, dev_config->connection_timeout_ms, &cdc_dev),
-        exit, TAG, "USB device with VID: 0x%04X, PID: 0x%04X not found", vid, pid);
-
-    // Find and save relevant interface and endpoint descriptors
-    const usb_ep_desc_t *notif_ep = NULL;
-    const usb_ep_desc_t *in_ep = NULL;
-    const usb_ep_desc_t *out_ep = NULL;
-    ESP_GOTO_ON_ERROR(
-        cdc_acm_find_intf_and_ep_desc(cdc_dev, interface_idx, &notif_ep, &in_ep, &out_ep),
-        err, TAG, "Could not find required interface");
-
-    // Check whether found Interfaces are really CDC-ACM
-    assert(cdc_dev->notif.intf_desc->bInterfaceClass == USB_CLASS_COMM);
-    assert(cdc_dev->notif.intf_desc->bInterfaceSubClass == USB_CDC_SUBCLASS_ACM);
-    assert(cdc_dev->notif.intf_desc->bNumEndpoints == 1);
-    assert(cdc_dev->data.intf_desc->bInterfaceClass == USB_CLASS_CDC_DATA);
-    assert(cdc_dev->data.intf_desc->bNumEndpoints == 2);
-
-    // Save Communication and Data protocols
-    cdc_dev->comm_protocol = (cdc_comm_protocol_t)cdc_dev->notif.intf_desc->bInterfaceProtocol;
-    cdc_dev->data_protocol = (cdc_data_protocol_t)cdc_dev->data.intf_desc->bInterfaceProtocol;
-
-    // Allocate USB transfers, claim CDC interfaces and return CDC-ACM handle
-    ESP_GOTO_ON_ERROR(cdc_acm_transfers_allocate(cdc_dev, notif_ep, in_ep, out_ep, dev_config->out_buffer_size), err, TAG,);
-    ESP_GOTO_ON_ERROR(cdc_acm_start(cdc_dev, dev_config->event_cb, dev_config->data_cb, dev_config->user_arg), err, TAG,);
-    *cdc_hdl_ret = (cdc_acm_dev_hdl_t)cdc_dev;
-    xSemaphoreGive(p_cdc_acm_obj->open_close_mutex);
-    return ESP_OK;
-
-err:
-    cdc_acm_device_remove(cdc_dev);
-exit:
-    xSemaphoreGive(p_cdc_acm_obj->open_close_mutex);
-    *cdc_hdl_ret = NULL;
-    return ret;
-}
-
-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)
-{
-    esp_err_t ret;
-    CDC_ACM_CHECK(p_cdc_acm_obj, ESP_ERR_INVALID_STATE);
-    CDC_ACM_CHECK(dev_config, ESP_ERR_INVALID_ARG);
-    CDC_ACM_CHECK(cdc_hdl_ret, ESP_ERR_INVALID_ARG);
-
-    xSemaphoreTake(p_cdc_acm_obj->open_close_mutex, portMAX_DELAY);
-
-    // Find underlying USB device
-    cdc_dev_t *cdc_dev;
-    ESP_GOTO_ON_ERROR(
-        cdc_acm_find_and_open_usb_device(vid, pid, dev_config->connection_timeout_ms, &cdc_dev),
-        exit, TAG, "USB device with VID: 0x%04X, PID: 0x%04X not found", vid, pid);
-
-    // Open procedure for CDC-ACM non-compliant devices:
-    const usb_config_desc_t *config_desc;
-    int desc_offset;
-    ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(cdc_dev->dev_hdl, &config_desc));
-    cdc_dev->data.intf_desc = usb_parse_interface_descriptor(config_desc, interface_num, 0, &desc_offset);
-    ESP_GOTO_ON_FALSE(
-        cdc_dev->data.intf_desc,
-        ESP_ERR_NOT_FOUND, err, TAG, "Required interfece no %d was not found.", interface_num);
-    const int temp_offset = desc_offset; // Save this offset for later
-
-    // The interface can have 2-3 endpoints. 2 for data and 1 optional for notifications
-    const usb_ep_desc_t *in_ep = NULL;
-    const usb_ep_desc_t *out_ep = NULL;
-    const usb_ep_desc_t *notif_ep = NULL;
-    int ep_idx = 0;
-    if (cdc_dev->data.intf_desc->bNumEndpoints == 3) {
-        // Notification channel does not have its dedicated interface (data and notif interface is the same)
-        // First endpoint of this interface is used as notification channel
-        cdc_dev->notif.intf_desc = cdc_dev->data.intf_desc;
-        notif_ep = usb_parse_endpoint_descriptor_by_index(cdc_dev->data.intf_desc, 0, config_desc->wTotalLength, &desc_offset);
-        desc_offset = temp_offset;
-        ep_idx++;
-    }
-
-    for (int i = ep_idx; i < ep_idx + 2; i++) {
-        const usb_ep_desc_t *this_ep = usb_parse_endpoint_descriptor_by_index(cdc_dev->data.intf_desc, i, config_desc->wTotalLength, &desc_offset);
-        assert(this_ep);
-        if (USB_EP_DESC_GET_EP_DIR(this_ep)) {
-            in_ep = this_ep;
-        } else {
-            out_ep = this_ep;
-        }
-        desc_offset = temp_offset;
-    }
-
-    // Allocate USB transfers, claim CDC interfaces and return CDC-ACM handle
-    ESP_GOTO_ON_ERROR(cdc_acm_transfers_allocate(cdc_dev, notif_ep, in_ep, out_ep, dev_config->out_buffer_size), err, TAG, );
-    ESP_GOTO_ON_ERROR(cdc_acm_start(cdc_dev, dev_config->event_cb, dev_config->data_cb, dev_config->user_arg), err, TAG,);
-    *cdc_hdl_ret = (cdc_acm_dev_hdl_t)cdc_dev;
-    xSemaphoreGive(p_cdc_acm_obj->open_close_mutex);
-    return ESP_OK;
-err:
-    cdc_acm_device_remove(cdc_dev);
-exit:
-    xSemaphoreGive(p_cdc_acm_obj->open_close_mutex);
-    return ret;
-}
-
-esp_err_t cdc_acm_host_close(cdc_acm_dev_hdl_t cdc_hdl)
-{
-    CDC_ACM_CHECK(p_cdc_acm_obj, ESP_ERR_INVALID_STATE);
-    CDC_ACM_CHECK(cdc_hdl, ESP_ERR_INVALID_ARG);
-
-    xSemaphoreTake(p_cdc_acm_obj->open_close_mutex, portMAX_DELAY);
-
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)cdc_hdl;
-
-    // Cancel polling of BULK IN and INTERRUPT IN endpoints
-    cdc_dev->notif.cb = NULL;
-    cdc_dev->data.in_cb = NULL;
-    ESP_ERROR_CHECK(cdc_acm_reset_transfer_endpoint(cdc_dev->dev_hdl, cdc_dev->data.in_xfer));
-    if (cdc_dev->notif.intf_desc != NULL) {
-        ESP_ERROR_CHECK(cdc_acm_reset_transfer_endpoint(cdc_dev->dev_hdl, cdc_dev->notif.xfer));
-    }
-
-    // Release all interfaces
-    ESP_ERROR_CHECK(usb_host_interface_release(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl, cdc_dev->data.intf_desc->bInterfaceNumber));
-    if ((cdc_dev->notif.intf_desc != NULL) && (cdc_dev->notif.intf_desc != cdc_dev->data.intf_desc)) {
-        ESP_ERROR_CHECK(usb_host_interface_release(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->dev_hdl, cdc_dev->notif.intf_desc->bInterfaceNumber));
-    }
-
-    CDC_ACM_ENTER_CRITICAL();
-    SLIST_REMOVE(&p_cdc_acm_obj->cdc_devices_list, cdc_dev, cdc_dev_s, list_entry);
-    CDC_ACM_EXIT_CRITICAL();
-
-    cdc_acm_device_remove(cdc_dev);
-    xSemaphoreGive(p_cdc_acm_obj->open_close_mutex);
-    return ESP_OK;
-}
-
-/**
- * @brief Print CDC specific descriptor in human readable form
- *
- * This is a callback function that is called from USB Host library,
- * when it wants to print full configuration descriptor to stdout.
- *
- * @param[in] _desc CDC specific descriptor
- */
-static void cdc_acm_print_desc(const usb_standard_desc_t *_desc)
-{
-    if (_desc->bDescriptorType != ((USB_CLASS_COMM << 4) | USB_B_DESCRIPTOR_TYPE_INTERFACE ))
-    {
-        // Quietly return in case that this descriptor is not CDC interface descriptor
-        return;
-    }
-
-    switch (((cdc_header_desc_t *)_desc)->bDescriptorSubtype) {
-    case USB_CDC_DESC_SUBTYPE_HEADER: {
-        cdc_header_desc_t *desc = (cdc_header_desc_t *)_desc;
-        printf("\t*** CDC Header Descriptor ***\n");
-        printf("\tbcdCDC: %d.%d0\n", ((desc->bcdCDC >> 8) & 0xF), ((desc->bcdCDC >> 4) & 0xF));
-        break;
-    }
-    case USB_CDC_DESC_SUBTYPE_CALL: {
-        cdc_acm_call_desc_t *desc = (cdc_acm_call_desc_t *)_desc;
-        printf("\t*** CDC Call Descriptor ***\n");
-        printf("\tbmCapabilities: 0x%02X\n", desc->bmCapabilities.val);
-        printf("\tbDataInterface: %d\n", desc->bDataInterface);
-        break;
-    }
-    case USB_CDC_DESC_SUBTYPE_ACM: {
-        cdc_acm_acm_desc_t *desc = (cdc_acm_acm_desc_t *)_desc;
-        printf("\t*** CDC ACM Descriptor ***\n");
-        printf("\tbmCapabilities: 0x%02X\n", desc->bmCapabilities.val);
-        break;
-    }
-    case USB_CDC_DESC_SUBTYPE_UNION: {
-        cdc_union_desc_t *desc = (cdc_union_desc_t *)_desc;
-        printf("\t*** CDC Union Descriptor ***\n");
-        printf("\tbControlInterface: %d\n", desc->bControlInterface);
-        printf("\tbSubordinateInterface[0]: %d\n", desc->bSubordinateInterface[0]);
-        break;
-    }
-    default:
-        ESP_LOGW(TAG, "Unsupported CDC specific descriptor");
-        break;
-    }
-}
-
-void cdc_acm_host_desc_print(cdc_acm_dev_hdl_t cdc_hdl)
-{
-    assert(cdc_hdl);
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)cdc_hdl;
-
-    const usb_device_desc_t *device_desc;
-    const usb_config_desc_t *config_desc;
-    ESP_ERROR_CHECK_WITHOUT_ABORT(usb_host_get_device_descriptor(cdc_dev->dev_hdl, &device_desc));
-    ESP_ERROR_CHECK_WITHOUT_ABORT(usb_host_get_active_config_descriptor(cdc_dev->dev_hdl, &config_desc));
-    usb_print_device_descriptor(device_desc);
-    usb_print_config_descriptor(config_desc, cdc_acm_print_desc);
-}
-
-/**
- * @brief Check finished transfer status
- *
- * Return to on transfer completed OK.
- * Cancel the transfer and issue user's callback in case of an error.
- *
- * @param[in] transfer Transfer to be checked
- * @return true Transfer completed
- * @return false Transfer NOT completed
- */
-static bool cdc_acm_is_transfer_completed(usb_transfer_t *transfer)
-{
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)transfer->context;
-    bool completed = false;
-
-    switch (transfer->status) {
-    case USB_TRANSFER_STATUS_COMPLETED:
-        completed = true;
-        break;
-    case USB_TRANSFER_STATUS_NO_DEVICE: // User is notified about device disconnection from usb_event_cb
-    case USB_TRANSFER_STATUS_CANCELED:
-        break;
-    case USB_TRANSFER_STATUS_ERROR:
-    case USB_TRANSFER_STATUS_TIMED_OUT:
-    case USB_TRANSFER_STATUS_STALL:
-    case USB_TRANSFER_STATUS_OVERFLOW:
-    case USB_TRANSFER_STATUS_SKIPPED:
-    default:
-        // Transfer was not completed or cancelled by user. Inform user about this
-        if (cdc_dev->notif.cb) {
-            const cdc_acm_host_dev_event_data_t error_event = {
-                .type = CDC_ACM_HOST_ERROR,
-                .data.error = (int) transfer->status
-            };
-            cdc_dev->notif.cb(&error_event, cdc_dev->cb_arg);
-        }
-    }
-    return completed;
-}
-
-static void in_xfer_cb(usb_transfer_t *transfer)
-{
-    ESP_LOGD("CDC_ACM", "in xfer cb");
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)transfer->context;
-
-    if (cdc_acm_is_transfer_completed(transfer)) {
-        if (cdc_dev->data.in_cb) {
-            cdc_dev->data.in_cb(transfer->data_buffer, transfer->actual_num_bytes, cdc_dev->cb_arg);
-        }
-
-        ESP_LOGD("CDC_ACM", "Submitting poll for BULK IN transfer");
-        usb_host_transfer_submit(cdc_dev->data.in_xfer);
-    }
-}
-
-static void notif_xfer_cb(usb_transfer_t *transfer)
-{
-    ESP_LOGD("CDC_ACM", "notif xfer cb");
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)transfer->context;
-
-    if (cdc_acm_is_transfer_completed(transfer)) {
-        cdc_notification_t *notif = (cdc_notification_t *)transfer->data_buffer;
-        switch (notif->bNotificationCode) {
-        case USB_CDC_NOTIF_NETWORK_CONNECTION: {
-            if (cdc_dev->notif.cb) {
-                const cdc_acm_host_dev_event_data_t net_conn_event = {
-                    .type = CDC_ACM_HOST_NETWORK_CONNECTION,
-                    .data.network_connected = (bool) notif->wValue
-                };
-                cdc_dev->notif.cb(&net_conn_event, cdc_dev->cb_arg);
-            }
-            break;
-        }
-        case USB_CDC_NOTIF_SERIAL_STATE: {
-            cdc_dev->serial_state.val = *((uint16_t *)notif->Data);
-            if (cdc_dev->notif.cb) {
-                const cdc_acm_host_dev_event_data_t serial_state_event = {
-                    .type = CDC_ACM_HOST_SERIAL_STATE,
-                    .data.serial_state = cdc_dev->serial_state
-                };
-                cdc_dev->notif.cb(&serial_state_event, cdc_dev->cb_arg);
-            }
-            break;
-        }
-        case USB_CDC_NOTIF_RESPONSE_AVAILABLE: // Encapsulated commands not implemented - fallthrough
-        default:
-            ESP_LOGW("CDC_ACM", "Unsupported notification type 0x%02X", notif->bNotificationCode);
-            ESP_LOG_BUFFER_HEX("CDC_ACM", transfer->data_buffer, transfer->actual_num_bytes);
-            break;
-        }
-
-        // Start polling for new data again
-        ESP_LOGD("CDC_ACM", "Submitting poll for INTR IN transfer");
-        usb_host_transfer_submit(cdc_dev->notif.xfer);
-    }
-}
-
-static void out_xfer_cb(usb_transfer_t *transfer)
-{
-    ESP_LOGD("CDC_ACM", "out/ctrl xfer cb");
-    assert(transfer->context);
-    xSemaphoreGive((SemaphoreHandle_t)transfer->context);
-}
-
-static void usb_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg)
-{
-    switch (event_msg->event) {
-    case USB_HOST_CLIENT_EVENT_NEW_DEV:
-        ESP_LOGD(TAG, "New device connected");
-        if (p_cdc_acm_obj->new_dev_cb) {
-            usb_device_handle_t new_dev;
-            if (usb_host_device_open(p_cdc_acm_obj->cdc_acm_client_hdl, event_msg->new_dev.address, &new_dev) != ESP_OK) {
-                ESP_LOGW(TAG, "Couldn't open the new device");
-                break;
-            }
-            assert(new_dev);
-            p_cdc_acm_obj->new_dev_cb(new_dev);
-            usb_host_device_close(p_cdc_acm_obj->cdc_acm_client_hdl, new_dev);
-        }
-        break;
-    case USB_HOST_CLIENT_EVENT_DEV_GONE: {
-        ESP_LOGD(TAG, "Device suddenly disconnected");
-        // Find CDC pseudo-devices associated with this USB device and close them
-        cdc_dev_t *cdc_dev;
-        cdc_dev_t *tcdc_dev;
-        // We are using 'SAFE' version of 'SLIST_FOREACH' which enables user to close the disconnected device in the callback
-        SLIST_FOREACH_SAFE(cdc_dev, &p_cdc_acm_obj->cdc_devices_list, list_entry, tcdc_dev) {
-            if (cdc_dev->dev_hdl == event_msg->dev_gone.dev_hdl && cdc_dev->notif.cb) {
-                // The suddenly disconnected device was opened by this driver: inform user about this
-                const cdc_acm_host_dev_event_data_t disconn_event = {
-                    .type = CDC_ACM_HOST_DEVICE_DISCONNECTED,
-                    .data.cdc_hdl = (cdc_acm_dev_hdl_t) cdc_dev,
-                };
-                cdc_dev->notif.cb(&disconn_event, cdc_dev->cb_arg);
-            }
-        }
-        break;
-    }
-    default:
-        assert(false);
-        break;
-    }
-}
-
-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)
-{
-    esp_err_t ret;
-    CDC_ACM_CHECK(cdc_hdl, ESP_ERR_INVALID_ARG);
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)cdc_hdl;
-    CDC_ACM_CHECK(data && (data_len > 0), ESP_ERR_INVALID_ARG);
-    CDC_ACM_CHECK(cdc_dev->data.out_xfer, ESP_ERR_NOT_SUPPORTED); // Device was opened as read-only.
-    CDC_ACM_CHECK(data_len <= cdc_dev->data.out_xfer->data_buffer_size, ESP_ERR_INVALID_SIZE);
-
-    // Take OUT mutex and fill the OUT transfer
-    BaseType_t taken = xSemaphoreTake(cdc_dev->data.out_mux, pdMS_TO_TICKS(timeout_ms));
-    if (taken != pdTRUE) {
-        return ESP_ERR_TIMEOUT;
-    }
-
-    ESP_LOGD("CDC_ACM", "Submitting BULK OUT transfer");
-    memcpy(cdc_dev->data.out_xfer->data_buffer, data, data_len);
-    cdc_dev->data.out_xfer->num_bytes = data_len;
-    cdc_dev->data.out_xfer->timeout_ms = timeout_ms;
-    ESP_GOTO_ON_ERROR(usb_host_transfer_submit(cdc_dev->data.out_xfer), unblock, TAG,);
-
-    // Wait for OUT transfer completion
-    taken = xSemaphoreTake((SemaphoreHandle_t)cdc_dev->data.out_xfer->context, pdMS_TO_TICKS(timeout_ms));
-    if (!taken) {
-        // Reset the endpoint
-        cdc_acm_reset_transfer_endpoint(cdc_dev->dev_hdl, cdc_dev->data.out_xfer);
-        ret = ESP_ERR_TIMEOUT;
-        goto unblock;
-    }
-
-    ESP_GOTO_ON_FALSE(cdc_dev->data.out_xfer->status == USB_TRANSFER_STATUS_COMPLETED, ESP_ERR_INVALID_RESPONSE, unblock, TAG, "Bulk OUT transfer error");
-    ESP_GOTO_ON_FALSE(cdc_dev->data.out_xfer->actual_num_bytes == data_len, ESP_ERR_INVALID_RESPONSE, unblock, TAG, "Incorrect number of bytes transferred");
-    ret = ESP_OK;
-
-unblock:
-    xSemaphoreGive(cdc_dev->data.out_mux);
-    return ret;
-}
-
-esp_err_t cdc_acm_host_line_coding_get(cdc_acm_dev_hdl_t cdc_hdl, cdc_acm_line_coding_t *line_coding)
-{
-    CDC_ACM_CHECK(line_coding, ESP_ERR_INVALID_ARG);
-
-    ESP_RETURN_ON_ERROR(
-        send_cdc_request((cdc_dev_t *)cdc_hdl, true, USB_CDC_REQ_GET_LINE_CODING, (uint8_t *)line_coding, sizeof(cdc_acm_line_coding_t), 0),
-        TAG,);
-    ESP_LOGD(TAG, "Line Get: Rate: %d, Stop bits: %d, Parity: %d, Databits: %d", line_coding->dwDTERate,
-             line_coding->bCharFormat, line_coding->bParityType, line_coding->bDataBits);
-    return ESP_OK;
-}
-
-esp_err_t cdc_acm_host_line_coding_set(cdc_acm_dev_hdl_t cdc_hdl, const cdc_acm_line_coding_t *line_coding)
-{
-    CDC_ACM_CHECK(line_coding, ESP_ERR_INVALID_ARG);
-
-    ESP_RETURN_ON_ERROR(
-        send_cdc_request((cdc_dev_t *)cdc_hdl, false, USB_CDC_REQ_SET_LINE_CODING, (uint8_t *)line_coding, sizeof(cdc_acm_line_coding_t), 0),
-        TAG,);
-    ESP_LOGD(TAG, "Line Set: Rate: %d, Stop bits: %d, Parity: %d, Databits: %d", line_coding->dwDTERate,
-             line_coding->bCharFormat, line_coding->bParityType, line_coding->bDataBits);
-    return ESP_OK;
-}
-
-esp_err_t cdc_acm_host_set_control_line_state(cdc_acm_dev_hdl_t cdc_hdl, bool dtr, bool rts)
-{
-    const uint16_t ctrl_bitmap = (uint16_t)dtr | ((uint16_t)rts << 1);
-
-    ESP_RETURN_ON_ERROR(
-        send_cdc_request((cdc_dev_t *)cdc_hdl, false, USB_CDC_REQ_SET_CONTROL_LINE_STATE, NULL, 0, ctrl_bitmap),
-        TAG,);
-    ESP_LOGD(TAG, "Control Line Set: DTR: %d, RTS: %d", dtr, rts);
-    return ESP_OK;
-}
-
-esp_err_t cdc_acm_host_send_break(cdc_acm_dev_hdl_t cdc_hdl, uint16_t duration_ms)
-{
-    ESP_RETURN_ON_ERROR(
-        send_cdc_request((cdc_dev_t *)cdc_hdl, false, USB_CDC_REQ_SEND_BREAK, NULL, 0, duration_ms),
-        TAG,);
-
-    // Block until break is deasserted
-    vTaskDelay(pdMS_TO_TICKS(duration_ms + 1));
-    return ESP_OK;
-}
-
-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)
-{
-    CDC_ACM_CHECK(cdc_hdl, ESP_ERR_INVALID_ARG);
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)cdc_hdl;
-    if (wLength > 0) {
-        CDC_ACM_CHECK(data, ESP_ERR_INVALID_ARG);
-    }
-    CDC_ACM_CHECK(cdc_dev->ctrl_transfer->data_buffer_size >= wLength, ESP_ERR_INVALID_SIZE);
-
-    esp_err_t ret;
-
-    // Take Mutex and fill the CTRL request
-    BaseType_t taken = xSemaphoreTake(cdc_dev->ctrl_mux, pdMS_TO_TICKS(5000));
-    if (!taken) {
-        return ESP_ERR_TIMEOUT;
-    }
-    usb_setup_packet_t *req = (usb_setup_packet_t *)(cdc_dev->ctrl_transfer->data_buffer);
-    uint8_t *start_of_data = (uint8_t *)req + sizeof(usb_setup_packet_t);
-    req->bmRequestType = bmRequestType;
-    req->bRequest = bRequest;
-    req->wValue = wValue;
-    req->wIndex = wIndex;
-    req->wLength = wLength;
-
-    // For IN transfers we must transfer data ownership to CDC driver
-    const bool in_transfer = bmRequestType & USB_BM_REQUEST_TYPE_DIR_IN;
-    if (!in_transfer) {
-        memcpy(start_of_data, data, wLength);
-    }
-
-    cdc_dev->ctrl_transfer->num_bytes = wLength + sizeof(usb_setup_packet_t);
-    ESP_GOTO_ON_ERROR(
-        usb_host_transfer_submit_control(p_cdc_acm_obj->cdc_acm_client_hdl, cdc_dev->ctrl_transfer),
-        unblock, TAG, "CTRL transfer failed");
-
-    taken = xSemaphoreTake((SemaphoreHandle_t)cdc_dev->ctrl_transfer->context, pdMS_TO_TICKS(5000)); // This is a fixed timeout. Every CDC device should be able to respond to CTRL transfer in 5 seconds
-    if (!taken) {
-        // Transfer was not finished, error in USB LIB. Reset the endpoint
-        cdc_acm_reset_transfer_endpoint(cdc_dev->dev_hdl, cdc_dev->ctrl_transfer);
-        ret = ESP_ERR_TIMEOUT;
-        goto unblock;
-    }
-
-    ESP_GOTO_ON_FALSE(cdc_dev->ctrl_transfer->status == USB_TRANSFER_STATUS_COMPLETED, ESP_ERR_INVALID_RESPONSE, unblock, TAG, "Control transfer error");
-    ESP_GOTO_ON_FALSE(cdc_dev->ctrl_transfer->actual_num_bytes == cdc_dev->ctrl_transfer->num_bytes, ESP_ERR_INVALID_RESPONSE, unblock, TAG, "Incorrect number of bytes transferred");
-
-    // For OUT transfers, we must transfer data ownership to user
-    if (in_transfer) {
-        memcpy(data, start_of_data, wLength);
-    }
-    ret = ESP_OK;
-
-unblock:
-    xSemaphoreGive(cdc_dev->ctrl_mux);
-    return ret;
-}
-
-static esp_err_t send_cdc_request(cdc_dev_t *cdc_dev, bool in_transfer, cdc_request_code_t request, uint8_t *data, uint16_t data_len, uint16_t value)
-{
-    CDC_ACM_CHECK(cdc_dev, ESP_ERR_INVALID_ARG);
-    CDC_ACM_CHECK(cdc_dev->notif.intf_desc, ESP_ERR_NOT_SUPPORTED);
-
-    uint8_t req_type = USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE;
-    if (in_transfer) {
-        req_type |= USB_BM_REQUEST_TYPE_DIR_IN;
-    } else {
-        req_type |= USB_BM_REQUEST_TYPE_DIR_OUT;
-    }
-    return cdc_acm_host_send_custom_request((cdc_acm_dev_hdl_t) cdc_dev, req_type, request, value, cdc_dev->notif.intf_desc->bInterfaceNumber, data_len, data);
-}
-
-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)
-{
-    CDC_ACM_CHECK(cdc_hdl, ESP_ERR_INVALID_ARG);
-    cdc_dev_t *cdc_dev = (cdc_dev_t *)cdc_hdl;
-
-    if (comm != NULL) *comm = cdc_dev->comm_protocol;
-    if (data != NULL) *data = cdc_dev->data_protocol;
-    return ESP_OK;
-}

+ 0 - 343
examples/peripherals/usb/host/cdc/common/cdc_acm_host/include/usb/cdc_acm_host.h

@@ -1,343 +0,0 @@
-/*
- * 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){};
-    ~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()
-    {
-        esp_err_t err = cdc_acm_host_close(this->cdc_hdl);
-        if (err == ESP_OK) {
-            this->cdc_hdl = NULL;
-        }
-        return err;
-    }
-
-    inline esp_err_t line_coding_get(cdc_acm_line_coding_t *line_coding)
-    {
-        return cdc_acm_host_line_coding_get(this->cdc_hdl, line_coding);
-    }
-
-    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);
-    }
-
-    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);
-    }
-
-    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(const CdcAcmDevice &Copy);
-    CdcAcmDevice &operator= (const CdcAcmDevice &Copy);
-    bool operator== (const CdcAcmDevice &param) const;
-    bool operator!= (const CdcAcmDevice &param) const;
-    cdc_acm_dev_hdl_t cdc_hdl;
-};
-#endif

+ 0 - 206
examples/peripherals/usb/host/cdc/common/cdc_acm_host/include/usb/usb_types_cdc.h

@@ -1,206 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-#include <inttypes.h>
-
-/**
- * @brief USB CDC Descriptor Subtypes
- *
- * @see Table 13, USB CDC specification rev. 1.2
- */
-typedef enum {
-    USB_CDC_DESC_SUBTYPE_HEADER = 0x00,             // Header Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_CALL = 0x01,               // Call Management Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_ACM = 0x02,                // Abstract Control Management Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_DLM = 0x03,                // Direct Line Management Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_TEL_RINGER = 0x04,         // Telephone Ringer Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_TEL_CLSR = 0x05,           // Telephone Call and Line State Reporting Capabilities Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_UNION = 0x06,              // Union Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_COUNTRY = 0x07,            // Country Selection Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_TEL_MODE = 0x08,           // Telephone Operational Modes Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_TERMINAL = 0x09,           // USB Terminal
-    USB_CDC_DESC_SUBTYPE_NCHT = 0x0A,               // Network Channel Terminal
-    USB_CDC_DESC_SUBTYPE_PROTOCOL = 0x08,           // Protocol Unit
-    USB_CDC_DESC_SUBTYPE_EXTENSION = 0x0C,          // Extension Unit
-    USB_CDC_DESC_SUBTYPE_MULTI_CHAN = 0x0D,         // Multi-Channel Management Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_CAPI = 0x0E,               // CAPI Control
-    USB_CDC_DESC_SUBTYPE_ETH = 0x0F,                // Ethernet Networking
-    USB_CDC_DESC_SUBTYPE_ATM = 0x10,                // ATM Networking
-    USB_CDC_DESC_SUBTYPE_WHANDSET = 0x11,           // Wireless Handset Control Model Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_MDLM = 0x12,               // Mobile Direct Line Model
-    USB_CDC_DESC_SUBTYPE_MDLM_DETAIL = 0x13,        // MDLM Detail
-    USB_CDC_DESC_SUBTYPE_DMM = 0x14,                // Device Management Model
-    USB_CDC_DESC_SUBTYPE_OBEX = 0x15,               // OBEX Functional
-    USB_CDC_DESC_SUBTYPE_COMMAND_SET = 0x16,        // Command Set
-    USB_CDC_DESC_SUBTYPE_COMMAND_SET_DETAIL = 0x17, // Command Set Detail Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_TEL_CM = 0x18,             // Telephone Control Model Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_OBEX_SERVICE = 0x19,       // OBEX Service Identifier Functional Descriptor
-    USB_CDC_DESC_SUBTYPE_NCM = 0x1A                 // NCM Functional Descriptor
-} __attribute__((packed)) cdc_desc_subtype_t;
-
-/**
- * @brief USB CDC Subclass codes
- *
- * @see Table 4, USB CDC specification rev. 1.2
- */
-typedef enum {
-    USB_CDC_SUBCLASS_DLCM = 0x01,    // Direct Line Control Model
-    USB_CDC_SUBCLASS_ACM = 0x02,     // Abstract Control Model
-    USB_CDC_SUBCLASS_TCM = 0x03,     // Telephone Control Model
-    USB_CDC_SUBCLASS_MCHCM = 0x04,   // Multi-Channel Control Model
-    USB_CDC_SUBCLASS_CAPI = 0x05,    // CAPI Control Model
-    USB_CDC_SUBCLASS_ECM = 0x06,     // Ethernet Networking Control Model
-    USB_CDC_SUBCLASS_ATM = 0x07,     // ATM Networking Model
-    USB_CDC_SUBCLASS_HANDSET = 0x08, // Wireless Handset Control Model
-    USB_CDC_SUBCLASS_DEV_MAN = 0x09, // Device Management
-    USB_CDC_SUBCLASS_MOBILE = 0x0A,  // Mobile Direct Line Model
-    USB_CDC_SUBCLASS_OBEX = 0x0B,    // OBEX
-    USB_CDC_SUBCLASS_EEM = 0x0C,     // Ethernet Emulation Model
-    USB_CDC_SUBCLASS_NCM = 0x0D      // Network Control Model
-} __attribute__((packed)) cdc_subclass_t;
-
-/**
- * @brief USB CDC Communications Protocol Codes
- *
- * @see Table 5, USB CDC specification rev. 1.2
- */
-typedef enum {
-    USB_CDC_COMM_PROTOCOL_NONE = 0x00,   // No class specific protocol required
-    USB_CDC_COMM_PROTOCOL_V250 = 0x01,   // AT Commands: V.250 etc
-    USB_CDC_COMM_PROTOCOL_PCAA = 0x02,   // AT Commands defined by PCCA-101
-    USB_CDC_COMM_PROTOCOL_PCAA_A = 0x03, // AT Commands defined by PCAA-101 & Annex O
-    USB_CDC_COMM_PROTOCOL_GSM = 0x04,    // AT Commands defined by GSM 07.07
-    USB_CDC_COMM_PROTOCOL_3GPP = 0x05,   // AT Commands defined by 3GPP 27.007
-    USB_CDC_COMM_PROTOCOL_TIA = 0x06,    // AT Commands defined by TIA for CDMA
-    USB_CDC_COMM_PROTOCOL_EEM = 0x07,    // Ethernet Emulation Model
-    USB_CDC_COMM_PROTOCOL_EXT = 0xFE,    // External Protocol: Commands defined by Command Set Functional Descriptor
-    USB_CDC_COMM_PROTOCOL_VENDOR = 0xFF  // Vendor-specific
-} __attribute__((packed)) cdc_comm_protocol_t;
-
-/**
- * @brief USB CDC Data Protocol Codes
- *
- * @see Table 7, USB CDC specification rev. 1.2
- */
-typedef enum {
-    USB_CDC_DATA_PROTOCOL_NONE = 0x00,   // No class specific protocol required
-    USB_CDC_DATA_PROTOCOL_NCM = 0x01,    // Network Transfer Block
-    USB_CDC_DATA_PROTOCOL_I430 = 0x30,   // Physical interface protocol for ISDN BRI
-    USB_CDC_DATA_PROTOCOL_HDLC = 0x31,   // HDLC
-    USB_CDC_DATA_PROTOCOL_Q921M = 0x50,  // Management protocol for Q.921 data link protocol
-    USB_CDC_DATA_PROTOCOL_Q921  = 0x51,  // Data link protocol for Q.931
-    USB_CDC_DATA_PROTOCOL_Q921TM = 0x52, // TEI-multiplexor for Q.921 data link protocol
-    USB_CDC_DATA_PROTOCOL_V42BIS = 0x90, // Data compression procedures
-    USB_CDC_DATA_PROTOCOL_Q931 = 0x91,   // Euro-ISDN protocol control
-    USB_CDC_DATA_PROTOCOL_V120 = 0x92,   // V.24 rate adaptation to ISDN
-    USB_CDC_DATA_PROTOCOL_CAPI = 0x93,   // CAPI Commands
-    USB_CDC_DATA_PROTOCOL_VENDOR = 0xFF  // Vendor-specific
-} __attribute__((packed)) cdc_data_protocol_t;
-
-/**
- * @brief USB CDC Request Codes
- *
- * @see Table 19, USB CDC specification rev. 1.2
- */
-typedef enum {
-    USB_CDC_REQ_SEND_ENCAPSULATED_COMMAND = 0x00,
-    USB_CDC_REQ_GET_ENCAPSULATED_RESPONSE = 0x01,
-    USB_CDC_REQ_SET_COMM_FEATURE = 0x02,
-    USB_CDC_REQ_GET_COMM_FEATURE = 0x03,
-    USB_CDC_REQ_CLEAR_COMM_FEATURE = 0x04,
-    USB_CDC_REQ_SET_AUX_LINE_STATE = 0x10,
-    USB_CDC_REQ_SET_HOOK_STATE = 0x11,
-    USB_CDC_REQ_PULSE_SETUP = 0x12,
-    USB_CDC_REQ_SEND_PULSE = 0x13,
-    USB_CDC_REQ_SET_PULSE_TIME = 0x14,
-    USB_CDC_REQ_RING_AUX_JACK = 0x15,
-    USB_CDC_REQ_SET_LINE_CODING = 0x20,
-    USB_CDC_REQ_GET_LINE_CODING = 0x21,
-    USB_CDC_REQ_SET_CONTROL_LINE_STATE = 0x22,
-    USB_CDC_REQ_SEND_BREAK = 0x23,
-    USB_CDC_REQ_SET_RINGER_PARMS = 0x30,
-    USB_CDC_REQ_GET_RINGER_PARMS = 0x31,
-    USB_CDC_REQ_SET_OPERATION_PARMS = 0x32,
-    USB_CDC_REQ_GET_OPERATION_PARMS = 0x33,
-    USB_CDC_REQ_SET_LINE_PARMS = 0x34,
-    USB_CDC_REQ_GET_LINE_PARMS = 0x35,
-    USB_CDC_REQ_DIAL_DIGITS = 0x36,
-    USB_CDC_REQ_SET_UNIT_PARAMETER = 0x37,
-    USB_CDC_REQ_GET_UNIT_PARAMETER = 0x38,
-    USB_CDC_REQ_CLEAR_UNIT_PARAMETER = 0x39,
-    USB_CDC_REQ_GET_PROFILE = 0x3A,
-    USB_CDC_REQ_SET_ETHERNET_MULTICAST_FILTERS = 0x40,
-    USB_CDC_REQ_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
-    USB_CDC_REQ_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
-    USB_CDC_REQ_SET_ETHERNET_PACKET_FILTER = 0x43,
-    USB_CDC_REQ_GET_ETHERNET_STATISTIC = 0x44,
-    USB_CDC_REQ_SET_ATM_DATA_FORMAT = 0x50,
-    USB_CDC_REQ_GET_ATM_DEVICE_STATISTICS = 0x51,
-    USB_CDC_REQ_SET_ATM_DEFAULT_VC = 0x52,
-    USB_CDC_REQ_GET_ATM_VC_STATISTICS = 0x53,
-    USB_CDC_REQ_GET_NTB_PARAMETERS = 0x80,
-    USB_CDC_REQ_GET_NET_ADDRESS = 0x81,
-    USB_CDC_REQ_SET_NET_ADDRESS = 0x82,
-    USB_CDC_REQ_GET_NTB_FORMAT = 0x83,
-    USB_CDC_REQ_SET_NTB_FORMAT = 0x84,
-    USB_CDC_REQ_GET_NTB_INPUT_SIZE = 0x85,
-    USB_CDC_REQ_SET_NTB_INPUT_SIZE = 0x86,
-    USB_CDC_REQ_GET_MAX_DATAGRAM_SIZE = 0x87,
-    USB_CDC_REQ_SET_MAX_DATAGRAM_SIZE = 0x88,
-    USB_CDC_REQ_GET_CRC_MODE = 0x89,
-    USB_CDC_REQ_SET_CRC_MODE = 0x8A
-} __attribute__((packed)) cdc_request_code_t;
-
-/**
- * @brief USB CDC Notification Codes
- *
- * @see Table 20, USB CDC specification rev. 1.2
- */
-typedef enum {
-    USB_CDC_NOTIF_NETWORK_CONNECTION = 0x00,
-    USB_CDC_NOTIF_RESPONSE_AVAILABLE = 0x01,
-    USB_CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08,
-    USB_CDC_NOTIF_RING_DETECT = 0x09,
-    USB_CDC_NOTIF_SERIAL_STATE = 0x20,
-    USB_CDC_NOTIF_CALL_STATE_CHANGE = 0x28,
-    USB_CDC_NOTIF_LINE_STATE_CHANGE = 0x29,
-    USB_CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A
-} __attribute__((packed)) cdc_notification_code_t;
-
-typedef struct {
-    uint8_t bmRequestType;
-    cdc_notification_code_t bNotificationCode;
-    uint16_t wValue;
-    uint16_t wIndex;
-    uint16_t wLength;
-    uint8_t Data[];
-} __attribute__((packed)) cdc_notification_t;
-
-/**
- * @brief USB CDC Header Functional Descriptor
- *
- * @see Table 15, USB CDC specification rev. 1.2
- */
-typedef struct {
-    uint8_t bFunctionLength;
-    const uint8_t bDescriptorType; // Upper nibble: CDC code 0x02, Lower nibble: intf/ep descriptor type 0x04/0x05
-    const cdc_desc_subtype_t bDescriptorSubtype;
-    uint16_t bcdCDC; // CDC version as binary-coded decimal. This driver is written for version 1.2
-} __attribute__((packed)) cdc_header_desc_t;
-
-/**
- * @brief USB CDC Union Functional Descriptor
- *
- * @see Table 16, USB CDC specification rev. 1.2
- */
-typedef struct {
-    uint8_t bFunctionLength;
-    const uint8_t bDescriptorType; // Upper nibble: CDC code 0x02, Lower nibble: intf/ep descriptor type 0x04/0x05
-    const cdc_desc_subtype_t bDescriptorSubtype;
-    const uint8_t bControlInterface; // Master/controlling interface
-    uint8_t bSubordinateInterface[]; // Slave/subordinate interfaces
-} __attribute__((packed)) cdc_union_desc_t;

+ 0 - 3
examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/CMakeLists.txt

@@ -1,3 +0,0 @@
-idf_component_register(SRCS "test_cdc_acm_host.c" "usb_device.c"
-                       INCLUDE_DIRS "."
-                       REQUIRES cdc_acm_host tinyusb unity)

+ 0 - 447
examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/test_cdc_acm_host.c

@@ -1,447 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#include "soc/soc_caps.h"
-#if SOC_USB_OTG_SUPPORTED
-
-#include <stdio.h>
-#include "esp_system.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "esp_log.h"
-#include "esp_err.h"
-
-#include "esp_private/usb_phy.h"
-#include "usb/usb_host.h"
-#include "usb/cdc_acm_host.h"
-#include <string.h>
-
-#include "esp_intr_alloc.h"
-
-#include "unity.h"
-#include "soc/usb_wrap_struct.h"
-
-static uint8_t tx_buf[] = "HELLO";
-static uint8_t tx_buf2[] = "WORLD";
-static int nb_of_responses;
-static int nb_of_responses2;
-static usb_phy_handle_t phy_hdl = NULL;
-
-static void force_conn_state(bool connected, TickType_t delay_ticks)
-{
-    TEST_ASSERT_NOT_EQUAL(NULL, phy_hdl);
-    if (delay_ticks > 0) {
-        //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0.
-        vTaskDelay(delay_ticks);
-    }
-    ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN));
-}
-
-void usb_lib_task(void *arg)
-{
-    // Initialize the internal USB PHY to connect to the USB OTG peripheral. We manually install the USB PHY for testing
-    usb_phy_config_t phy_config = {
-        .controller = USB_PHY_CTRL_OTG,
-        .target = USB_PHY_TARGET_INT,
-        .otg_mode = USB_OTG_MODE_HOST,
-        .otg_speed = USB_PHY_SPEED_UNDEFINED,   //In Host mode, the speed is determined by the connected device
-        .gpio_conf = NULL,
-    };
-    TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_hdl));
-    // Install USB Host driver. Should only be called once in entire application
-    const usb_host_config_t host_config = {
-        .skip_phy_setup = true,
-        .intr_flags = ESP_INTR_FLAG_LEVEL1,
-    };
-    TEST_ASSERT_EQUAL(ESP_OK, usb_host_install(&host_config));
-    printf("USB Host installed\n");
-    xTaskNotifyGive(arg);
-
-    bool all_clients_gone = false;
-    bool all_dev_free = false;
-    while (!all_clients_gone || !all_dev_free) {
-        // Start handling system events
-        uint32_t event_flags;
-        usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
-        if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
-            printf("No more clients\n");
-            usb_host_device_free_all();
-            all_clients_gone = true;
-        }
-        if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
-            printf("All devices freed\n");
-            all_dev_free = true;
-        }
-    }
-
-    // Clean up USB Host
-    vTaskDelay(10); // Short delay to allow clients clean-up
-    TEST_ASSERT_EQUAL(ESP_OK, usb_host_uninstall());
-    TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_hdl)); //Tear down USB PHY
-    phy_hdl = NULL;
-    vTaskDelete(NULL);
-}
-
-void test_install_cdc_driver(void)
-{
-    // Create a task that will handle USB library events
-    TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(usb_lib_task, "usb_lib", 4*4096, xTaskGetCurrentTaskHandle(), 10, NULL, 0));
-    ulTaskNotifyTake(false, 1000);
-
-    printf("Installing CDC-ACM driver\n");
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_install(NULL));
-}
-
-/* ------------------------------- Callbacks -------------------------------- */
-static void handle_rx(uint8_t *data, size_t data_len, void *arg)
-{
-    printf("Data received\n");
-    nb_of_responses++;
-    TEST_ASSERT_EQUAL_STRING_LEN(data, arg, data_len);
-}
-
-static void handle_rx2(uint8_t *data, size_t data_len, void *arg)
-{
-    printf("Data received 2\n");
-    nb_of_responses2++;
-    TEST_ASSERT_EQUAL_STRING_LEN(data, arg, data_len);
-}
-
-static void notif_cb(const cdc_acm_host_dev_event_data_t *event, void *user_ctx)
-{
-    switch (event->type) {
-    case CDC_ACM_HOST_ERROR:
-        printf("Error event %d\n", event->data.error);
-        break;
-    case CDC_ACM_HOST_SERIAL_STATE:
-        break;
-    case CDC_ACM_HOST_NETWORK_CONNECTION:
-        break;
-    case CDC_ACM_HOST_DEVICE_DISCONNECTED:
-        printf("Disconnection event\n");
-        TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(event->data.cdc_hdl));
-        xTaskNotifyGive(user_ctx);
-        break;
-    default:
-        assert(false);
-    }
-}
-
-static bool new_dev_cb_called = false;
-static void new_dev_cb(usb_device_handle_t usb_dev) {
-    new_dev_cb_called = true;
-    const usb_config_desc_t *config_desc;
-    const usb_device_desc_t *device_desc;
-
-    // Get descriptors
-    TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(usb_dev, &device_desc));
-    TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_active_config_descriptor(usb_dev, &config_desc));
-
-    printf("New device connected. VID = 0x%04X PID = %04X\n", device_desc->idVendor, device_desc->idProduct);
-}
-
-/* Basic test to check CDC communication:
- * open/read/write/close device
- * CDC-ACM specific commands: set/get_line_coding, set_control_line_state */
-TEST_CASE("read_write", "[cdc_acm]")
-{
-    nb_of_responses = 0;
-    cdc_acm_dev_hdl_t cdc_dev = NULL;
-
-    test_install_cdc_driver();
-
-    const cdc_acm_host_device_config_t dev_config = {
-        .connection_timeout_ms = 500,
-        .out_buffer_size = 64,
-        .event_cb = notif_cb,
-        .data_cb = handle_rx,
-        .user_arg = tx_buf,
-    };
-
-    printf("Opening CDC-ACM device\n");
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev)); // 0x303A:0x4002 (TinyUSB Dual CDC device)
-    TEST_ASSERT_NOT_NULL(cdc_dev);
-    cdc_acm_host_desc_print(cdc_dev);
-    vTaskDelay(100);
-
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_data_tx_blocking(cdc_dev, tx_buf, sizeof(tx_buf), 1000));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_data_tx_blocking(cdc_dev, tx_buf, sizeof(tx_buf), 1000));
-    vTaskDelay(100); // Wait until responses are processed
-
-    // We sent two messages, should get two responses
-    TEST_ASSERT_EQUAL(2, nb_of_responses);
-
-    cdc_acm_line_coding_t line_coding_get;
-    const cdc_acm_line_coding_t line_coding_set = {
-     .dwDTERate = 9600,
-     .bDataBits = 7,
-     .bParityType = 1,
-     .bCharFormat = 1,
-    };
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_line_coding_set(cdc_dev, &line_coding_set));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_line_coding_get(cdc_dev, &line_coding_get));
-    TEST_ASSERT_EQUAL_MEMORY(&line_coding_set, &line_coding_get, sizeof(cdc_acm_line_coding_t));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_set_control_line_state(cdc_dev, true, false));
-
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-
-    vTaskDelay(20); //Short delay to allow task to be cleaned up
-}
-
-/* Test communication with multiple CDC-ACM devices from one thread */
-TEST_CASE("multiple_devices", "[cdc_acm]")
-{
-    nb_of_responses = 0;
-    nb_of_responses2 = 0;
-
-    test_install_cdc_driver();
-
-    printf("Opening 2 CDC-ACM devices\n");
-    cdc_acm_dev_hdl_t cdc_dev1, cdc_dev2;
-    cdc_acm_host_device_config_t dev_config = {
-        .connection_timeout_ms = 1000,
-        .out_buffer_size = 64,
-        .event_cb = notif_cb,
-        .data_cb = handle_rx,
-        .user_arg = tx_buf,
-    };
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev1)); // 0x303A:0x4002 (TinyUSB Dual CDC device)
-    dev_config.data_cb = handle_rx2;
-    dev_config.user_arg = tx_buf2;
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 2, &dev_config, &cdc_dev2)); // 0x303A:0x4002 (TinyUSB Dual CDC device)
-    TEST_ASSERT_NOT_NULL(cdc_dev1);
-    TEST_ASSERT_NOT_NULL(cdc_dev2);
-
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_data_tx_blocking(cdc_dev1, tx_buf, sizeof(tx_buf), 1000));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_data_tx_blocking(cdc_dev2, tx_buf2, sizeof(tx_buf2), 1000));
-
-    vTaskDelay(100); // Wait for RX callbacks
-
-    // We sent two messages, should get two responses
-    TEST_ASSERT_EQUAL(1, nb_of_responses);
-    TEST_ASSERT_EQUAL(1, nb_of_responses2);
-
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev1));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev2));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-
-    //Short delay to allow task to be cleaned up
-    vTaskDelay(20);
-}
-
-#define MULTIPLE_THREADS_TRANSFERS_NUM 5
-#define MULTIPLE_THREADS_TASKS_NUM 4
-void tx_task(void *arg)
-{
-    cdc_acm_dev_hdl_t cdc_dev = (cdc_acm_dev_hdl_t) arg;
-    // Send multiple transfers to make sure that some of them will run at the same time
-    for (int i = 0; i < MULTIPLE_THREADS_TRANSFERS_NUM; i++) {
-        // BULK endpoints
-        TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_data_tx_blocking(cdc_dev, tx_buf, sizeof(tx_buf), 1000));
-
-        // CTRL endpoints
-        cdc_acm_line_coding_t line_coding_get;
-        TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_line_coding_get(cdc_dev, &line_coding_get));
-        TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_set_control_line_state(cdc_dev, true, false));
-    }
-    vTaskDelete(NULL);
-}
-
-/**
- * @brief Multiple threads test
- *
- * In this test, one CDC device is accessed from multiple threads.
- * It has to be opened/closed just once, though.
- */
-TEST_CASE("multiple_threads", "[cdc_acm]")
-{
-    nb_of_responses = 0;
-    cdc_acm_dev_hdl_t cdc_dev;
-    test_install_cdc_driver();
-
-    const cdc_acm_host_device_config_t dev_config = {
-        .connection_timeout_ms = 5000,
-        .out_buffer_size = 64,
-        .event_cb = notif_cb,
-        .data_cb = handle_rx,
-        .user_arg = tx_buf,
-    };
-
-    printf("Opening CDC-ACM device\n");
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev)); // 0x303A:0x4002 (TinyUSB Dual CDC device)
-    TEST_ASSERT_NOT_NULL(cdc_dev);
-
-    // Create two tasks that will try to access cdc_dev
-    for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
-        TEST_ASSERT_EQUAL(pdTRUE, xTaskCreate(tx_task, "CDC TX", 4096, cdc_dev, i + 3, NULL));
-    }
-
-    // Wait until all tasks finish
-    vTaskDelay(pdMS_TO_TICKS(500));
-    TEST_ASSERT_EQUAL(MULTIPLE_THREADS_TASKS_NUM * MULTIPLE_THREADS_TRANSFERS_NUM, nb_of_responses);
-
-    // Clean-up
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-    vTaskDelay(20);
-}
-
-/* Test CDC driver reaction to USB device sudden disconnection */
-TEST_CASE("sudden_disconnection", "[cdc_acm]")
-{
-    test_install_cdc_driver();
-
-    cdc_acm_dev_hdl_t cdc_dev;
-    cdc_acm_host_device_config_t dev_config = {
-        .connection_timeout_ms = 1000,
-        .out_buffer_size = 64,
-        .event_cb = notif_cb,
-        .data_cb = handle_rx
-    };
-    dev_config.user_arg = xTaskGetCurrentTaskHandle();
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev));
-    TEST_ASSERT_NOT_NULL(cdc_dev);
-
-    force_conn_state(false, pdMS_TO_TICKS(10));                        // Simulate device disconnection
-    TEST_ASSERT_EQUAL(1, ulTaskNotifyTake(false, pdMS_TO_TICKS(100))); // Notify will succeed only if CDC_ACM_HOST_DEVICE_DISCONNECTED notification was generated
-
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-    vTaskDelay(20); //Short delay to allow task to be cleaned up
-}
-
-/**
- * @brief CDC-ACM error handling test
- *
- * There are multiple erroneous scenarios checked in this test:
- *
- * -# Install CDC-ACM driver without USB Host
- * -# Open device without installed driver
- * -# Uninstall driver before installing it
- * -# Open non-existent device
- * -# Open the same device twice
- * -# Uninstall driver with open devices
- * -# Send data that is too large
- * -# Send unsupported CDC request
- * -# Write to read-only device
- */
-TEST_CASE("error_handling", "[cdc_acm]")
-{
-    cdc_acm_dev_hdl_t cdc_dev;
-    cdc_acm_host_device_config_t dev_config = {
-        .connection_timeout_ms = 500,
-        .out_buffer_size = 64,
-        .event_cb = notif_cb,
-        .data_cb = handle_rx
-    };
-
-    // Install CDC-ACM driver without USB Host
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, cdc_acm_host_install(NULL));
-
-    // Open device without installed driver
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev));
-
-    // Uninstall driver before installing it
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, cdc_acm_host_uninstall());
-
-    // Properly install USB and CDC drivers
-    test_install_cdc_driver();
-
-    // Open non-existent device
-    TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, cdc_acm_host_open(0x303A, 0x1234, 0, &dev_config, &cdc_dev)); // 0x303A:0x1234 this device is not connected to USB Host
-    TEST_ASSERT_NULL(cdc_dev);
-
-    // Open regular device
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev));
-    TEST_ASSERT_NOT_NULL(cdc_dev);
-
-    // Open one CDC-ACM device twice
-    cdc_acm_dev_hdl_t cdc_dev_test;
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev_test));
-    TEST_ASSERT_NULL(cdc_dev_test);
-
-    // Uninstall driver with open devices
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, cdc_acm_host_uninstall());
-
-    // Send data that is too large and NULL data
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, cdc_acm_host_data_tx_blocking(cdc_dev, tx_buf, 1024, 1000));
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, cdc_acm_host_data_tx_blocking(cdc_dev, NULL, 10, 1000));
-
-    // Change mode to read-only and try to write to it
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev));
-    dev_config.out_buffer_size = 0; // Read-only device
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev));
-    TEST_ASSERT_NOT_NULL(cdc_dev);
-    TEST_ASSERT_EQUAL(ESP_ERR_NOT_SUPPORTED, cdc_acm_host_data_tx_blocking(cdc_dev, tx_buf, sizeof(tx_buf), 1000));
-
-    // Send unsupported CDC request (TinyUSB accepts SendBreak command, eventhough it doesn't support it)
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_send_break(cdc_dev, 100));
-
-    // Clean-up
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-    vTaskDelay(20);
-}
-
-TEST_CASE("custom_command", "[cdc_acm]")
-{
-    test_install_cdc_driver();
-
-    // Open device with only CTRL endpoint (endpoint no 0)
-    cdc_acm_dev_hdl_t cdc_dev;
-    const cdc_acm_host_device_config_t dev_config = {
-        .connection_timeout_ms = 500,
-        .out_buffer_size = 0,
-        .event_cb = notif_cb,
-        .data_cb = NULL
-    };
-
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev));
-    TEST_ASSERT_NOT_NULL(cdc_dev);
-
-    // Corresponds to command: Set Control Line State, DTR on, RTS off
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_send_custom_request(cdc_dev, 0x21, 34, 1, 0, 0, NULL));
-
-    // Clean-up
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_close(cdc_dev));
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-    vTaskDelay(20);
-}
-
-TEST_CASE("new_device_connection", "[cdc_acm]")
-{
-    // Create a task that will handle USB library events
-    TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(usb_lib_task, "usb_lib", 4*4096, xTaskGetCurrentTaskHandle(), 10, NULL, 0));
-    ulTaskNotifyTake(false, 1000);
-
-    printf("Installing CDC-ACM driver\n");
-    const cdc_acm_host_driver_config_t driver_config = {
-        .driver_task_priority = 11,
-        .driver_task_stack_size = 2048,
-        .xCoreID = 0,
-        .new_dev_cb = new_dev_cb,
-    };
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_install(&driver_config));
-
-    vTaskDelay(80);
-    TEST_ASSERT_TRUE_MESSAGE(new_dev_cb_called, "New device callback was not called\n");
-
-    // Clean-up
-    TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
-    vTaskDelay(20);
-}
-
-/* Following test case implements dual CDC-ACM USB device that can be used as mock device for CDC-ACM Host tests */
-void run_usb_dual_cdc_device(void);
-TEST_CASE("mock_device_app", "[cdc_acm_device][ignore]")
-{
-    run_usb_dual_cdc_device();
-    while (1) {
-        vTaskDelay(10);
-    }
-}
-
-#endif

+ 0 - 71
examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/usb_device.c

@@ -1,71 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#include <stdint.h>
-#include "sdkconfig.h"
-#include "tinyusb.h"
-#include "tusb_cdc_acm.h"
-
-static uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1];
-void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event)
-{
-    size_t rx_size = 0;
-    /* read and write back */
-    ESP_ERROR_CHECK(tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size));
-    tinyusb_cdcacm_write_queue(itf, buf, rx_size);
-    tinyusb_cdcacm_write_flush(itf, 0);
-}
-
-static const tusb_desc_device_t cdc_device_descriptor = {
-    .bLength = sizeof(cdc_device_descriptor),
-    .bDescriptorType = TUSB_DESC_DEVICE,
-    .bcdUSB = 0x0200,
-    .bDeviceClass = TUSB_CLASS_MISC,
-    .bDeviceSubClass = MISC_SUBCLASS_COMMON,
-    .bDeviceProtocol = MISC_PROTOCOL_IAD,
-    .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
-    .idVendor = USB_ESPRESSIF_VID,
-    .idProduct = 0x4002,
-    .bcdDevice = 0x0100,
-    .iManufacturer = 0x01,
-    .iProduct = 0x02,
-    .iSerialNumber = 0x03,
-    .bNumConfigurations = 0x01
-};
-
-const uint16_t cdc_desc_config_len = TUD_CONFIG_DESC_LEN + 2 * TUD_CDC_DESC_LEN;
-static const uint8_t cdc_desc_configuration[] = {
-    TUD_CONFIG_DESCRIPTOR(1, 4, 0, cdc_desc_config_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
-    TUD_CDC_DESCRIPTOR(0, 4, 0x81, 8, 0x02, 0x82, 64),
-    TUD_CDC_DESCRIPTOR(2, 4, 0x83, 8, 0x04, 0x84, 64),
-};
-
-void run_usb_dual_cdc_device(void)
-{
-    const tinyusb_config_t tusb_cfg = {
-        .device_descriptor = &cdc_device_descriptor,
-        .configuration_descriptor = cdc_desc_configuration
-    };
-    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
-
-    tinyusb_config_cdcacm_t acm_cfg = {
-        .usb_dev = TINYUSB_USBDEV_0,
-        .cdc_port = TINYUSB_CDC_ACM_0,
-        .rx_unread_buf_sz = 64,
-        .callback_rx = &tinyusb_cdc_rx_callback,
-        .callback_rx_wanted_char = NULL,
-        .callback_line_state_changed = NULL,
-        .callback_line_coding_changed = NULL
-    };
-
-    ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
-#if (CONFIG_TINYUSB_CDC_COUNT > 1)
-    acm_cfg.cdc_port = TINYUSB_CDC_ACM_1;
-    ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
-#endif
-
-    printf("USB initialization DONE\n");
-}

+ 0 - 9
examples/peripherals/usb/host/msc/components/msc/CMakeLists.txt

@@ -1,9 +0,0 @@
-set(sources src/msc_scsi_bot.c
-            src/diskio_usb.c
-            src/msc_host.c
-            src/msc_host_vfs.c)
-
-idf_component_register( SRCS ${sources}
-                        INCLUDE_DIRS include
-                        PRIV_INCLUDE_DIRS private_include
-                        REQUIRES usb fatfs vfs )

+ 0 - 32
examples/peripherals/usb/host/msc/components/msc/README.md

@@ -1,32 +0,0 @@
-# USB Host MSC (Mass Storage Class) Driver
-
-This directory contains an implementation of a USB Mass Storage Class Driver implemented on top of the [USB Host Library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_host.html).
-
-MSC driver allows access to USB flash drivers using the BOT “Bulk-Only Transport” protocol and the Transparent SCSI command set.
-
-## Usage
-
-- First, usb host library has to be initialized by calling `usb_host_install`
-- USB Host Library events have to be handled by invoking `usb_host_lib_handle_events` periodically.
-  In general, an application should spawn a dedicated task handle USB Host Library events.
-  However, in order to save RAM, an already existing task can also be used to call `usb_host_lib_handle_events`.
-- Mass Storage Class driver is installed by calling `usb_msc_install` function along side with configuration.
-- Supplied configuration contains user provided callback function invoked whenever MSC device is connected/disconnected
-  and optional parameters for creating background task handling MSC related events. 
-  Alternatively, user can call `usb_msc_handle_events` function from already existing task.
-- After receiving `MSC_DEVICE_CONNECTED` event, user has to install device with `usb_msc_install_device` function,
-  obtaining MSC device handle.
-- USB descriptors can be printed out with `usb_msc_print_descriptors` and general information about MSC device retrieved
-  with `from usb_msc_get_device_info` function.
-- Obtained device handle is then used in helper function `usb_msc_vfs_register` mounting USB Disk to Virtual filesystem.
-- At this point, standard C functions for accessing storage (`fopen`, `fwrite`, `fread`, `mkdir` etc.) can be carried out.
-- In order to uninstall the whole USB stack, deinitializing counterparts to functions above has to be called in reverse order. 
-
-## Known issues
-
-- Driver only supports USB 2.0 flash drives using the BOT “Bulk-Only Transport” protocol and the Transparent SCSI command set
-- Composite USB devices are not supported
-
-## Troubleshooting
-
-After connecting composite USB device, driver prints `COMPOSITE DEVICES UNSUPPORTED` 

+ 0 - 169
examples/peripherals/usb/host/msc/components/msc/include/msc_host.h

@@ -1,169 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#include <wchar.h>
-#include <stdint.h>
-#include "esp_err.h"
-#include <freertos/FreeRTOS.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ESP_ERR_MSC_HOST_BASE        0x1700                      /*!< MSC host error code base */
-#define ESP_ERR_MSC_MOUNT_FAILED    (ESP_ERR_MSC_HOST_BASE + 1)  /*!< Failed to mount storage */
-#define ESP_ERR_MSC_FORMAT_FAILED   (ESP_ERR_MSC_HOST_BASE + 2)  /*!< Failed to format storage */
-#define ESP_ERR_MSC_INTERNAL        (ESP_ERR_MSC_HOST_BASE + 3)  /*!< MSC host internal error */
-
-#define MSC_STR_DESC_SIZE 32
-
-typedef struct msc_host_device *msc_host_device_handle_t;     /**< Handle to a Mass Storage Device */
-
-/**
- * @brief USB Mass Storage event containing event type and associated device handle.
-*/
-typedef struct {
-    enum {
-        MSC_DEVICE_CONNECTED,       /**< MSC device has been connected to the system.*/
-        MSC_DEVICE_DISCONNECTED,    /**< MSC device has been disconnected from the system.*/
-    } event;
-    union {
-        uint8_t address;                /**< Address of connected MSC device.*/
-        msc_host_device_handle_t handle; /**< MSC device handle to disconnected device.*/
-    } device;
-} msc_host_event_t;
-
-/**
- * @brief USB Mass Storage event callback.
- *
- * @param[in] event mass storage event
-*/
-typedef void (*msc_host_event_cb_t)(const msc_host_event_t *event, void *arg);
-
-/**
- * @brief MSC configuration structure.
-*/
-typedef struct {
-    bool create_backround_task;     /**< When set to true, background task handling usb events is created.
-                                         Otherwise user has to periodically call msc_host_handle_events function */
-    size_t task_priority;           /**< Task priority of crated background task */
-    size_t stack_size;              /**< Stack size of crated background task */
-    BaseType_t core_id;             /**< Select core on which background task will run or tskNO_AFFINITY  */
-    msc_host_event_cb_t callback;   /**< Callback invoked when MSC event occurs. Must not be NULL. */
-    void *callback_arg;             /**< User provided argument passed to callback */
-} msc_host_driver_config_t;
-
-/**
- * @brief MSC device info.
-*/
-typedef struct {
-    uint32_t sector_count;
-    uint32_t sector_size;
-    uint16_t idProduct;
-    uint16_t idVendor;
-    wchar_t iManufacturer[MSC_STR_DESC_SIZE];
-    wchar_t iProduct[MSC_STR_DESC_SIZE];
-    wchar_t iSerialNumber[MSC_STR_DESC_SIZE];
-} msc_host_device_info_t;
-
-/**
- * @brief Install USB Host Mass Storage Class driver
- *
- * @param[in] config configuration structure MSC to create
- * @return esp_err_r
- */
-esp_err_t msc_host_install(const msc_host_driver_config_t *config);
-
-/**
- * @brief Uninstall Mass Storage Class driver
- * @return esp_err_t
- */
-esp_err_t msc_host_uninstall(void);
-
-/**
- * @brief Initialization of MSC device.
- *
- * @param[in]  device_address  Device address obtained from MSC callback provided upon connection and enumeration
- * @param[out] device          Mass storage device handle to be used for subsequent calls.
- * @return esp_err_t
- */
-esp_err_t msc_host_install_device(uint8_t device_address, msc_host_device_handle_t *device);
-
-/**
- * @brief Deinitialization of MSC device.
- *
- * @param[in]  device  Device handle obtained from msc_host_install_device function
- * @return esp_err_t
- */
-esp_err_t msc_host_uninstall_device(msc_host_device_handle_t device);
-
-/**
- * @brief Helper function for reading sector from mass storage device.
- *
- * @warning This call is not thread safe and should not be combined
- *          with accesses to storage through file system.
- *
- * @note  Provided sector and size cannot exceed
- *        sector_count and sector_size obtained from msc_host_device_info_t
- *
- * @param[in]  device Device handle
- * @param[in]  sector Number of sector to be read
- * @param[out] data   Buffer into which data will be written
- * @param[in]  size   Number of bytes to be read
- * @return esp_err_t
- */
-esp_err_t msc_host_read_sector(msc_host_device_handle_t device, size_t sector, void *data, size_t size);
-
-/**
- * @brief Helper function for writing sector to mass storage device.
- *
- * @warning This call is not thread safe and should not be combined
- *          with accesses to storare through file system.
- *
- * @note  Provided sector and size cannot exceed
- *        sector_count and sector_size obtained from msc_host_device_info_t
- *
- * @param[in]  device Device handle
- * @param[in]  sector Number of sector to be read
- * @param[in]  data   Data to be written to the sector
- * @param[in]  size   Number of bytes to be written
- * @return esp_err_t
- */
-esp_err_t msc_host_write_sector(msc_host_device_handle_t device, size_t sector, const void *data, size_t size);
-
-/**
- * @brief Handle MSC HOST events.
- *
- * @param[in]  timeout_ms  Timeout in miliseconds
- * @return esp_err_t
- */
-esp_err_t msc_host_handle_events(uint32_t timeout_ms);
-
-/**
- * @brief Gets devices information.
- *
- * @warning This call is not thread safe and should not be combined
- *          with accesses to storare through file system.
- *
- * @param[in]  device  Handle to device
- * @param[out] info  Structure to be populated with device info
- * @return esp_err_t
- */
-esp_err_t msc_host_get_device_info(msc_host_device_handle_t device, msc_host_device_info_t *info);
-
-/**
- * @brief Print configuration descriptor.
- *
- * @param[in]  device  Handle of MSC device
- * @return esp_err_t
- */
-esp_err_t msc_host_print_descriptors(msc_host_device_handle_t device);
-
-#ifdef __cplusplus
-}
-#endif //__cplusplus

+ 0 - 44
examples/peripherals/usb/host/msc/components/msc/include/msc_host_vfs.h

@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#include "esp_vfs_fat.h"
-#include "msc_host.h"
-#include "esp_err.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct msc_host_vfs *msc_host_vfs_handle_t;           /**< VFS handle to attached Mass Storage device */
-
-/**
- * @brief Register MSC device to Virtual filesystem.
- *
- * @param[in]  device  Device handle obtained from MSC callback provided upon initialization
- * @param[in]  base_path Base VFS path to be used to access file storage
- * @param[in]  mount_config Mount configuration.
- * @param[out] vfs_handle Handle to MSC device associated with registered VFS
- * @return esp_err_t
- */
-esp_err_t msc_host_vfs_register(msc_host_device_handle_t device,
-                                const char *base_path,
-                                const esp_vfs_fat_mount_config_t *mount_config,
-                                msc_host_vfs_handle_t *vfs_handle);
-
-
-/**
- * @brief Unregister MSC device from Virtual filesystem.
- *
- * @param[in]  vfs_handle  VFS handle obtained from MSC callback provided upon initialization
- * @return esp_err_t
- */
-esp_err_t msc_host_vfs_unregister(msc_host_vfs_handle_t vfs_handle);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 39
examples/peripherals/usb/host/msc/components/msc/private_include/diskio_usb.h

@@ -1,39 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Mass storage disk initialization structure
- */
-typedef struct {
-    uint32_t block_size;    /**< Block size */
-    uint32_t block_count;   /**< Block count */
-} usb_disk_t;
-
-/**
- * @brief Register mass storage disk to fat file system
- *
- * @param[in] pdrv Number of free drive obtained from ff_diskio_get_drive() function
- * @param[in] disk usb_disk_t structure
- */
-void ff_diskio_register_msc(uint8_t pdrv, usb_disk_t *disk);
-
-/**
- * @brief Obtains number of drive assigned to usb disk upon calling ff_diskio_register_msc()
- *
- * @param[in] disk usb_disk_t structure
- * @return Drive number
- */
-uint8_t ff_diskio_get_pdrv_disk(const usb_disk_t *disk);
-
-#ifdef __cplusplus
-}
-#endif //__cplusplus

+ 0 - 61
examples/peripherals/usb/host/msc/components/msc/private_include/msc_common.h

@@ -1,61 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <sys/queue.h>
-#include "esp_err.h"
-#include "esp_check.h"
-#include "diskio_usb.h"
-#include "usb/usb_host.h"
-#include "usb/usb_types_stack.h"
-#include "freertos/semphr.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef enum {
-    MSC_EP_OUT,
-    MSC_EP_IN
-} msc_endpoint_t;
-
-typedef struct {
-    uint16_t bulk_in_mps;
-    uint8_t bulk_in_ep;
-    uint8_t bulk_out_ep;
-    uint8_t iface_num;
-} msc_config_t;
-
-typedef struct msc_host_device {
-    STAILQ_ENTRY(msc_host_device) tailq_entry;
-    usb_transfer_status_t transfer_status;
-    SemaphoreHandle_t transfer_done;
-    usb_device_handle_t handle;
-    usb_transfer_t *xfer;
-    msc_config_t config;
-    usb_disk_t disk;
-} msc_device_t;
-
-esp_err_t msc_bulk_transfer(msc_device_t *device_handle, uint8_t *data, size_t size, msc_endpoint_t ep);
-
-esp_err_t msc_control_transfer(msc_device_t *device_handle, usb_transfer_t *xfer, size_t len);
-
-#define MSC_GOTO_ON_ERROR(exp) ESP_GOTO_ON_ERROR(exp, fail, TAG, "")
-
-#define MSC_GOTO_ON_FALSE(exp, err) ESP_GOTO_ON_FALSE( (exp), err, fail, TAG, "" )
-
-#define MSC_RETURN_ON_ERROR(exp) ESP_RETURN_ON_ERROR((exp), TAG, "")
-
-#define MSC_RETURN_ON_FALSE(exp, err) ESP_RETURN_ON_FALSE( (exp), (err), TAG, "")
-
-#define MSC_RETURN_ON_INVALID_ARG(exp) ESP_RETURN_ON_FALSE((exp) != NULL, ESP_ERR_INVALID_ARG, TAG, "")
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 56
examples/peripherals/usb/host/msc/components/msc/private_include/msc_scsi_bot.h

@@ -1,56 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#include <stdint.h>
-#include "esp_err.h"
-#include "msc_common.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef struct {
-    uint8_t key;
-    uint8_t code;
-    uint8_t code_q;
-} scsi_sense_data_t;
-
-esp_err_t scsi_cmd_read10(msc_device_t *device,
-                          uint8_t *data,
-                          uint32_t sector_address,
-                          uint32_t num_sectors,
-                          uint32_t sector_size);
-
-esp_err_t scsi_cmd_write10(msc_device_t *device,
-                           const uint8_t *data,
-                           uint32_t sector_address,
-                           uint32_t num_sectors,
-                           uint32_t sector_size);
-
-esp_err_t scsi_cmd_read_capacity(msc_device_t *device,
-                                 uint32_t *block_size,
-                                 uint32_t *block_count);
-
-esp_err_t scsi_cmd_sense(msc_device_t *device, scsi_sense_data_t *sense);
-
-esp_err_t scsi_cmd_unit_ready(msc_device_t *device);
-
-esp_err_t scsi_cmd_inquiry(msc_device_t *device);
-
-esp_err_t scsi_cmd_prevent_removal(msc_device_t *device, bool prevent);
-
-esp_err_t scsi_cmd_mode_sense(msc_device_t *device);
-
-esp_err_t msc_mass_reset(msc_device_t *device);
-
-esp_err_t msc_get_max_lun(msc_device_t *device, uint8_t *lun);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 118
examples/peripherals/usb/host/msc/components/msc/src/diskio_usb.c

@@ -1,118 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include "diskio_impl.h"
-#include "ffconf.h"
-#include "ff.h"
-#include "esp_log.h"
-#include "diskio_usb.h"
-#include "msc_scsi_bot.h"
-#include "msc_common.h"
-#include "usb/usb_types_stack.h"
-
-static usb_disk_t *s_disks[FF_VOLUMES] = { NULL };
-
-static const char *TAG = "diskio_usb";
-
-static DSTATUS usb_disk_initialize (BYTE pdrv)
-{
-    return RES_OK;
-}
-
-static DSTATUS usb_disk_status (BYTE pdrv)
-{
-    return RES_OK;
-}
-
-static DRESULT usb_disk_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
-{
-    assert(pdrv < FF_VOLUMES);
-    assert(s_disks[pdrv]);
-
-    esp_err_t err;
-    usb_disk_t *disk = s_disks[pdrv];
-    size_t sector_size = disk->block_size;
-    msc_device_t *dev = __containerof(disk, msc_device_t, disk);
-
-    for (int i = 0; i < count; i++) {
-        err = scsi_cmd_read10(dev, &buff[i * sector_size], sector + i, 1, sector_size);
-        if (err != ESP_OK) {
-            ESP_LOGE(TAG, "scsi_cmd_read10 failed (%d)", err);
-            return RES_ERROR;
-        }
-
-    }
-
-    return RES_OK;
-}
-
-static DRESULT usb_disk_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
-{
-    assert(pdrv < FF_VOLUMES);
-    assert(s_disks[pdrv]);
-
-    esp_err_t err;
-    usb_disk_t *disk = s_disks[pdrv];
-    size_t sector_size = disk->block_size;
-    msc_device_t *dev = __containerof(disk, msc_device_t, disk);
-
-    for (int i = 0; i < count; i++) {
-        err = scsi_cmd_write10(dev, &buff[i * sector_size], sector + i, 1, sector_size);
-        if (err != ESP_OK) {
-            ESP_LOGE(TAG, "scsi_cmd_write10 failed (%d)", err);
-            return RES_ERROR;
-        }
-
-    }
-    return RES_OK;
-}
-
-static DRESULT usb_disk_ioctl (BYTE pdrv, BYTE cmd, void *buff)
-{
-    assert(pdrv < FF_VOLUMES);
-    assert(s_disks[pdrv]);
-
-    usb_disk_t *disk = s_disks[pdrv];
-
-    switch (cmd) {
-    case CTRL_SYNC:
-        return RES_OK;
-    case GET_SECTOR_COUNT:
-        *((DWORD *) buff) = disk->block_count;
-        return RES_OK;
-    case GET_SECTOR_SIZE:
-        *((WORD *) buff) = disk->block_size;
-        return RES_OK;
-    case GET_BLOCK_SIZE:
-        return RES_ERROR;
-    }
-    return RES_ERROR;
-}
-
-void ff_diskio_register_msc(BYTE pdrv, usb_disk_t *disk)
-{
-    assert(pdrv < FF_VOLUMES);
-
-    static const ff_diskio_impl_t usb_disk_impl = {
-        .init = &usb_disk_initialize,
-        .status = &usb_disk_status,
-        .read = &usb_disk_read,
-        .write = &usb_disk_write,
-        .ioctl = &usb_disk_ioctl
-    };
-    s_disks[pdrv] = disk;
-    ff_diskio_register(pdrv, &usb_disk_impl);
-}
-
-BYTE ff_diskio_get_pdrv_disk(const usb_disk_t *disk)
-{
-    for (int i = 0; i < FF_VOLUMES; i++) {
-        if (disk == s_disks[i]) {
-            return i;
-        }
-    }
-    return 0xff;
-}

+ 0 - 553
examples/peripherals/usb/host/msc/components/msc/src/msc_host.c

@@ -1,553 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <sys/param.h>
-#include "esp_log.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "freertos/semphr.h"
-#include "usb/usb_host.h"
-#include "diskio_usb.h"
-#include "msc_common.h"
-#include "msc_host.h"
-#include "msc_scsi_bot.h"
-#include "usb/usb_types_ch9.h"
-#include "usb/usb_helpers.h"
-
-static portMUX_TYPE msc_lock = portMUX_INITIALIZER_UNLOCKED;
-
-#define MSC_ENTER_CRITICAL()    portENTER_CRITICAL(&msc_lock)
-#define MSC_EXIT_CRITICAL()     portEXIT_CRITICAL(&msc_lock)
-
-#define MSC_GOTO_ON_FALSE_CRITICAL(exp, err)    \
-    do {                                        \
-        if(!(exp)) {                            \
-            MSC_EXIT_CRITICAL();                \
-            ret = err;                          \
-            goto fail;                          \
-        }                                       \
-    } while(0)
-
-#define MSC_RETURN_ON_FALSE_CRITICAL(exp, err)  \
-    do {                                        \
-        if(!(exp)) {                            \
-            MSC_EXIT_CRITICAL();                \
-            return err;                         \
-        }                                       \
-    } while(0)
-
-#define WAIT_FOR_READY_TIMEOUT_MS 3000
-#define TAG "USB_MSC"
-
-#define SCSI_COMMAND_SET    0x06
-#define BULK_ONLY_TRANSFER  0x50
-#define MSC_NO_SENSE        0x00
-#define MSC_NOT_READY       0x02
-#define MSC_UNIT_ATTENTION  0x06
-
-typedef struct {
-    usb_host_client_handle_t client_handle;
-    msc_host_event_cb_t user_cb;
-    void *user_arg;
-    SemaphoreHandle_t all_events_handled;
-    volatile bool end_client_event_handling;
-} msc_driver_t;
-
-static msc_driver_t *s_msc_driver;
-
-STAILQ_HEAD(devices, msc_host_device) devices_tailq;
-
-static const usb_standard_desc_t *next_interface_desc(const usb_standard_desc_t *desc, size_t len, size_t *offset)
-{
-    return usb_parse_next_descriptor_of_type(desc, len, USB_W_VALUE_DT_INTERFACE, (int *)offset);
-}
-
-static const usb_standard_desc_t *next_endpoint_desc(const usb_standard_desc_t *desc, size_t len, size_t *offset)
-{
-    return usb_parse_next_descriptor_of_type(desc, len, USB_B_DESCRIPTOR_TYPE_ENDPOINT, (int *)offset);
-}
-
-static const usb_intf_desc_t *find_msc_interface(const usb_config_desc_t *config_desc, size_t *offset)
-{
-    size_t total_length = config_desc->wTotalLength;
-    const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)config_desc;
-
-    next_desc = next_interface_desc(next_desc, total_length, offset);
-
-    while ( next_desc ) {
-
-        const usb_intf_desc_t *ifc_desc = (const usb_intf_desc_t *)next_desc;
-
-        if ( ifc_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE &&
-                ifc_desc->bInterfaceSubClass == SCSI_COMMAND_SET &&
-                ifc_desc->bInterfaceProtocol == BULK_ONLY_TRANSFER ) {
-            return ifc_desc;
-        }
-
-        next_desc = next_interface_desc(next_desc, total_length, offset);
-    };
-    return NULL;
-}
-
-/**
- * @brief Extracts configuration from configuration descriptor.
- *
- * @note  Passes interface and endpoint descriptors to obtain:
-
- *        - interface number, IN endpoint, OUT endpoint, max. packet size
- *
- * @param[in]  cfg_desc  Configuration descriptor
- * @param[out] cfg       Obtained configuration
- * @return esp_err_t
- */
-static esp_err_t extract_config_from_descriptor(const usb_config_desc_t *cfg_desc, msc_config_t *cfg)
-{
-    size_t offset = 0;
-    size_t total_len = cfg_desc->wTotalLength;
-    const usb_intf_desc_t *ifc_desc = find_msc_interface(cfg_desc, &offset);
-    assert(ifc_desc);
-    const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)ifc_desc;
-    const usb_ep_desc_t *ep_desc = NULL;
-
-    cfg->iface_num = ifc_desc->bInterfaceNumber;
-
-    next_desc = next_endpoint_desc(next_desc, total_len, &offset);
-    MSC_RETURN_ON_FALSE(next_desc, ESP_ERR_NOT_SUPPORTED);
-    ep_desc = (const usb_ep_desc_t *)next_desc;
-
-    if (ep_desc->bEndpointAddress & 0x80) {
-        cfg->bulk_in_ep = ep_desc->bEndpointAddress;
-        cfg->bulk_in_mps = ep_desc->wMaxPacketSize;
-    } else {
-        cfg->bulk_out_ep = ep_desc->bEndpointAddress;
-    }
-
-    next_desc = next_endpoint_desc(next_desc, total_len, &offset);
-    MSC_RETURN_ON_FALSE(next_desc, ESP_ERR_NOT_SUPPORTED);
-    ep_desc = (const usb_ep_desc_t *)next_desc;
-
-    if (ep_desc->bEndpointAddress & 0x80) {
-        cfg->bulk_in_ep = ep_desc->bEndpointAddress;
-        cfg->bulk_in_mps = ep_desc->wMaxPacketSize;
-    } else {
-        cfg->bulk_out_ep = ep_desc->bEndpointAddress;
-    }
-
-    return ESP_OK;
-}
-
-static esp_err_t msc_deinit_device(msc_device_t *dev, bool install_failed)
-{
-    MSC_ENTER_CRITICAL();
-    MSC_RETURN_ON_FALSE_CRITICAL( dev, ESP_ERR_INVALID_STATE );
-    STAILQ_REMOVE(&devices_tailq, dev, msc_host_device, tailq_entry);
-    MSC_EXIT_CRITICAL();
-
-    if (dev->transfer_done) {
-        vSemaphoreDelete(dev->transfer_done);
-    }
-    if (install_failed) {
-        // Error code is unchecked, as it's unknown at what point installation failed.
-        usb_host_interface_release(s_msc_driver->client_handle, dev->handle, dev->config.iface_num);
-        usb_host_device_close(s_msc_driver->client_handle, dev->handle);
-        usb_host_transfer_free(dev->xfer);
-    } else {
-        MSC_RETURN_ON_ERROR( usb_host_interface_release(s_msc_driver->client_handle, dev->handle, dev->config.iface_num) );
-        MSC_RETURN_ON_ERROR( usb_host_device_close(s_msc_driver->client_handle, dev->handle) );
-        MSC_RETURN_ON_ERROR( usb_host_transfer_free(dev->xfer) );
-    }
-
-    free(dev);
-    return ESP_OK;
-}
-
-// Some MSC devices requires to change its internal state from non-ready to ready
-static esp_err_t msc_wait_for_ready_state(msc_device_t *dev, size_t timeout_ms)
-{
-    esp_err_t err;
-    scsi_sense_data_t sense;
-    uint32_t trials = MAX(1, timeout_ms / 100);
-
-    do {
-        err = scsi_cmd_unit_ready(dev);
-        if (err != ESP_OK) {
-            MSC_RETURN_ON_ERROR( scsi_cmd_sense(dev, &sense) );
-            if (sense.key != MSC_NOT_READY &&
-                    sense.key != MSC_UNIT_ATTENTION &&
-                    sense.key != MSC_NO_SENSE) {
-                return ESP_ERR_MSC_INTERNAL;
-            }
-        }
-        vTaskDelay( pdMS_TO_TICKS(100) );
-    } while (trials-- && err);
-
-    return err;
-}
-
-static bool is_mass_storage_device(uint8_t dev_addr)
-{
-    size_t dummy = 0;
-    bool is_msc_device = false;
-    usb_device_handle_t device;
-    const usb_config_desc_t *config_desc;
-
-    if ( usb_host_device_open(s_msc_driver->client_handle, dev_addr, &device) == ESP_OK) {
-        if ( usb_host_get_active_config_descriptor(device, &config_desc) == ESP_OK ) {
-            if ( find_msc_interface(config_desc, &dummy) ) {
-                is_msc_device = true;
-            } else {
-                ESP_LOGD(TAG, "Connected USB device is not MSC");
-            }
-        }
-        usb_host_device_close(s_msc_driver->client_handle, device);
-    }
-
-    return is_msc_device;
-}
-
-static void event_handler_task(void *arg)
-{
-    while (1) {
-        usb_host_client_handle_events(s_msc_driver->client_handle, pdMS_TO_TICKS(50));
-
-        if (s_msc_driver->end_client_event_handling) {
-            break;
-        }
-    }
-    usb_host_client_unblock(s_msc_driver->client_handle);
-    ESP_ERROR_CHECK( usb_host_client_deregister(s_msc_driver->client_handle) );
-    xSemaphoreGive(s_msc_driver->all_events_handled);
-    vTaskDelete(NULL);
-}
-
-static msc_device_t *find_msc_device(usb_device_handle_t device_handle)
-{
-    msc_host_device_handle_t device;
-
-    STAILQ_FOREACH(device, &devices_tailq, tailq_entry) {
-        if (device_handle == device->handle) {
-            return device;
-        }
-    }
-
-    return NULL;
-}
-
-static void client_event_cb(const usb_host_client_event_msg_t *event, void *arg)
-{
-    if (event->event == USB_HOST_CLIENT_EVENT_NEW_DEV) {
-        if (is_mass_storage_device(event->new_dev.address)) {
-            const msc_host_event_t msc_event = {
-                .event = MSC_DEVICE_CONNECTED,
-                .device.address = event->new_dev.address,
-            };
-            s_msc_driver->user_cb(&msc_event, s_msc_driver->user_arg);
-        }
-    } else if (event->event == USB_HOST_CLIENT_EVENT_DEV_GONE) {
-        msc_device_t *msc_device = find_msc_device(event->dev_gone.dev_hdl);
-        if (msc_device) {
-            const msc_host_event_t msc_event = {
-                .event = MSC_DEVICE_DISCONNECTED,
-                .device.handle = msc_device,
-            };
-            s_msc_driver->user_cb(&msc_event, s_msc_driver->user_arg);
-        }
-    }
-}
-
-esp_err_t msc_host_install(const msc_host_driver_config_t *config)
-{
-    esp_err_t ret;
-
-    MSC_RETURN_ON_INVALID_ARG(config);
-    MSC_RETURN_ON_INVALID_ARG(config->callback);
-    if ( config->create_backround_task ) {
-        MSC_RETURN_ON_FALSE(config->stack_size != 0, ESP_ERR_INVALID_ARG);
-        MSC_RETURN_ON_FALSE(config->task_priority != 0, ESP_ERR_INVALID_ARG);
-    }
-    MSC_RETURN_ON_FALSE(!s_msc_driver, ESP_ERR_INVALID_STATE);
-
-    msc_driver_t *driver = calloc(1, sizeof(msc_driver_t));
-    MSC_RETURN_ON_FALSE(driver, ESP_ERR_NO_MEM);
-    driver->user_cb = config->callback;
-    driver->user_arg = config->callback_arg;
-
-    usb_host_client_config_t client_config = {
-        .async.client_event_callback = client_event_cb,
-        .async.callback_arg = NULL,
-        .max_num_event_msg = 10,
-    };
-
-    driver->end_client_event_handling = false;
-    driver->all_events_handled = xSemaphoreCreateBinary();
-    MSC_GOTO_ON_FALSE(driver->all_events_handled, ESP_ERR_NO_MEM);
-
-    MSC_GOTO_ON_ERROR( usb_host_client_register(&client_config, &driver->client_handle) );
-
-    MSC_ENTER_CRITICAL();
-    MSC_GOTO_ON_FALSE_CRITICAL(!s_msc_driver, ESP_ERR_INVALID_STATE);
-    s_msc_driver = driver;
-    STAILQ_INIT(&devices_tailq);
-    MSC_EXIT_CRITICAL();
-
-    if (config->create_backround_task) {
-        BaseType_t task_created = xTaskCreatePinnedToCore(
-            event_handler_task, "USB MSC", config->stack_size,
-            NULL, config->task_priority, NULL, config->core_id);
-        MSC_GOTO_ON_FALSE(task_created, ESP_ERR_NO_MEM);
-    }
-
-    return ESP_OK;
-
-fail:
-    s_msc_driver = NULL;
-    usb_host_client_deregister(driver->client_handle);
-    if (driver->all_events_handled) {
-        vSemaphoreDelete(driver->all_events_handled);
-    }
-    free(driver);
-    return ret;
-}
-
-esp_err_t msc_host_uninstall(void)
-{
-    // Make sure msc driver is installed,
-    // not being uninstalled from other task
-    // and no msc device is registered
-    MSC_ENTER_CRITICAL();
-    MSC_RETURN_ON_FALSE_CRITICAL( s_msc_driver != NULL, ESP_ERR_INVALID_STATE );
-    MSC_RETURN_ON_FALSE_CRITICAL( !s_msc_driver->end_client_event_handling, ESP_ERR_INVALID_STATE );
-    MSC_RETURN_ON_FALSE_CRITICAL( STAILQ_EMPTY(&devices_tailq), ESP_ERR_INVALID_STATE );
-    s_msc_driver->end_client_event_handling = true;
-    MSC_EXIT_CRITICAL();
-
-    xSemaphoreTake(s_msc_driver->all_events_handled, portMAX_DELAY);
-    vSemaphoreDelete(s_msc_driver->all_events_handled);
-    free(s_msc_driver);
-    s_msc_driver = NULL;
-    return ESP_OK;
-}
-
-esp_err_t msc_host_install_device(uint8_t device_address, msc_host_device_handle_t *msc_device_handle)
-{
-    esp_err_t ret;
-    uint32_t block_size, block_count;
-    const usb_config_desc_t *config_desc;
-    msc_device_t *msc_device;
-    uint8_t lun;
-    size_t transfer_size = 512; // Normally the smallest block size
-
-    MSC_GOTO_ON_FALSE( msc_device = calloc(1, sizeof(msc_device_t)), ESP_ERR_NO_MEM );
-
-    MSC_ENTER_CRITICAL();
-    MSC_GOTO_ON_FALSE_CRITICAL( s_msc_driver, ESP_ERR_INVALID_STATE );
-    MSC_GOTO_ON_FALSE_CRITICAL( s_msc_driver->client_handle, ESP_ERR_INVALID_STATE );
-    STAILQ_INSERT_TAIL(&devices_tailq, msc_device, tailq_entry);
-    MSC_EXIT_CRITICAL();
-
-    MSC_GOTO_ON_FALSE( msc_device->transfer_done = xSemaphoreCreateBinary(), ESP_ERR_NO_MEM);
-    MSC_GOTO_ON_ERROR( usb_host_device_open(s_msc_driver->client_handle, device_address, &msc_device->handle) );
-    MSC_GOTO_ON_ERROR( usb_host_get_active_config_descriptor(msc_device->handle, &config_desc) );
-    MSC_GOTO_ON_ERROR( extract_config_from_descriptor(config_desc, &msc_device->config) );
-    MSC_GOTO_ON_ERROR( usb_host_transfer_alloc(transfer_size, 0, &msc_device->xfer) );
-    MSC_GOTO_ON_ERROR( usb_host_interface_claim(s_msc_driver->client_handle,
-                                                msc_device->handle,
-                                                msc_device->config.iface_num, 0) );
-
-    MSC_GOTO_ON_ERROR( msc_get_max_lun(msc_device, &lun) );
-    MSC_GOTO_ON_ERROR( scsi_cmd_inquiry(msc_device) );
-    MSC_GOTO_ON_ERROR( msc_wait_for_ready_state(msc_device, WAIT_FOR_READY_TIMEOUT_MS) );
-    MSC_GOTO_ON_ERROR( scsi_cmd_read_capacity(msc_device, &block_size, &block_count) );
-
-    // Configuration descriptor size of simple MSC device is 32 bytes.
-    if (config_desc->wTotalLength != 32) {
-        ESP_LOGE(TAG, "COMPOSITE DEVICES UNSUPPORTED");
-    }
-
-    msc_device->disk.block_size = block_size;
-    msc_device->disk.block_count = block_count;
-
-    if (block_size > transfer_size) {
-        usb_transfer_t *larger_xfer;
-        MSC_GOTO_ON_ERROR( usb_host_transfer_alloc(block_size, 0, &larger_xfer) );
-        usb_host_transfer_free(msc_device->xfer);
-        msc_device->xfer = larger_xfer;
-    }
-
-    *msc_device_handle = msc_device;
-
-    return ESP_OK;
-
-fail:
-    msc_deinit_device(msc_device, true);
-    return ret;
-}
-
-esp_err_t msc_host_uninstall_device(msc_host_device_handle_t device)
-{
-    MSC_RETURN_ON_INVALID_ARG(device);
-    return msc_deinit_device((msc_device_t *)device, false);
-}
-
-
-esp_err_t msc_host_read_sector(msc_host_device_handle_t device, size_t sector, void *data, size_t size)
-{
-    MSC_RETURN_ON_INVALID_ARG(device);
-    msc_device_t *dev = (msc_device_t *)device;
-
-    return scsi_cmd_read10(dev, data, sector, 1, dev->disk.block_size);
-}
-
-esp_err_t msc_host_write_sector(msc_host_device_handle_t device, size_t sector, const void *data, size_t size)
-{
-    MSC_RETURN_ON_INVALID_ARG(device);
-    msc_device_t *dev = (msc_device_t *)device;
-
-    return scsi_cmd_write10(dev, data, sector, 1, dev->disk.block_size);
-}
-
-esp_err_t msc_host_handle_events(uint32_t timeout_ms)
-{
-    MSC_RETURN_ON_FALSE(s_msc_driver != NULL, ESP_ERR_INVALID_STATE);
-
-    return usb_host_client_handle_events(s_msc_driver->client_handle, timeout_ms);
-}
-
-static esp_err_t msc_read_string_desc(msc_device_t *dev, uint8_t index, wchar_t *str)
-{
-    if (index == 0) {
-        // String descriptor not available
-        str[0] = 0;
-        return ESP_OK;
-    }
-
-    usb_transfer_t *xfer = dev->xfer;
-    USB_SETUP_PACKET_INIT_GET_STR_DESC((usb_setup_packet_t *)xfer->data_buffer, index, 0x409, 64);
-    MSC_RETURN_ON_ERROR( msc_control_transfer(dev, xfer, USB_SETUP_PACKET_SIZE + 64) );
-
-    usb_standard_desc_t *desc = (usb_standard_desc_t *)(xfer->data_buffer + USB_SETUP_PACKET_SIZE);
-    wchar_t *data = (wchar_t *)(xfer->data_buffer + USB_SETUP_PACKET_SIZE + 2);
-    size_t len = MIN((desc->bLength - USB_STANDARD_DESC_SIZE) / 2, MSC_STR_DESC_SIZE - 1);
-
-    wcsncpy(str, data, len);
-    str[len] = 0;
-
-    return ESP_OK;
-}
-
-esp_err_t msc_host_get_device_info(msc_host_device_handle_t device, msc_host_device_info_t *info)
-{
-    MSC_RETURN_ON_INVALID_ARG(device);
-    MSC_RETURN_ON_INVALID_ARG(info);
-
-    msc_device_t *dev = (msc_device_t *)device;
-    const usb_device_desc_t *desc;
-
-    MSC_RETURN_ON_ERROR( usb_host_get_device_descriptor(dev->handle, &desc) );
-
-    info->idProduct = desc->idProduct;
-    info->idVendor = desc->idVendor;
-    info->sector_size = dev->disk.block_size;
-    info->sector_count = dev->disk.block_count;
-
-    MSC_RETURN_ON_ERROR( msc_read_string_desc(dev, desc->iManufacturer, info->iManufacturer) );
-    MSC_RETURN_ON_ERROR( msc_read_string_desc(dev, desc->iProduct, info->iProduct) );
-    MSC_RETURN_ON_ERROR( msc_read_string_desc(dev, desc->iSerialNumber, info->iSerialNumber) );
-
-    return ESP_OK;
-}
-
-esp_err_t msc_host_print_descriptors(msc_host_device_handle_t device)
-{
-    msc_device_t *dev = (msc_device_t *)device;
-    const usb_device_desc_t *device_desc;
-    const usb_config_desc_t *config_desc;
-    MSC_RETURN_ON_ERROR( usb_host_get_device_descriptor(dev->handle, &device_desc) );
-    MSC_RETURN_ON_ERROR( usb_host_get_active_config_descriptor(dev->handle, &config_desc) );
-    usb_print_device_descriptor(device_desc);
-    usb_print_config_descriptor(config_desc, NULL);
-    return ESP_OK;
-}
-
-static void transfer_callback(usb_transfer_t *transfer)
-{
-    msc_device_t *device = (msc_device_t *)transfer->context;
-
-    if (transfer->status != USB_TRANSFER_STATUS_COMPLETED) {
-        ESP_LOGE("Transfer failed", "Status %d", transfer->status);
-    }
-
-    device->transfer_status = transfer->status;
-    xSemaphoreGive(device->transfer_done);
-}
-
-static esp_err_t wait_for_transfer_done(usb_transfer_t *xfer)
-{
-    msc_device_t *device = (msc_device_t *)xfer->context;
-    BaseType_t received = xSemaphoreTake(device->transfer_done, pdMS_TO_TICKS(xfer->timeout_ms));
-
-    if (received != pdTRUE) {
-        usb_host_endpoint_halt(xfer->device_handle, xfer->bEndpointAddress);
-        usb_host_endpoint_flush(xfer->device_handle, xfer->bEndpointAddress);
-        xSemaphoreTake(device->transfer_done, portMAX_DELAY);
-        return ESP_ERR_TIMEOUT;
-    }
-
-    return (device->transfer_status == USB_TRANSFER_STATUS_COMPLETED) ? ESP_OK : ESP_FAIL;
-}
-
-static inline bool is_in_endpoint(uint8_t endpoint)
-{
-    return endpoint & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK ? true : false;
-}
-
-esp_err_t msc_bulk_transfer(msc_device_t *device, uint8_t *data, size_t size, msc_endpoint_t ep)
-{
-    usb_transfer_t *xfer = device->xfer;
-    MSC_RETURN_ON_FALSE(size <= xfer->data_buffer_size, ESP_ERR_INVALID_SIZE);
-    uint8_t endpoint = (ep == MSC_EP_IN) ? device->config.bulk_in_ep : device->config.bulk_out_ep;
-
-    if (is_in_endpoint(endpoint)) {
-        xfer->num_bytes = usb_round_up_to_mps(size, device->config.bulk_in_mps);
-    } else {
-        memcpy(xfer->data_buffer, data, size);
-        xfer->num_bytes = size;
-    }
-
-    xfer->device_handle = device->handle;
-    xfer->bEndpointAddress = endpoint;
-    xfer->callback = transfer_callback;
-    xfer->timeout_ms = 1000;
-    xfer->context = device;
-
-    MSC_RETURN_ON_ERROR( usb_host_transfer_submit(xfer) );
-    MSC_RETURN_ON_ERROR( wait_for_transfer_done(xfer) );
-
-    if (is_in_endpoint(endpoint)) {
-        memcpy(data, xfer->data_buffer, size);
-    }
-
-    return ESP_OK;
-}
-
-esp_err_t msc_control_transfer(msc_device_t *device, usb_transfer_t *xfer, size_t len)
-{
-    xfer->device_handle = device->handle;
-    xfer->bEndpointAddress = 0;
-    xfer->callback = transfer_callback;
-    xfer->timeout_ms = 1000;
-    xfer->num_bytes = len;
-    xfer->context = device;
-
-    MSC_RETURN_ON_ERROR( usb_host_transfer_submit_control(s_msc_driver->client_handle, xfer));
-    return wait_for_transfer_done(xfer);
-}

+ 0 - 124
examples/peripherals/usb/host/msc/components/msc/src/msc_host_vfs.c

@@ -1,124 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/param.h>
-#include "msc_common.h"
-#include "msc_host_vfs.h"
-#include "diskio_impl.h"
-#include "ffconf.h"
-#include "ff.h"
-
-#define DRIVE_STR_LEN 3
-
-typedef struct msc_host_vfs {
-    char drive[DRIVE_STR_LEN];
-    char *base_path;
-    uint8_t pdrv;
-} msc_host_vfs_t;
-
-static const char *TAG = "MSC VFS";
-
-static esp_err_t msc_format_storage(size_t block_size, size_t allocation_size, const char *drv)
-{
-    void *workbuf = NULL;
-    const size_t workbuf_size = 4096;
-
-    MSC_RETURN_ON_FALSE( workbuf = ff_memalloc(workbuf_size), ESP_ERR_NO_MEM );
-
-    // Valid value of cluster size is between sector_size and 128 * sector_size.
-    size_t cluster_size = MIN(MAX(allocation_size, block_size), 128 * block_size);
-    const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, cluster_size};
-    FRESULT err = f_mkfs(drv, &opt, workbuf, workbuf_size);
-    if (err) {
-        ESP_LOGE(TAG, "Formatting failed with error: %d", err);
-        free(workbuf);
-        return ESP_ERR_MSC_FORMAT_FAILED;
-    }
-
-    free(workbuf);
-    return ESP_OK;
-}
-
-static void dealloc_msc_vfs(msc_host_vfs_t *vfs)
-{
-    free(vfs->base_path);
-    free(vfs);
-}
-
-esp_err_t msc_host_vfs_register(msc_host_device_handle_t device,
-                                const char *base_path,
-                                const esp_vfs_fat_mount_config_t *mount_config,
-                                msc_host_vfs_handle_t *vfs_handle)
-{
-    MSC_RETURN_ON_INVALID_ARG(device);
-    MSC_RETURN_ON_INVALID_ARG(base_path);
-    MSC_RETURN_ON_INVALID_ARG(mount_config);
-    MSC_RETURN_ON_INVALID_ARG(vfs_handle);
-
-    FATFS *fs = NULL;
-    BYTE pdrv;
-    bool diskio_registered = false;
-    esp_err_t ret = ESP_ERR_MSC_MOUNT_FAILED;
-    msc_device_t *dev = (msc_device_t *)device;
-    size_t block_size = dev->disk.block_size;
-    size_t alloc_size = mount_config->allocation_unit_size;
-
-    msc_host_vfs_t *vfs = calloc(1, sizeof(msc_host_vfs_t));
-    MSC_RETURN_ON_FALSE(vfs != NULL, ESP_ERR_NO_MEM);
-
-    MSC_GOTO_ON_ERROR( ff_diskio_get_drive(&pdrv) );
-
-    ff_diskio_register_msc(pdrv, &dev->disk);
-    char drive[DRIVE_STR_LEN] = {(char)('0' + pdrv), ':', 0};
-    diskio_registered = true;
-
-    strncpy(vfs->drive, drive, DRIVE_STR_LEN);
-    MSC_GOTO_ON_FALSE( vfs->base_path = strdup(base_path), ESP_ERR_NO_MEM );
-    vfs->pdrv = pdrv;
-
-    MSC_GOTO_ON_ERROR( esp_vfs_fat_register(base_path, drive, mount_config->max_files, &fs) );
-
-    FRESULT fresult = f_mount(fs, drive, 1);
-
-    if ( fresult != FR_OK) {
-        if (mount_config->format_if_mount_failed &&
-                (fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR)) {
-            MSC_GOTO_ON_ERROR( msc_format_storage(block_size, alloc_size, drive) );
-            MSC_GOTO_ON_FALSE( f_mount(fs, drive, 0) == FR_OK, ESP_ERR_MSC_MOUNT_FAILED );
-        } else {
-            goto fail;
-        }
-    }
-
-    *vfs_handle = vfs;
-    return ESP_OK;
-
-fail:
-    if (diskio_registered) {
-        ff_diskio_unregister(pdrv);
-    }
-    esp_vfs_fat_unregister_path(base_path);
-    if(fs) {
-        f_mount(NULL, drive, 0);
-    }
-    dealloc_msc_vfs(vfs);
-    return ret;
-}
-
-esp_err_t msc_host_vfs_unregister(msc_host_vfs_handle_t vfs_handle)
-{
-    MSC_RETURN_ON_INVALID_ARG(vfs_handle);
-    msc_host_vfs_t *vfs = (msc_host_vfs_t *)vfs_handle;
-
-    f_mount(NULL, vfs->drive, 0);
-    ff_diskio_unregister(vfs->pdrv);
-    esp_vfs_fat_unregister_path(vfs->base_path);
-    dealloc_msc_vfs(vfs);
-    return ESP_OK;
-}

+ 0 - 434
examples/peripherals/usb/host/msc/components/msc/src/msc_scsi_bot.c

@@ -1,434 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "esp_log.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "esp_check.h"
-#include "esp_log.h"
-#include "msc_common.h"
-#include "msc_scsi_bot.h"
-
-#define TAG "USB_MSC_SCSI"
-
-/* --------------------------- SCSI Definitions ----------------------------- */
-#define CMD_SENSE_VALID_BIT (1 << 7)
-#define SCSI_FLAG_DPO (1<<4)
-#define SCSI_FLAG_FUA (1<<3)
-
-#define SCSI_CMD_FORMAT_UNIT 0x04
-#define SCSI_CMD_INQUIRY 0x12
-#define SCSI_CMD_MODE_SELECT 0x55
-#define SCSI_CMD_MODE_SENSE 0x5A
-#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
-#define SCSI_CMD_READ10 0x28
-#define SCSI_CMD_READ12 0xA8
-#define SCSI_CMD_READ_CAPACITY 0x25
-#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
-#define SCSI_CMD_REQUEST_SENSE 0x03
-#define SCSI_CMD_REZERO 0x01
-#define SCSI_CMD_SEEK10 0x2B
-#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
-#define SCSI_CMD_START_STOP Unit 0x1B
-#define SCSI_CMD_TEST_UNIT_READY 0x00
-#define SCSI_CMD_VERIFY 0x2F
-#define SCSI_CMD_WRITE10 0x2A
-#define SCSI_CMD_WRITE12 0xAA
-#define SCSI_CMD_WRITE_AND_VERIFY 0x2E
-
-#define IN_DIR   CWB_FLAG_DIRECTION_IN
-#define OUT_DIR  0
-
-#define INQUIRY_VID_SIZE    8
-#define INQUIRY_PID_SIZE    16
-#define INQUIRY_REV_SIZE    4
-
-#define CBW_CMD_SIZE(cmd) (sizeof(cmd) - sizeof(msc_cbw_t))
-
-#define CBW_BASE_INIT(dir, cbw_len, data_len)   \
-    .base = {                                   \
-        .signature = 0x43425355,                \
-        .tag = ++cbw_tag,                       \
-        .flags = dir,                           \
-        .lun = 0,                               \
-        .data_length = data_len,                \
-        .cbw_length = cbw_len,                  \
-    }
-
-#define FEATURE_SELECTOR_ENDPOINT   0
-#define CSW_SIGNATURE   0x53425355
-#define CBW_SIZE        31
-
-#define USB_MASS_REQ_INIT_RESET(ctrl_req_ptr, intf_num) ({                  \
-    (ctrl_req_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT |           \
-                                    USB_BM_REQUEST_TYPE_TYPE_CLASS |        \
-                                    USB_BM_REQUEST_TYPE_RECIP_INTERFACE;    \
-    (ctrl_req_ptr)->bRequest = 0xFF;                                        \
-    (ctrl_req_ptr)->wValue = 0;                                             \
-    (ctrl_req_ptr)->wIndex = (intf_num);                                    \
-    (ctrl_req_ptr)->wLength = 0;                                            \
-})
-
-#define USB_MASS_REQ_INIT_GET_MAX_LUN(ctrl_req_ptr, intf_num) ({            \
-    (ctrl_req_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN |            \
-                                    USB_BM_REQUEST_TYPE_TYPE_CLASS |        \
-                                    USB_BM_REQUEST_TYPE_RECIP_INTERFACE;    \
-    (ctrl_req_ptr)->bRequest = 0xFE;                                        \
-    (ctrl_req_ptr)->wValue = 0;                                             \
-    (ctrl_req_ptr)->wIndex = (intf_num);                                    \
-    (ctrl_req_ptr)->wLength = 1;                                            \
-})
-
-#define USB_SETUP_PACKET_INIT_CLEAR_FEATURE_EP(ctrl_req_ptr, ep_num) ({     \
-    (ctrl_req_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT |           \
-                                    USB_BM_REQUEST_TYPE_TYPE_STANDARD |     \
-                                    USB_BM_REQUEST_TYPE_RECIP_ENDPOINT;     \
-    (ctrl_req_ptr)->bRequest = USB_B_REQUEST_CLEAR_FEATURE;                 \
-    (ctrl_req_ptr)->wValue = FEATURE_SELECTOR_ENDPOINT;                     \
-    (ctrl_req_ptr)->wIndex = (ep_num);                                      \
-    (ctrl_req_ptr)->wLength = 0;                                            \
-})
-
-#define CWB_FLAG_DIRECTION_IN (1<<7) // device -> host
-
-/**
- * @brief Command Block Wrapper structure
- */
-typedef struct __attribute__((packed))
-{
-    uint32_t signature;
-    uint32_t tag;
-    uint32_t data_length;
-    uint8_t flags;
-    uint8_t lun;
-    uint8_t cbw_length;
-} msc_cbw_t;
-
-/**
- * @brief Command Status Wrapper structure
- */
-typedef struct __attribute__((packed))
-{
-    uint32_t signature;
-    uint32_t tag;
-    uint32_t dataResidue;
-    uint8_t status;
-} msc_csw_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint32_t address;
-    uint8_t reserved1;
-    uint16_t length;
-    uint8_t reserved2[3];
-} cbw_read10_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint32_t address;
-    uint8_t reserved1;
-    uint16_t length;
-    uint8_t reserved2[1];
-} cbw_write10_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint32_t address;
-    uint8_t reserved[6];
-} cbw_read_capacity_t;
-
-typedef struct __attribute__((packed))
-{
-    uint32_t block_count;
-    uint32_t block_size;
-} cbw_read_capacity_response_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint8_t reserved[10];
-} cbw_unit_ready_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint8_t reserved_0[2];
-    uint8_t allocation_length;
-    uint8_t reserved_1[7];
-} cbw_sense_t;
-
-typedef struct __attribute__((packed))
-{
-    uint8_t error_code;
-    uint8_t reserved_0;
-    uint8_t sense_key;
-    uint32_t info;
-    uint8_t sense_len;
-    uint32_t reserved_1;
-    uint8_t sense_code;
-    uint8_t sense_code_qualifier;
-    uint32_t reserved_2;
-} cbw_sense_response_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint8_t page_code;
-    uint8_t reserved_0;
-    uint8_t allocation_length;
-    uint8_t reserved_1[7];
-} cbw_inquiry_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint8_t pc_page_code;
-    uint8_t reserved_1[4];
-    uint16_t parameter_list_length;
-    uint8_t reserved_2[3];
-} mode_sense_t;
-
-typedef struct __attribute__((packed))
-{
-    uint8_t data[8];
-} mode_sense_response_t;
-
-typedef struct __attribute__((packed))
-{
-    msc_cbw_t base;
-    uint8_t opcode;
-    uint8_t flags;
-    uint8_t reserved_1[2];
-    uint8_t prevent;
-    uint8_t reserved_2[7];
-} prevent_allow_medium_removal_t;
-
-typedef struct __attribute__((packed))
-{
-    uint8_t data[36];
-} cbw_inquiry_response_t;
-
-// Unique number based on which MSC protocol pairs request and response
-static uint32_t cbw_tag;
-
-static esp_err_t check_csw(msc_csw_t *csw, uint32_t tag)
-{
-    bool csw_ok = csw->signature == CSW_SIGNATURE && csw->tag == tag &&
-                  csw->dataResidue == 0 && csw->status == 0;
-
-    if (!csw_ok) {
-        ESP_LOGD(TAG, "CSW failed: status %d", csw->status);
-    }
-
-    return csw_ok ? ESP_OK : ESP_FAIL;
-}
-
-static esp_err_t clear_feature(msc_device_t *device, uint8_t endpoint)
-{
-    usb_device_handle_t dev = device->handle;
-    usb_transfer_t *xfer = device->xfer;
-
-    MSC_RETURN_ON_ERROR( usb_host_endpoint_clear(dev, endpoint) );
-    USB_SETUP_PACKET_INIT_CLEAR_FEATURE_EP((usb_setup_packet_t *)xfer->data_buffer, endpoint);
-    MSC_RETURN_ON_ERROR( msc_control_transfer(device, xfer, USB_SETUP_PACKET_SIZE) );
-
-    return ESP_OK;
-}
-
-esp_err_t msc_mass_reset(msc_device_t *device)
-{
-    usb_transfer_t *xfer = device->xfer;
-
-    USB_MASS_REQ_INIT_RESET((usb_setup_packet_t *)xfer->data_buffer, 0);
-    MSC_RETURN_ON_ERROR( msc_control_transfer(device, xfer, USB_SETUP_PACKET_SIZE) );
-
-    return ESP_OK;
-}
-
-esp_err_t msc_get_max_lun(msc_device_t *device, uint8_t *lun)
-{
-    usb_transfer_t *xfer = device->xfer;
-
-    USB_MASS_REQ_INIT_GET_MAX_LUN((usb_setup_packet_t *)xfer->data_buffer, 0);
-    MSC_RETURN_ON_ERROR( msc_control_transfer(device, xfer, USB_SETUP_PACKET_SIZE + 1) );
-
-    *lun = xfer->data_buffer[USB_SETUP_PACKET_SIZE];
-
-    return ESP_OK;
-}
-
-static esp_err_t bot_execute_command(msc_device_t *device, msc_cbw_t *cbw, void *data, size_t size)
-{
-    msc_csw_t csw;
-    msc_endpoint_t ep = (cbw->flags & CWB_FLAG_DIRECTION_IN) ? MSC_EP_IN : MSC_EP_OUT;
-
-    MSC_RETURN_ON_ERROR( msc_bulk_transfer(device, (uint8_t *)cbw, CBW_SIZE, MSC_EP_OUT) );
-
-    if (data) {
-        MSC_RETURN_ON_ERROR( msc_bulk_transfer(device, (uint8_t *)data, size, ep) );
-    }
-
-    esp_err_t  err = msc_bulk_transfer(device, (uint8_t *)&csw, sizeof(msc_csw_t), MSC_EP_IN);
-
-    if (err ==  ESP_FAIL && device->transfer_status == USB_TRANSFER_STATUS_STALL) {
-        ESP_RETURN_ON_ERROR( clear_feature(device, MSC_EP_IN), TAG, "Clear feature failed" );
-        // Try to read csw again after clearing feature
-        err = msc_bulk_transfer(device, (uint8_t *)&csw, sizeof(msc_csw_t), MSC_EP_IN);
-        if (err) {
-            ESP_RETURN_ON_ERROR( clear_feature(device, MSC_EP_IN), TAG, "Clear feature failed" );
-            ESP_RETURN_ON_ERROR( msc_mass_reset(device), TAG, "Mass reset failed" );
-            return ESP_FAIL;
-        }
-    }
-
-    MSC_RETURN_ON_ERROR(err);
-
-    return check_csw(&csw, cbw->tag);
-}
-
-
-esp_err_t scsi_cmd_read10(msc_device_t *device,
-                          uint8_t *data,
-                          uint32_t sector_address,
-                          uint32_t num_sectors,
-                          uint32_t sector_size)
-{
-    cbw_read10_t cbw = {
-        CBW_BASE_INIT(IN_DIR, CBW_CMD_SIZE(cbw_read10_t), num_sectors * sector_size),
-        .opcode = SCSI_CMD_READ10,
-        .flags = 0, // lun
-        .address = __builtin_bswap32(sector_address),
-        .length = __builtin_bswap16(num_sectors),
-    };
-
-    return bot_execute_command(device, &cbw.base, data, num_sectors * sector_size);
-}
-
-esp_err_t scsi_cmd_write10(msc_device_t *device,
-                           const uint8_t *data,
-                           uint32_t sector_address,
-                           uint32_t num_sectors,
-                           uint32_t sector_size)
-{
-    cbw_write10_t cbw = {
-        CBW_BASE_INIT(OUT_DIR, CBW_CMD_SIZE(cbw_write10_t), num_sectors * sector_size),
-        .opcode = SCSI_CMD_WRITE10,
-        .address = __builtin_bswap32(sector_address),
-        .length = __builtin_bswap16(num_sectors),
-    };
-
-    return bot_execute_command(device, &cbw.base, (void *)data, num_sectors * sector_size);
-}
-
-esp_err_t scsi_cmd_read_capacity(msc_device_t *device, uint32_t *block_size, uint32_t *block_count)
-{
-    cbw_read_capacity_response_t response;
-
-    cbw_read_capacity_t cbw = {
-        CBW_BASE_INIT(IN_DIR, CBW_CMD_SIZE(cbw_read_capacity_t), sizeof(response)),
-        .opcode = SCSI_CMD_READ_CAPACITY,
-    };
-
-    MSC_RETURN_ON_ERROR( bot_execute_command(device, &cbw.base, &response, sizeof(response)) );
-
-    *block_count = __builtin_bswap32(response.block_count);
-    *block_size = __builtin_bswap32(response.block_size);
-
-    return ESP_OK;
-}
-
-esp_err_t scsi_cmd_unit_ready(msc_device_t *device)
-{
-    cbw_unit_ready_t cbw = {
-        CBW_BASE_INIT(IN_DIR, CBW_CMD_SIZE(cbw_unit_ready_t), 0),
-        .opcode = SCSI_CMD_TEST_UNIT_READY,
-    };
-
-    return bot_execute_command(device, &cbw.base, NULL, 0);
-}
-
-esp_err_t scsi_cmd_sense(msc_device_t *device, scsi_sense_data_t *sense)
-{
-    cbw_sense_response_t response;
-
-    cbw_sense_t cbw = {
-        CBW_BASE_INIT(IN_DIR, CBW_CMD_SIZE(cbw_sense_t), sizeof(response)),
-        .opcode = SCSI_CMD_REQUEST_SENSE,
-        .allocation_length = sizeof(response),
-    };
-
-    MSC_RETURN_ON_ERROR( bot_execute_command(device, &cbw.base, &response, sizeof(response)) );
-
-    if (sense->key) {
-        ESP_LOGD(TAG, "sense_key: 0x%02X, code: 0x%02X, qualifier: 0x%02X",
-                 response.sense_key, response.sense_code, response.sense_code_qualifier);
-    }
-
-    sense->key = response.sense_key;
-    sense->code = response.sense_code;
-    sense->code_q = response.sense_code_qualifier;
-
-    return ESP_OK;
-}
-
-esp_err_t scsi_cmd_inquiry(msc_device_t *device)
-{
-    cbw_inquiry_response_t response = { 0 };
-
-    cbw_inquiry_t cbw = {
-        CBW_BASE_INIT(IN_DIR, CBW_CMD_SIZE(cbw_inquiry_t), sizeof(response)),
-        .opcode = SCSI_CMD_INQUIRY,
-        .allocation_length = sizeof(response),
-    };
-
-    return bot_execute_command(device, &cbw.base, &response, sizeof(response) );
-}
-
-esp_err_t scsi_cmd_mode_sense(msc_device_t *device)
-{
-    mode_sense_response_t response = { 0 };
-
-    mode_sense_t cbw = {
-        CBW_BASE_INIT(IN_DIR, CBW_CMD_SIZE(mode_sense_t), sizeof(response)),
-        .opcode = SCSI_CMD_MODE_SENSE,
-        .pc_page_code = 0x3F,
-        .parameter_list_length = sizeof(response),
-    };
-
-    return bot_execute_command(device, &cbw.base, &response, sizeof(response) );
-}
-
-esp_err_t scsi_cmd_prevent_removal(msc_device_t *device, bool prevent)
-{
-    prevent_allow_medium_removal_t cbw = {
-        CBW_BASE_INIT(OUT_DIR, CBW_CMD_SIZE(prevent_allow_medium_removal_t), 0),
-        .opcode = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,
-        .prevent = 1,
-    };
-
-    return bot_execute_command(device, &cbw.base, NULL, 0);
-}

+ 0 - 3
examples/peripherals/usb/host/msc/components/msc/test/CMakeLists.txt

@@ -1,3 +0,0 @@
-idf_component_register(SRC_DIRS .
-                       INCLUDE_DIRS .
-                       REQUIRES unity usb msc tinyusb)

+ 0 - 302
examples/peripherals/usb/host/msc/components/msc/test/msc_device.c

@@ -1,302 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2019 Ha Thach (tinyusb.org)
- *
- * SPDX-License-Identifier: MIT
- *
- * SPDX-FileContributor: 2019-2021 Espressif Systems (Shanghai) CO LTD
- *
- */
-
-/*
- * 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.
- *
- */
-
-#include <stdint.h>
-#include "esp_log.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "tinyusb.h"
-#include "test_common.h"
-#include "soc/soc_caps.h"
-
-#if SOC_USB_OTG_SUPPORTED
-
-#define MASS_STORAGE_CLASS  0x08
-#define SCSI_COMMAND_SET    0x06
-#define BULK_ONLY_TRANSFER  0x50
-
-static const char *TAG = "msc_example";
-
-
-/**** Kconfig driven Descriptor ****/
-static const tusb_desc_device_t device_descriptor = {
-    .bLength = sizeof(device_descriptor),
-    .bDescriptorType = TUSB_DESC_DEVICE,
-    .bcdUSB = 0x0200,
-    .bDeviceClass = MASS_STORAGE_CLASS,
-    .bDeviceSubClass = SCSI_COMMAND_SET,
-    .bDeviceProtocol = BULK_ONLY_TRANSFER,
-    .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
-    .idVendor = USB_ESPRESSIF_VID,
-    .idProduct = 0x1234,
-    .bcdDevice = 0x0100,
-    .iManufacturer = 0x01,
-    .iProduct = 0x02,
-    .iSerialNumber = 0x03,
-    .bNumConfigurations = 0x01
-};
-
-const uint16_t msc_desc_config_len = TUD_CONFIG_DESC_LEN + CFG_TUD_MSC * TUD_MSC_DESC_LEN;
-static const uint8_t msc_desc_configuration[] = {
-    TUD_CONFIG_DESCRIPTOR(1, 4, 0, msc_desc_config_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
-    TUD_MSC_DESCRIPTOR(0, 5, 1, 0x80 | 1, 64),
-};
-
-
-void device_app(void)
-{
-    ESP_LOGI(TAG, "USB initialization");
-
-    tinyusb_config_t tusb_cfg = {
-        .device_descriptor = &device_descriptor,
-        .configuration_descriptor = msc_desc_configuration
-    };
-
-    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
-    ESP_LOGI(TAG, "USB initialization DONE");
-
-    while (1) {
-        vTaskDelay(100);
-    }
-}
-
-// whether host does safe-eject
-static bool ejected = false;
-
-// Some MCU doesn't have enough 8KB SRAM to store the whole disk
-// We will use Flash as read-only disk with board that has
-// CFG_EXAMPLE_MSC_READONLY defined
-
-uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = {
-    //------------- Block0: Boot Sector -------------//
-    // byte_per_sector    = DISK_BLOCK_SIZE; fat12_sector_num_16  = DISK_BLOCK_NUM;
-    // sector_per_cluster = 1; reserved_sectors = 1;
-    // fat_num            = 1; fat12_root_entry_num = 16;
-    // sector_per_fat     = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0;
-    // drive_number       = 0x80; media_type = 0xf8; extended_boot_signature = 0x29;
-    // filesystem_type    = "FAT12   "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC";
-    // FAT magic code at offset 510-511
-    {
-        0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
-        0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T', 'i', 'n', 'y', 'U',
-        'S', 'B', ' ', 'M', 'S', 'C', 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
-
-        // Zero up to 2 last bytes of FAT magic code
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 'F', 'A', 'T', '3', '2', ' ', ' ', ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
-    },
-
-    //------------- Block1: FAT12 Table -------------//
-    {
-        0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file
-    },
-
-    //------------- Block2: Root Directory -------------//
-    {
-        // first entry is volume label
-        'T', 'i', 'n', 'y', 'U', 'S', 'B', ' ', 'M', 'S', 'C', 0x08, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        // second entry is readme file
-        'R', 'E', 'A', 'D', 'M', 'E', ' ', ' ', 'T', 'X', 'T', 0x20, 0x00, 0xC6, 0x52, 0x6D,
-        0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00,
-        sizeof(README_CONTENTS) - 1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes)
-    },
-
-    //------------- Block3: Readme Content -------------//
-    README_CONTENTS
-};
-
-// Invoked when received SCSI_CMD_INQUIRY
-// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
-void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
-{
-    (void) lun;
-
-    const char vid[] = "TinyUSB";
-    const char pid[] = "Mass Storage";
-    const char rev[] = "1.0";
-
-    memcpy(vendor_id, vid, strlen(vid));
-    memcpy(product_id, pid, strlen(pid));
-    memcpy(product_rev, rev, strlen(rev));
-}
-
-// Invoked when received Test Unit Ready command.
-// return true allowing host to read/write this LUN e.g SD card inserted
-bool tud_msc_test_unit_ready_cb(uint8_t lun)
-{
-    (void) lun;
-
-    // RAM disk is ready until ejected
-    if (ejected) {
-        tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
-        return false;
-    }
-
-    return true;
-}
-
-// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
-// Application update block count and block size
-void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size)
-{
-    (void) lun;
-
-    *block_count = DISK_BLOCK_NUM;
-    *block_size  = DISK_BLOCK_SIZE;
-}
-
-// Invoked when received Start Stop Unit command
-// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
-// - Start = 1 : active mode, if load_eject = 1 : load disk storage
-bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
-{
-    (void) lun;
-    (void) power_condition;
-
-    if ( load_eject ) {
-        if (start) {
-            // load disk storage
-        } else {
-            // unload disk storage
-            ejected = true;
-        }
-    }
-
-    return true;
-}
-
-// Callback invoked when received READ10 command.
-// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
-int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize)
-{
-    (void) lun;
-
-    uint8_t const *addr = msc_disk[lba] + offset;
-    memcpy(buffer, addr, bufsize);
-
-    return bufsize;
-}
-
-// Callback invoked when received WRITE10 command.
-// Process data in buffer to disk's storage and return number of written bytes
-int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize)
-{
-    (void) lun;
-
-#ifndef CFG_EXAMPLE_MSC_READONLY
-    uint8_t *addr = msc_disk[lba] + offset;
-    memcpy(addr, buffer, bufsize);
-#else
-    (void) lba; (void) offset; (void) buffer;
-#endif
-
-    return bufsize;
-}
-
-// Callback invoked when received an SCSI command not in built-in list below
-// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
-// - READ10 and WRITE10 has their own callbacks
-int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize)
-{
-    // read10 & write10 has their own callback and MUST not be handled here
-
-    void const *response = NULL;
-    uint16_t resplen = 0;
-
-    // most scsi handled is input
-    bool in_xfer = true;
-
-    switch (scsi_cmd[0]) {
-    case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
-        // Host is about to read/write etc ... better not to disconnect disk
-        resplen = 0;
-        break;
-
-    default:
-        // Set Sense = Invalid Command Operation
-        tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
-
-        // negative means error -> tinyusb could stall and/or response with failed status
-        resplen = -1;
-        break;
-    }
-
-    // return resplen must not larger than bufsize
-    if ( resplen > bufsize ) {
-        resplen = bufsize;
-    }
-
-    if ( response && (resplen > 0) ) {
-        if (in_xfer) {
-            memcpy(buffer, response, resplen);
-        } else {
-            // SCSI output
-        }
-    }
-
-    return resplen;
-}
-
-#endif /* SOC_USB_OTG_SUPPORTED */

+ 0 - 19
examples/peripherals/usb/host/msc/components/msc/test/test_common.h

@@ -1,19 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-#pragma once
-
-enum {
-    // FatFS only allows to format disks with number of blocks greater than 128
-    DISK_BLOCK_NUM  = 128 + 1,
-    DISK_BLOCK_SIZE = 512
-};
-
-#define README_CONTENTS \
-"This is tinyusb's MassStorage Class demo.\r\n\r\n\
-If you find any bugs or get any questions, feel free to file an\r\n\
-issue at github.com/hathach/tinyusb"
-
-void device_app(void);

+ 0 - 325
examples/peripherals/usb/host/msc/components/msc/test/test_msc.c

@@ -1,325 +0,0 @@
-
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: CC0-1.0
- */
-
-#include "unity.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "freertos/queue.h"
-#include "freertos/semphr.h"
-#include "esp_err.h"
-#include "esp_log.h"
-#include "esp_private/usb_phy.h"
-#include "usb/usb_host.h"
-#include "msc_host.h"
-#include "msc_host_vfs.h"
-#include "ffconf.h"
-#include "ff.h"
-#include "esp_vfs.h"
-#include "test_common.h"
-#include "soc/usb_wrap_struct.h"
-#include "soc/soc_caps.h"
-
-#if SOC_USB_OTG_SUPPORTED
-
-static const char *TAG = "APP";
-
-#define ESP_OK_ASSERT(exp) TEST_ASSERT_EQUAL(ESP_OK, exp)
-
-static esp_vfs_fat_mount_config_t mount_config = {
-    .format_if_mount_failed = false,
-    .max_files = 3,
-    .allocation_unit_size = 1024,
-};
-
-static QueueHandle_t app_queue;
-static SemaphoreHandle_t ready_to_deinit_usb;
-static msc_host_device_handle_t device;
-static msc_host_vfs_handle_t vfs_handle;
-static volatile bool waiting_for_sudden_disconnect;
-static usb_phy_handle_t phy_hdl = NULL;
-
-static void force_conn_state(bool connected, TickType_t delay_ticks)
-{
-    TEST_ASSERT(phy_hdl);
-    if (delay_ticks > 0) {
-        //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0.
-        vTaskDelay(delay_ticks);
-    }
-    ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN));
-}
-
-static void msc_event_cb(const msc_host_event_t *event, void *arg)
-{
-    if (waiting_for_sudden_disconnect) {
-        waiting_for_sudden_disconnect = false;
-        TEST_ASSERT_EQUAL(MSC_DEVICE_DISCONNECTED, event->event);
-    }
-
-    if (event->event == MSC_DEVICE_CONNECTED) {
-        printf("MSC_DEVICE_CONNECTED\n");
-    } else {
-        printf("MSC_DEVICE_DISCONNECTED\n");
-    }
-
-    xQueueSend(app_queue, event, 10);
-}
-
-static const char *TEST_STRING = "Hello World!";
-static const char *FILE_NAME = "/usb/ESP32.txt";
-
-static void write_read_file(const char *file_path)
-{
-    char line[64];
-
-    ESP_LOGI(TAG, "Writing file");
-    FILE *f = fopen(file_path, "w");
-    TEST_ASSERT(f);
-    fprintf(f, TEST_STRING);
-    fclose(f);
-
-    ESP_LOGI(TAG, "Reading file");
-    TEST_ASSERT(fopen(file_path, "r"));
-    fgets(line, sizeof(line), f);
-    fclose(f);
-    // strip newline
-    char *pos = strchr(line, '\n');
-    if (pos) {
-        *pos = '\0';
-    }
-    TEST_ASSERT_EQUAL_STRING(line, TEST_STRING);
-    ESP_LOGI(TAG, "Done");
-}
-
-static bool file_exists(const char *file_path)
-{
-    return ( access(file_path, F_OK) == 0 );
-}
-
-// Handles common USB host library events
-static void handle_usb_events(void *args)
-{
-    uint32_t end_flags = 0;
-
-    while (1) {
-        uint32_t event_flags;
-        usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
-        // Release devices once all clients has deregistered
-        if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
-            printf("USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS\n");
-            usb_host_device_free_all();
-            end_flags |= 1;
-        }
-        // Give ready_to_deinit_usb semaphore to indicate that USB Host library
-        // can be deinitialized, and terminate this task.
-        if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
-            printf("USB_HOST_LIB_EVENT_FLAGS_ALL_FREE\n");
-            end_flags |= 2;
-        }
-
-        if (end_flags == 3) {
-            xSemaphoreGive(ready_to_deinit_usb);
-            break;
-        }
-    }
-    vTaskDelete(NULL);
-}
-
-static void check_file_content(const char *file_path, const char *expected)
-{
-    ESP_LOGI(TAG, "Reading %s:", file_path);
-    FILE *file = fopen(file_path, "r");
-    TEST_ASSERT(file)
-
-    char content[200];
-    fread(content, 1, sizeof(content), file);
-    TEST_ASSERT_EQUAL_STRING(content, expected);
-    fclose(file);
-}
-
-static void check_sudden_disconnect(void)
-{
-    uint8_t data[512];
-    const size_t DATA_SIZE = sizeof(data);
-
-    ESP_LOGI(TAG, "Creating test.tx");
-    FILE *file = fopen("/usb/test.txt", "w");
-    TEST_ASSERT(file);
-
-    ESP_LOGI(TAG, "Write data");
-    TEST_ASSERT_EQUAL(DATA_SIZE, fwrite(data, 1, DATA_SIZE, file));
-    TEST_ASSERT_EQUAL(DATA_SIZE, fwrite(data, 1, DATA_SIZE, file));
-    TEST_ASSERT_EQUAL(0, fflush(file));
-
-    ESP_LOGI(TAG, "Trigger a disconnect");
-    //Trigger a disconnect
-    waiting_for_sudden_disconnect = true;
-    force_conn_state(false, 0);
-
-    // Make sure flag was leared in callback
-    vTaskDelay( pdMS_TO_TICKS(100) );
-    TEST_ASSERT_FALSE(waiting_for_sudden_disconnect);
-
-    ESP_LOGI(TAG, "Write data after disconnect");
-    TEST_ASSERT_NOT_EQUAL( DATA_SIZE, fwrite(data, 1, DATA_SIZE, file));
-
-    fclose(file);
-}
-
-static void msc_setup(void)
-{
-    BaseType_t task_created;
-
-    ready_to_deinit_usb = xSemaphoreCreateBinary();
-
-    TEST_ASSERT( app_queue = xQueueCreate(5, sizeof(msc_host_event_t)) );
-
-    //Initialize the internal USB PHY to connect to the USB OTG peripheral. We manually install the USB PHY for testing
-    usb_phy_config_t phy_config = {
-        .controller = USB_PHY_CTRL_OTG,
-        .target = USB_PHY_TARGET_INT,
-        .otg_mode = USB_OTG_MODE_HOST,
-        .otg_speed = USB_PHY_SPEED_UNDEFINED,   //In Host mode, the speed is determined by the connected device
-        .gpio_conf = NULL,
-    };
-    ESP_OK_ASSERT(usb_new_phy(&phy_config, &phy_hdl));
-    const usb_host_config_t host_config = {
-        .skip_phy_setup = true,
-        .intr_flags = ESP_INTR_FLAG_LEVEL1,
-    };
-    ESP_OK_ASSERT( usb_host_install(&host_config) );
-
-    task_created = xTaskCreatePinnedToCore(handle_usb_events, "usb_events", 2048, NULL, 2, NULL, 0);
-    TEST_ASSERT(task_created);
-
-    const msc_host_driver_config_t msc_config = {
-        .create_backround_task = true,
-        .callback = msc_event_cb,
-        .stack_size = 4096,
-        .task_priority = 5,
-    };
-    ESP_OK_ASSERT( msc_host_install(&msc_config) );
-
-    ESP_LOGI(TAG, "Waiting for USB stick to be connected");
-    msc_host_event_t app_event;
-    xQueueReceive(app_queue, &app_event, portMAX_DELAY);
-    TEST_ASSERT_EQUAL(MSC_DEVICE_CONNECTED, app_event.event);
-    uint8_t device_addr = app_event.device.address;
-
-    ESP_OK_ASSERT( msc_host_install_device(device_addr, &device) );
-    ESP_OK_ASSERT( msc_host_vfs_register(device, "/usb", &mount_config, &vfs_handle) );
-}
-
-static void msc_teardown(void)
-{
-    // Wait to finish any ongoing USB operations
-    vTaskDelay(100);
-
-    ESP_OK_ASSERT( msc_host_vfs_unregister(vfs_handle) );
-    ESP_OK_ASSERT( msc_host_uninstall_device(device) );
-    ESP_OK_ASSERT( msc_host_uninstall() );
-
-    xSemaphoreTake(ready_to_deinit_usb, portMAX_DELAY);
-    vSemaphoreDelete(ready_to_deinit_usb);
-    ESP_OK_ASSERT( usb_host_uninstall() );
-    //Tear down USB PHY
-    ESP_OK_ASSERT(usb_del_phy(phy_hdl));
-    phy_hdl = NULL;
-
-    vQueueDelete(app_queue);
-}
-
-static void write_read_sectors(void)
-{
-    uint8_t write_data[DISK_BLOCK_SIZE];
-    uint8_t read_data[DISK_BLOCK_SIZE];
-
-    memset(write_data, 0x55, DISK_BLOCK_SIZE);
-    memset(read_data, 0, DISK_BLOCK_SIZE);
-
-    msc_host_write_sector(device, 10, write_data, DISK_BLOCK_SIZE);
-    msc_host_read_sector(device, 10, read_data, DISK_BLOCK_SIZE);
-
-    TEST_ASSERT_EQUAL_MEMORY(write_data, read_data, DISK_BLOCK_SIZE);
-}
-
-static void erase_storage(void)
-{
-    uint8_t data[DISK_BLOCK_SIZE];
-    memset(data, 0xFF, DISK_BLOCK_SIZE);
-
-    for (int block = 0; block < DISK_BLOCK_NUM; block++) {
-        msc_host_write_sector(device, block, data, DISK_BLOCK_SIZE);
-    }
-}
-
-TEST_CASE("write_and_read_file", "[usb_msc]")
-{
-    msc_setup();
-    write_read_file(FILE_NAME);
-    msc_teardown();
-}
-
-TEST_CASE("sudden_disconnect", "[usb_msc]")
-{
-    msc_setup();
-    check_sudden_disconnect();
-    msc_teardown();
-}
-
-TEST_CASE("sectors_can_be_written_and_read", "[usb_msc]")
-{
-    msc_setup();
-    write_read_sectors();
-    msc_teardown();
-}
-
-TEST_CASE("check_README_content", "[usb_msc]")
-{
-    msc_setup();
-    check_file_content("/usb/README.TXT", README_CONTENTS);
-    msc_teardown();
-}
-
-/**
- * @brief USB MSC format testcase
- * @attention This testcase deletes all content on the USB MSC device.
- *            The device must be reset in order to contain the FILE_NAME again.
- */
-TEST_CASE("can_be_formated", "[usb_msc]")
-{
-    printf("Create file\n");
-    msc_setup();
-    write_read_file(FILE_NAME);
-    msc_teardown();
-
-    printf("File exists after mounting again\n");
-    msc_setup();
-    TEST_ASSERT(file_exists(FILE_NAME));
-    printf("Erase storage device\n");
-    erase_storage();
-    msc_teardown();
-
-    printf("Check file does not exist after formatting\n");
-    mount_config.format_if_mount_failed = true;
-    msc_setup();
-    TEST_ASSERT_FALSE(file_exists(FILE_NAME));
-    msc_teardown();
-    mount_config.format_if_mount_failed = false;
-}
-
-TEST_CASE("mock_device_app", "[usb_msc_device][ignore]")
-{
-    device_app();
-}
-
-#endif

+ 1 - 2
examples/peripherals/usb/host/msc/main/CMakeLists.txt

@@ -1,4 +1,3 @@
 idf_component_register(SRCS "msc_example_main.c"
                     INCLUDE_DIRS ""
-                    REQUIRES usb msc fatfs vfs)
-target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
+                    REQUIRES usb vfs)

+ 4 - 0
examples/peripherals/usb/host/msc/main/idf_component.yml

@@ -0,0 +1,4 @@
+## IDF Component Manager Manifest File
+dependencies:
+  idf: ">=4.4"
+  usb_host_msc: "^1.0.0"

+ 3 - 4
examples/peripherals/usb/host/msc/main/msc_example_main.c

@@ -16,7 +16,6 @@
 #include "msc_host.h"
 #include "msc_host_vfs.h"
 #include "ffconf.h"
-#include "ff.h"
 #include "esp_vfs.h"
 #include "errno.h"
 #include "hal/usb_hal.h"
@@ -57,8 +56,8 @@ static void print_device_info(msc_host_device_info_t *info)
 
     printf("Device info:\n");
     printf("\t Capacity: %llu MB\n", capacity);
-    printf("\t Sector size: %u\n", info->sector_size);
-    printf("\t Sector count: %u\n", info->sector_count);
+    printf("\t Sector size: %"PRIu32"\n", info->sector_size);
+    printf("\t Sector count: %"PRIu32"\n", info->sector_count);
     printf("\t PID: 0x%4X \n", info->idProduct);
     printf("\t VID: 0x%4X \n", info->idVendor);
     wprintf(L"\t iProduct: %S \n", info->iProduct);
@@ -161,7 +160,7 @@ void app_main(void)
     BaseType_t task_created;
 
     const gpio_config_t input_pin = {
-        .pin_bit_mask = (1 << USB_DISCONNECT_PIN),
+        .pin_bit_mask = BIT64(USB_DISCONNECT_PIN),
         .mode = GPIO_MODE_INPUT,
         .pull_up_en = GPIO_PULLUP_ENABLE,
     };

+ 0 - 11
tools/test_apps/peripherals/usb/CMakeLists.txt

@@ -1,11 +0,0 @@
-# The following lines of boilerplate have to be in your project's
-# CMakeLists in this exact order for cmake to work correctly
-cmake_minimum_required(VERSION 3.16)
-
-set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/peripherals/usb/host/cdc/common
-                         $ENV{IDF_PATH}/examples/peripherals/usb/host/msc/components/)
-
-# Set the components to include the tests for.
-set(TEST_COMPONENTS "cdc_acm_host" "msc" CACHE STRING "List of components to test")
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-project(usb_test_app)

+ 0 - 26
tools/test_apps/peripherals/usb/README.md

@@ -1,26 +0,0 @@
-| Supported Targets | ESP32-S2 | ESP32-S3 |
-| ----------------- | -------- | -------- |
-
-# USB Host Class driver test project
-Main purpose of this application is to test the USB Host Class drivers.
-
-## CDC-ACM driver
-
-It tests basic functionality of the driver like open/close/read/write operations,
-advanced features like CDC control request, multi-threaded or multi-device access,
-as well as reaction to sudden disconnection and other error states.
-
-### Hardware Required
-
-This test expects that TinyUSB dual CDC device with VID = 0x303A and PID = 0x4002
-is connected to the USB host.
-
-## MSC driver
-
-Basic functionality such as MSC device install/uninstall, file operatons, 
-raw access to MSC device and sudden disconnect is tested.
-
-### Hardware Required
-
-This test requires two ESP32-S2/S3 boards with a interconnected USB perpherals,
-one acting as host running MSC host driver and another MSC device driver (tinyusb).

+ 0 - 3
tools/test_apps/peripherals/usb/main/CMakeLists.txt

@@ -1,3 +0,0 @@
-idf_component_register(SRCS "usb_test_main.c"
-                       INCLUDE_DIRS ""
-                       REQUIRES unity driver usb)

+ 0 - 44
tools/test_apps/peripherals/usb/main/usb_test_main.c

@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "unity.h"
-#include "esp_heap_caps.h"
-
-static size_t before_free_8bit;
-static size_t before_free_32bit;
-
-#define TEST_MEMORY_LEAK_THRESHOLD (-10000) // @todo MSC test are leaking memory
-static void check_leak(size_t before_free, size_t after_free, const char *type)
-{
-    ssize_t delta = after_free - before_free;
-    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
-    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
-}
-
-void app_main(void)
-{
-    UNITY_BEGIN();
-    unity_run_menu();
-    UNITY_END();
-}
-
-/* setUp runs before every test */
-void setUp(void)
-{
-    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
-    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
-}
-
-/* tearDown runs after every test */
-void tearDown(void)
-{
-    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
-    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
-    check_leak(before_free_8bit, after_free_8bit, "8BIT");
-    check_leak(before_free_32bit, after_free_32bit, "32BIT");
-}

+ 0 - 40
tools/test_apps/peripherals/usb/pytest_usb_host.py

@@ -1,40 +0,0 @@
-# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
-# SPDX-License-Identifier: CC0-1.0
-
-from typing import Tuple
-
-import pytest
-from pytest_embedded_idf.dut import IdfDut
-
-
-@pytest.mark.esp32s2
-@pytest.mark.esp32s3
-@pytest.mark.usb_host
-@pytest.mark.parametrize('count', [
-    2,
-], indirect=True)
-def test_usb_host(dut: Tuple[IdfDut, IdfDut]) -> None:
-    device = dut[0]
-    host = dut[1]
-
-    # 1.1 Prepare USB device for CDC test
-    device.expect_exact('Press ENTER to see the list of tests.')
-    device.write('[cdc_acm_device]')
-    device.expect_exact('USB initialization DONE')
-
-    # 1.2 Run CDC test
-    host.expect_exact('Press ENTER to see the list of tests.')
-    host.write('[cdc_acm]')
-    host.expect_unity_test_output()
-    host.expect_exact("Enter next test, or 'enter' to see menu")
-
-    # 2.1 Prepare USB device for MSC test
-    device.serial.hard_reset()
-    device.expect_exact('Press ENTER to see the list of tests.')
-    device.write('[usb_msc_device]')
-    device.expect_exact('USB initialization DONE')
-
-    # 2.2 Run MSC test
-    host.write('[usb_msc]')
-    host.expect_unity_test_output()
-    host.expect_exact("Enter next test, or 'enter' to see menu")

+ 0 - 16
tools/test_apps/peripherals/usb/sdkconfig.defaults

@@ -1,16 +0,0 @@
-# Configure TinyUSB, it will be used to mock USB devices
-CONFIG_TINYUSB=y
-CONFIG_TINYUSB_MSC_ENABLED=y
-CONFIG_TINYUSB_CDC_ENABLED=y
-CONFIG_TINYUSB_CDC_COUNT=2
-
-# Disable watchdogs, they'd get triggered during unity interactive menu
-CONFIG_ESP_INT_WDT=n
-CONFIG_ESP_TASK_WDT=n
-
-# Run-time checks of Heap and Stack
-CONFIG_HEAP_POISONING_COMPREHENSIVE=y
-CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y
-CONFIG_COMPILER_STACK_CHECK=y
-
-CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y