diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index e56f357b9..f7eb832d0 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -494,6 +494,17 @@ build_example_usb_host_usb_cdc_4g_module: variables: EXAMPLE_DIR: examples/usb/host/usb_cdc_4g_module +build_example_usb_host_usb_cdc_basic: + extends: + - .build_examples_template + - .rules:build:example_usb_host_usb_cdc_basic + parallel: + matrix: + - IMAGE: espressif/idf:release-v4.4 + - IMAGE: espressif/idf:release-v5.1 + variables: + EXAMPLE_DIR: examples/usb/host/usb_cdc_basic + build_example_utilities_xz_decompress_file: extends: - .build_examples_template diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index 5ba5f1154..912c93456 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -234,6 +234,7 @@ - "components/sensors/sensor_hub/include/hal/light_sensor_hal.h" - "components/sensors/sensor_hub/include/iot_sensor_hub.h" - "components/sensors/sensor_hub/include/sensor_type.h" + - "components/usb/iot_usbh_cdc/include/iot_usbh_cdc.h" - "components/usb/usb_device_uvc/include/usb_device_uvc.h" - "components/usb/usb_stream/include/usb_stream.h" - "components/zero_detection/include/zero_detection.h" @@ -359,6 +360,9 @@ .patterns-example_usb_host_usb_cdc_4g_module: &patterns-example_usb_host_usb_cdc_4g_module - "examples/usb/host/usb_cdc_4g_module/**/*" +.patterns-example_usb_host_usb_cdc_basic: &patterns-example_usb_host_usb_cdc_basic + - "examples/usb/host/usb_cdc_basic/**/*" + .patterns-example_utilities_xz_decompress_file: &patterns-example_utilities_xz_decompress_file - "examples/utilities/xz_decompress_file/**/*" @@ -911,6 +915,20 @@ - <<: *if-dev-push changes: *patterns-example_usb_host_usb_cdc_4g_module +.rules:build:example_usb_host_usb_cdc_basic: + rules: + - <<: *if-protected + - <<: *if-label-build + - <<: *if-trigger-job + - <<: *if-dev-push + changes: *patterns-build_system + - <<: *if-dev-push + changes: *patterns-components_usb_iot_usbh + - <<: *if-dev-push + changes: *patterns-components_usb_iot_usbh_cdc + - <<: *if-dev-push + changes: *patterns-example_usb_host_usb_cdc_basic + .rules:build:example_utilities_xz_decompress_file: rules: - <<: *if-protected diff --git a/components/usb/iot_usbh_cdc/CHANGELOG.md b/components/usb/iot_usbh_cdc/CHANGELOG.md index 9498355b2..951b2d91d 100644 --- a/components/usb/iot_usbh_cdc/CHANGELOG.md +++ b/components/usb/iot_usbh_cdc/CHANGELOG.md @@ -1,5 +1,9 @@ # ChangeLog +## v0.2.2 - 2023-12-08 + +* Add doc and example + ## v0.2.1 - 2023-11-23 * Fix possible cmake_utilities dependency issue diff --git a/components/usb/iot_usbh_cdc/README.md b/components/usb/iot_usbh_cdc/README.md index a1ec4bb82..c0bdc61c3 100644 --- a/components/usb/iot_usbh_cdc/README.md +++ b/components/usb/iot_usbh_cdc/README.md @@ -1,38 +1,36 @@ -## USB Host CDC +## iot_usbh_cdc Component -This component implements a simple version of the USB CDC host function. It only retains the default control endpoint and bulk transfer endpoints, which streamlines the enumeration logic of the USB host. Users only need to bind the USB CDC device endpoint address to achieve fast Initialization. The component is suitable for the CDC-like vendor classes that require high startup speed. +This component implements a simple version of the USB host CDC driver. The API is designed similarly to [ESP-IDF UART driver](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/uart.html), which can be used to replace the original UART driver to realize the update from UART to USB. -The design logic of the component API is similar to the [ESP-IDF UART driver](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/uart.html) interface, which can directly replace the UART interface to realize the update of the original code from UART to USB. +**Features:** -### API Guide +1. Similar API to ESP-IDF UART driver +2. Support USB CDC device +3. Support USB Vendor device +4. Support USB CDC multiple interface -1. Using `usbh_cdc_driver_install` to configure and start internal USB tasks, most importantly the CDC bulk endpoint addresses `bulk_in_ep_addr` and `bulk_out_ep_addr` is required to be specified for communication, and the transfer buffer memory size needs to be configured too. user is allowed to config descriptor details too through `bulk_in_ep` and `bulk_out_ep`. +### User Guide -```c -/* @brief install usbh cdc driver with bulk endpoint configs and size of internal ringbuffer*/ -static usbh_cdc_config_t config = { - /* use default endpoint descriptor with user address */ - .bulk_in_ep_addr = EXAMPLE_BULK_IN_EP_ADDR, - .bulk_out_ep_addr = EXAMPLE_BULK_OUT_EP_ADDR, - .rx_buffer_size = IN_RINGBUF_SIZE, - .tx_buffer_size = OUT_RINGBUF_SIZE, - .conn_callback = usb_connect_callback, - .disconn_callback = usb_disconnect_callback, -}; +Please refer: https://docs.espressif.com/projects/esp-iot-solution/en/latest/usb/usb_host_iot_usbh_cdc.html -/* install USB host CDC driver */ -usbh_cdc_driver_install(&config); +### Add component to your project -/* Waiting for USB device connected */ -usbh_cdc_wait_connect(portMAX_DELAY); +Please use the component manager command `add-dependency` to add the `iot_usbh_cdc` to your project's dependency, during the `CMake` step the component will be downloaded automatically + +``` +idf.py add-dependency "espressif/iot_usbh_cdc=*" ``` -2. After the driver initialization, the internal state machine will automatically handle the hot plug of the USB, and user can also configure the hot plug related callback function `conn_callback` `disconn_callback`. -3. `usbh_cdc_wait_connect` can be used to block task until USB CDC Device is connected or timeout. -4. After successfully connected, the host will automatically receive USB data from CDC device to the internal `ringbuffer`, user can poll `usbh_cdc_get_buffered_data_len` to read buffered data size or register a receive callback to get notified when data is ready. Then `usbh_cdc_read_bytes` can be used to read buffered data out. -5. `usbh_cdc_write_bytes` can be used to send data to USB Device. The data is first written to the internal transmit `ringbuffer`,then will be sent out during USB bus free. -6. `usbh_cdc_driver_delete` can uninstall the USB driver completely to release all resources. +### Examples + +Please use the component manager command `create-project-from-example` to create the project from the example template + +* USB Host CDC Basic Example + +``` +idf.py create-project-from-example "espressif/iot_usbh_cdc=*:usb_cdc_basic" +``` -### CDC Multiple Interface Support +Then the example will be downloaded in the current folder, you can check into it for build and flash. -This component supports enable multiple CDC interfaces, each interface contains an IN and OUT endpoint. Users can communicate with the specified interfaces using `usbh_cdc_itf_read_bytes` and `usbh_cdc_itf_write_bytes`. +> Or you can download examples from esp-iot-solution repository: [usb_cdc_basic](https://github.com/espressif/esp-iot-solution/tree/master/examples/usb/host/usb_cdc_basic). diff --git a/components/usb/iot_usbh_cdc/idf_component.yml b/components/usb/iot_usbh_cdc/idf_component.yml index 3a0e21e42..b3e5bcbe5 100644 --- a/components/usb/iot_usbh_cdc/idf_component.yml +++ b/components/usb/iot_usbh_cdc/idf_component.yml @@ -1,10 +1,11 @@ -version: "0.2.1" +version: "0.2.2" targets: - esp32s2 - esp32s3 description: Simple USB Host CDC driver maintained in esp-iot-solution url: https://github.com/espressif/esp-iot-solution/tree/master/components/usb/iot_usbh_cdc repository: https://github.com/espressif/esp-iot-solution/tree/master/components/usb/iot_usbh_cdc +documentation: https://docs.espressif.com/projects/esp-iot-solution/en/latest/usb/usb_host_iot_usbh_cdc.html issues: https://github.com/espressif/esp-iot-solution/issues dependencies: idf: ">=4.4.1" @@ -13,3 +14,5 @@ dependencies: version: "0.*" public: true override_path: "../iot_usbh" +examples: + - path: ../../../examples/usb/host/usb_cdc_basic diff --git a/docs/Doxyfile b/docs/Doxyfile index 3a5351734..617fb0203 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -42,6 +42,7 @@ INPUT = \ $(PROJECT_PATH)/components/sensors/sensor_hub/include/hal/light_sensor_hal.h \ $(PROJECT_PATH)/components/sensors/sensor_hub/include/iot_sensor_hub.h \ $(PROJECT_PATH)/components/sensors/sensor_hub/include/sensor_type.h \ + $(PROJECT_PATH)/components/usb/iot_usbh_cdc/include/iot_usbh_cdc.h \ $(PROJECT_PATH)/components/usb/usb_device_uvc/include/usb_device_uvc.h \ $(PROJECT_PATH)/components/usb/usb_stream/include/usb_stream.h \ $(PROJECT_PATH)/components/zero_detection/include/zero_detection.h \ diff --git a/docs/en/usb/usb_host_index.rst b/docs/en/usb/usb_host_index.rst index 49ddd48aa..288629b4c 100644 --- a/docs/en/usb/usb_host_index.rst +++ b/docs/en/usb/usb_host_index.rst @@ -6,4 +6,5 @@ USB Host Drivers .. toctree:: :maxdepth: 1 - USB UVC/UAC Host \ No newline at end of file + USB UVC/UAC Host + USB CDC Host \ No newline at end of file diff --git a/docs/en/usb/usb_host_iot_usbh_cdc.rst b/docs/en/usb/usb_host_iot_usbh_cdc.rst new file mode 100644 index 000000000..4734337a5 --- /dev/null +++ b/docs/en/usb/usb_host_iot_usbh_cdc.rst @@ -0,0 +1,55 @@ +USB Host CDC +===================== + +:link_to_translation:`zh_CN:[中文]` + +The ``iot_usbh_cdc`` component implements a simple version of the USB host CDC driver. The API is designed similar like `ESP-IDF UART driver `_, which can be used to replace the original UART driver to realize the update from UART to USB. + +User Guide +--------------- + +1. Using ``usbh_cdc_driver_install`` to configure, user can simply configure the bulk endpoint address and the size of the internal ringbuffer, user can also configure the hot plug related callback function ``conn_callback`` ``disconn_callback``. + +.. code:: c + + /* install usbh cdc driver with bulk endpoint configs and size of internal ringbuffer */ + static usbh_cdc_config_t config = { + /* use default endpoint descriptor with user address */ + .bulk_in_ep_addr = EXAMPLE_BULK_IN_EP_ADDR, + .bulk_out_ep_addr = EXAMPLE_BULK_OUT_EP_ADDR, + .rx_buffer_size = IN_RINGBUF_SIZE, + .tx_buffer_size = OUT_RINGBUF_SIZE, + .conn_callback = usb_connect_callback, + .disconn_callback = usb_disconnect_callback, + }; + /* if user want to use multiple interfaces, can configure like this */ + #if (EXAMPLE_BULK_ITF_NUM > 1) + config.itf_num = 2; + config.bulk_in_ep_addrs[1] = EXAMPLE_BULK_IN1_EP_ADDR; + config.bulk_out_ep_addrs[1] = EXAMPLE_BULK_OUT1_EP_ADDR; + config.rx_buffer_sizes[1] = IN_RINGBUF_SIZE; + config.tx_buffer_sizes[1] = OUT_RINGBUF_SIZE; + #endif + + /* install USB host CDC driver */ + usbh_cdc_driver_install(&config); + + /* Waiting for USB device connected */ + usbh_cdc_wait_connect(portMAX_DELAY); + +2. After the driver initialization, the internal state machine will automatically handle the hot plug of the USB. +3. ``usbh_cdc_wait_connect`` can be used to block task until USB CDC Device is connected or timeout. +4. After successfully connected, the host will automatically receive USB data from CDC device to the internal ``ringbuffer``, user can poll ``usbh_cdc_get_buffered_data_len`` to read buffered data size or register a receive callback to get notified when data is ready. Then ``usbh_cdc_read_bytes`` can be used to read buffered data out. +5. ``usbh_cdc_write_bytes`` can be used to send data to USB Device. The data is first written to the internal transmit ``ringbuffer``,then will be sent out during USB bus free. +6. ``usbh_cdc_driver_delete`` can uninstall the USB driver completely to release all resources. +7. If config multiple CDC interfaces, each interface contains an IN and OUT endpoint. Users can communicate with the specified interfaces using ``usbh_cdc_itf_read_bytes`` and ``usbh_cdc_itf_write_bytes``. + +Examples +------------------------------- + +:example:`usb/host/usb_cdc_basic` + +API Reference +------------------------------- + +.. include-build-file:: inc/iot_usbh_cdc.inc diff --git a/docs/zh_CN/usb/usb_host_index.rst b/docs/zh_CN/usb/usb_host_index.rst index e005e7366..e31f1f8ea 100644 --- a/docs/zh_CN/usb/usb_host_index.rst +++ b/docs/zh_CN/usb/usb_host_index.rst @@ -6,4 +6,5 @@ USB 主机驱动 .. toctree:: :maxdepth: 1 - USB UVC/UAC 主机 \ No newline at end of file + USB UVC/UAC 主机 + USB CDC 主机 \ No newline at end of file diff --git a/docs/zh_CN/usb/usb_host_iot_usbh_cdc.rst b/docs/zh_CN/usb/usb_host_iot_usbh_cdc.rst new file mode 100644 index 000000000..33d7e9e69 --- /dev/null +++ b/docs/zh_CN/usb/usb_host_iot_usbh_cdc.rst @@ -0,0 +1,55 @@ +USB 主机 CDC +===================== + +:link_to_translation:`en:[English]` + +``iot_usbh_cdc`` 组件实现了一个 USB 主机 CDC 驱动的简化版本。该 API 的设计类似于 `ESP-IDF UART 驱动程序 `_,可在一些应用中替代 UART,快速实现从 UART 到 USB 的迁移。 + +使用指南 +--------------- + +1. 使用 ``usbh_cdc_driver_install`` 配置,用户可以简单配置 bulk 端点地址和内部 ringbuffer 的大小,除此之外,用户还可以配置热插拔相关的回调函数 ``conn_callback`` ``disconn_callback``: + +.. code:: c + + /* 安装 USB 主机 CDC 驱动程序,配置 bulk 端点地址和内部 ringbuffer 的大小 */ + static usbh_cdc_config_t config = { + /* use default endpoint descriptor with user address */ + .bulk_in_ep_addr = EXAMPLE_BULK_IN_EP_ADDR, + .bulk_out_ep_addr = EXAMPLE_BULK_OUT_EP_ADDR, + .rx_buffer_size = IN_RINGBUF_SIZE, + .tx_buffer_size = OUT_RINGBUF_SIZE, + .conn_callback = usb_connect_callback, + .disconn_callback = usb_disconnect_callback, + }; + /* 如果用户想要使用多个接口,可以像这样配置 */ + #if (EXAMPLE_BULK_ITF_NUM > 1) + config.itf_num = 2; + config.bulk_in_ep_addrs[1] = EXAMPLE_BULK_IN1_EP_ADDR; + config.bulk_out_ep_addrs[1] = EXAMPLE_BULK_OUT1_EP_ADDR; + config.rx_buffer_sizes[1] = IN_RINGBUF_SIZE; + config.tx_buffer_sizes[1] = OUT_RINGBUF_SIZE; + #endif + + /* 安装 USB 主机 CDC 驱动程序 */ + usbh_cdc_driver_install(&config); + + /* 等待 USB 设备连接 */ + usbh_cdc_wait_connect(portMAX_DELAY); + +2. 驱动程序初始化后,内部状态机将自动处理 USB 的热插拔。 +3. ``usbh_cdc_wait_connect`` 可以用于阻塞任务,直到 USB CDC 设备连接或超时。 +4. 成功连接后,主机将自动从 CDC 设备接收 USB 数据到内部 ``ringbuffer``,用户可以轮询 ``usbh_cdc_get_buffered_data_len`` 以读取缓冲数据大小,或者注册接收回调以在数据准备就绪时得到通知。然后 ``usbh_cdc_read_bytes`` 可以用于读取缓冲数据。 +5. ``usbh_cdc_write_bytes`` 可以用于向 USB 设备发送数据。数据首先被写入内部传输 ``ringbuffer``,然后在 USB 总线空闲时发送出去。 +6. ``usbh_cdc_driver_delete`` 可以完全卸载 USB 驱动程序以释放所有资源。 +7. 如果配置多个 CDC 接口,每个接口都包含一个 IN 和 OUT 端点。用户可以使用 ``usbh_cdc_itf_read_bytes`` 和 ``usbh_cdc_itf_write_bytes`` 与指定的接口通信。 + +示例代码 +------------------------------- + +:example:`usb/host/usb_cdc_basic` + +API 参考 +------------------------------- + +.. include-build-file:: inc/iot_usbh_cdc.inc diff --git a/examples/.build-rules.yml b/examples/.build-rules.yml index b9cb597db..f95a6b939 100644 --- a/examples/.build-rules.yml +++ b/examples/.build-rules.yml @@ -163,10 +163,10 @@ examples/usb/host/usb_audio_player: examples/usb/host/usb_cdc_4g_module: enable: - if: IDF_TARGET in ["esp32s2","esp32s3"] - disable: - - if: IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR == 0 - temporary: true - reason: IDF Bug '#36' + +examples/usb/host/usb_cdc_basic: + enable: + - if: IDF_TARGET in ["esp32s2","esp32s3"] examples/utilities/xz_decompress_file: enable: diff --git a/examples/usb/host/usb_cdc_basic/CMakeLists.txt b/examples/usb/host/usb_cdc_basic/CMakeLists.txt new file mode 100644 index 000000000..596f609b8 --- /dev/null +++ b/examples/usb/host/usb_cdc_basic/CMakeLists.txt @@ -0,0 +1,6 @@ +# 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.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(usb_cdc_basic) diff --git a/examples/usb/host/usb_cdc_basic/README.md b/examples/usb/host/usb_cdc_basic/README.md new file mode 100644 index 000000000..229d7c014 --- /dev/null +++ b/examples/usb/host/usb_cdc_basic/README.md @@ -0,0 +1,85 @@ +# USB Host CDC Basic Example + +This example demonstrates how to use [iot_usbh_cdc](https://components.espressif.com/components/espressif/iot_usbh_cdc) to communicate with USB CDC device. + +## How to use the example + +### Hardware Required + +The example can be run on ESP32-S2 or ESP32-S3 based development board with USB interface. + +### Setup the Hardware + +Connect the external USB device to ESP32-S USB interface directly. + +| ESP32-Sx GPIO | USB Device | +| ------------- | ----------- | +| 20 | D+ (green) | +| 19 | D- (white) | +| GND | GND (black) | +| +5V | +5V (red) | + +### Configure the project + +1. The example enables one bulk interface by default. +2. Users can modify the `EXAMPLE_BULK_ITF_NUM` to `2` in `usb_cdc_basic_main.c` to enable two bulk interfaces. +3. Users need to modify the endpoint address `EXAMPLE_BULK_OUTx_EP_ADDR` and `EXAMPLE_BULK_INx_EP_ADDR` to the actual endpoint address of the USB device. +4. Use the command below to set build target to `esp32s2` or `esp32s3`. + +``` +idf.py set-target esp32s3 +``` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT build flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +If your USB device (eg. 4G Module) supports AT command, When host send `AT`, the device usually returns `OK` in most cases. + +``` +I (408) USB_HCDC: Waitting Device Connection +I (438) USB_HCDC: Port=1 init succeed +W (438) USB_HCDC: Waitting USB Connection +I (688) USB_HCDC: line 261 HCD_PORT_EVENT_CONNECTION +I (688) USB_HCDC: Resetting Port +I (748) USB_HCDC: Port speed = 1 +I (748) USB_HCDC: Set Device Addr = 1 +I (748) USB_HCDC: Set Device Addr Done +I (748) USB_HCDC: Set Device Configuration = 1 +I (748) USB_HCDC: Set Device Configuration Done +I (758) USB_HCDC: Set Device Line State: dtr 1, rts 0 +I (758) USB_HCDC: Set Device Line State Done +I (768) USB_HCDC: Creating bulk in pipe +I (768) USB_HCDC: Creating bulk out pipe +I (808) USB_HCDC: usb driver install succeed + +I (6059) cdc_basic_demo: Send itf0 len=4: AT + +I (6069) cdc_basic_demo: Send itf1 len=4: AT + +I (6079) cdc_basic_demo: Itf 0, Receive len=6: +OK + +I (6079) cdc_basic_demo: Itf 1, Receive len=6: +OK + +I (7089) cdc_basic_demo: Send itf0 len=4: AT + +I (7089) cdc_basic_demo: Send itf1 len=4: AT + +I (7109) cdc_basic_demo: Itf 0, Receive len=6: +OK + +I (7109) cdc_basic_demo: Itf 1, Receive len=6: +OK +``` \ No newline at end of file diff --git a/examples/usb/host/usb_cdc_basic/main/CMakeLists.txt b/examples/usb/host/usb_cdc_basic/main/CMakeLists.txt new file mode 100644 index 000000000..ab96b2d05 --- /dev/null +++ b/examples/usb/host/usb_cdc_basic/main/CMakeLists.txt @@ -0,0 +1,3 @@ + +idf_component_register(SRCS usb_cdc_basic_main.c + INCLUDE_DIRS ".") diff --git a/examples/usb/host/usb_cdc_basic/main/idf_component.yml b/examples/usb/host/usb_cdc_basic/main/idf_component.yml new file mode 100644 index 000000000..4c38e317b --- /dev/null +++ b/examples/usb/host/usb_cdc_basic/main/idf_component.yml @@ -0,0 +1,8 @@ +targets: + - esp32s2 + - esp32s3 +dependencies: + idf: ">=4.4.1" + iot_usbh_cdc: + version: "0.2.*" + override_path: "../../../../../components/usb/iot_usbh_cdc" diff --git a/examples/usb/host/usb_cdc_basic/main/usb_cdc_basic_main.c b/examples/usb/host/usb_cdc_basic/main/usb_cdc_basic_main.c new file mode 100644 index 000000000..0e73fbda3 --- /dev/null +++ b/examples/usb/host/usb_cdc_basic/main/usb_cdc_basic_main.c @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "iot_usbh_cdc.h" + +static const char *TAG = "cdc_basic_demo"; +/* USB PIN fixed in esp32-s2/s3, can not use io matrix */ +#define BOARD_USB_DP_PIN 20 +#define BOARD_USB_DN_PIN 19 + +/* ringbuffer size */ +#define IN_RINGBUF_SIZE (1024 * 1) +#define OUT_RINGBUF_SIZE (1024 * 1) + +/* enable interface num */ +#define EXAMPLE_BULK_ITF_NUM 1 +/* bulk endpoint address */ +#define EXAMPLE_BULK_IN0_EP_ADDR 0x81 +#define EXAMPLE_BULK_OUT0_EP_ADDR 0x01 +#define EXAMPLE_BULK_IN1_EP_ADDR 0x82 +#define EXAMPLE_BULK_OUT1_EP_ADDR 0x02 +/* bulk endpoint max package size */ +#define EXAMPLE_BULK_EP_MPS 64 + +/* choose if use user endpoint descriptors */ +#define EXAMPLE_CONFIG_USER_EP_DESC + +/* +the basic demo skip the standred get descriptors process, +users need to get params from cdc device descriptors from PC side, +eg. run `lsusb -v` in linux, then hardcode the related params below +*/ +#ifdef EXAMPLE_CONFIG_USER_EP_DESC +static usb_ep_desc_t bulk_out_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = EXAMPLE_BULK_OUT0_EP_ADDR, + .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, + .wMaxPacketSize = EXAMPLE_BULK_EP_MPS, +}; + +static usb_ep_desc_t bulk_in_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = EXAMPLE_BULK_IN0_EP_ADDR, + .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, + .wMaxPacketSize = EXAMPLE_BULK_EP_MPS, +}; +#endif + +static void usb_receive_task(void *param) +{ + size_t data_len = 0; + uint8_t buf[IN_RINGBUF_SIZE]; + + while (1) { + /* Polling USB receive buffer to get data */ + for (size_t i = 0; i < EXAMPLE_BULK_ITF_NUM; i++) { + if (usbh_cdc_get_itf_state(i) == false) { + continue; + } + usbh_cdc_itf_get_buffered_data_len(i, &data_len); + if (data_len > 0) { + usbh_cdc_itf_read_bytes(i, buf, data_len, 10); + ESP_LOGI(TAG, "Itf %d, Receive len=%d: %.*s", i, data_len, data_len, buf); + } else { + vTaskDelay(1); + } + } + } +} + +static void usb_connect_callback(void *arg) +{ + ESP_LOGI(TAG, "Device Connected!"); +} + +static void usb_disconnect_callback(void *arg) +{ + ESP_LOGW(TAG, "Device Disconnected!"); +} + +void app_main(void) +{ + /* install usbh cdc driver with bulk endpoint configs + and size of internal ringbuffer*/ +#ifdef EXAMPLE_CONFIG_USER_EP_DESC + ESP_LOGI(TAG, "using user bulk endpoint descriptor"); + static usbh_cdc_config_t config = { + /* use user endpoint descriptor */ + .bulk_in_ep = &bulk_in_ep_desc, + .bulk_out_ep = &bulk_out_ep_desc, +#else + ESP_LOGI(TAG, "using default bulk endpoint descriptor"); + static usbh_cdc_config_t config = { + /* use default endpoint descriptor with user address */ + .bulk_in_ep_addr = EXAMPLE_BULK_IN0_EP_ADDR, + .bulk_out_ep_addr = EXAMPLE_BULK_OUT0_EP_ADDR, +#endif + .rx_buffer_size = IN_RINGBUF_SIZE, + .tx_buffer_size = OUT_RINGBUF_SIZE, + .conn_callback = usb_connect_callback, + .disconn_callback = usb_disconnect_callback, + }; + +#if (EXAMPLE_BULK_ITF_NUM > 1) + ESP_LOGI(TAG, "itf %d using default bulk endpoint descriptor", 1); + config.itf_num = 2; + /* test config with only ep addr */ + config.bulk_in_ep_addrs[1] = EXAMPLE_BULK_IN1_EP_ADDR; + config.bulk_out_ep_addrs[1] = EXAMPLE_BULK_OUT1_EP_ADDR; + config.rx_buffer_sizes[1] = IN_RINGBUF_SIZE; + config.tx_buffer_sizes[1] = OUT_RINGBUF_SIZE; +#endif + + /* install USB host CDC driver */ + ESP_ERROR_CHECK(usbh_cdc_driver_install(&config)); + /* Waiting for USB device connected */ + ESP_ERROR_CHECK(usbh_cdc_wait_connect(portMAX_DELAY)); + /* Create a task for USB data processing */ + xTaskCreate(usb_receive_task, "usb_rx", 4096, NULL, 2, NULL); + + /* Repeatly sent AT through USB */ + char buff[32] = "AT\r\n"; + while (1) { + int len = usbh_cdc_write_bytes((uint8_t *)buff, strlen(buff)); + ESP_LOGI(TAG, "Send itf0 len=%d: %s", len, buff); +#if (EXAMPLE_BULK_ITF_NUM > 1) + len = usbh_cdc_itf_write_bytes(1, (uint8_t *)buff, strlen(buff)); + ESP_LOGI(TAG, "Send itf1 len=%d: %s", len, buff); +#endif + vTaskDelay(pdMS_TO_TICKS(1000)); + } +}