SerialUSBHost Lib WIP

This commit is contained in:
Clement_B 2025-01-28 13:02:34 +01:00
parent 88207a7632
commit afa7fc7cb0
4 changed files with 99 additions and 57 deletions

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.associations": {
"memory": "cpp",
"vector": "cpp"
}
}

View File

@ -0,0 +1,37 @@
#ifndef SERIAL_USB_HOST_H
#define SERIAL_USB_HOST_H
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "usb/cdc_acm_host.h"
#include "usb/vcp_ch34x.hpp"
#include "usb/vcp_cp210x.hpp"
#include "usb/vcp_ftdi.hpp"
#include "usb/vcp.hpp"
#include "usb/usb_host.h"
#include <Arduino.h>
class SerialUSBHost
{
public:
SerialUSBHost(/* args */);
SemaphoreHandle_t device_disconnected_sem;
private:
/**
* @brief USB Host library handling task
*
* @param arg unused but required for task
*/
static void usb_lib_task(void* arg);
};
#endif

View File

@ -0,0 +1,50 @@
#include "../include/SerialUSBHost.h"
void SerialUSBHost::usb_lib_task(void* arg) {
const String TAG = "SerialUSBHost_usb_lib_task";
while (1) {
// 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) {
ESP_ERROR_CHECK(usb_host_device_free_all());
}
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
ESP_LOGI(TAG.c_str(), "USB: All devices freed");
// Continue handling USB events to allow device reconnection
}
}
}
SerialUSBHost::SerialUSBHost() {
const String TAG = "SerialUSBHost_constructor";
this->device_disconnected_sem = xSemaphoreCreateBinary();
assert(device_disconnected_sem);
// Install USB Host driver. Should only be called once in entire application
ESP_LOGI(TAG.c_str(), "Installing USB Host");
const usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
.enum_filter_cb = nullptr,
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
// Create a task that will handle USB library events
BaseType_t task_created = xTaskCreate(SerialUSBHost::usb_lib_task, "usb_lib", 4096, NULL, 10, NULL);
assert(task_created == pdTRUE);
ESP_LOGI(TAG.c_str(), "Installing CDC-ACM driver");
ESP_ERROR_CHECK(cdc_acm_host_install(NULL));
// Register VCP drivers to VCP service
esp_usb::VCP::register_driver<esp_usb::FT23x>();
esp_usb::VCP::register_driver<esp_usb::CP210x>();
esp_usb::VCP::register_driver<esp_usb::CH34x>();
}

View File

@ -3,17 +3,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "usb/cdc_acm_host.h" #include "SerialUSBHost.h"
#include "usb/vcp_ch34x.hpp"
#include "usb/vcp_cp210x.hpp" SerialUSBHost* serialUSB;
#include "usb/vcp_ftdi.hpp"
#include "usb/vcp.hpp"
#include "usb/usb_host.h"
using namespace esp_usb; using namespace esp_usb;
@ -26,8 +19,6 @@ using namespace esp_usb;
namespace { namespace {
static const char *TAG = "VCP example"; static const char *TAG = "VCP example";
static SemaphoreHandle_t device_disconnected_sem;
/** /**
* @brief Data received callback * @brief Data received callback
* *
@ -62,7 +53,7 @@ static void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_
break; break;
case CDC_ACM_HOST_DEVICE_DISCONNECTED: case CDC_ACM_HOST_DEVICE_DISCONNECTED:
ESP_LOGI(TAG, "Device suddenly disconnected"); ESP_LOGI(TAG, "Device suddenly disconnected");
xSemaphoreGive(device_disconnected_sem); xSemaphoreGive(serialUSB->device_disconnected_sem);
break; break;
case CDC_ACM_HOST_SERIAL_STATE: case CDC_ACM_HOST_SERIAL_STATE:
ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val); ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val);
@ -71,55 +62,13 @@ static void handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_
default: break; default: break;
} }
} }
/**
* @brief USB Host library handling task
*
* @param arg Unused
*/
static void usb_lib_task(void *arg)
{
while (1) {
// 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) {
ESP_ERROR_CHECK(usb_host_device_free_all());
}
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
ESP_LOGI(TAG, "USB: All devices freed");
// Continue handling USB events to allow device reconnection
}
}
}
} }
void setup() { void setup() {
device_disconnected_sem = xSemaphoreCreateBinary(); serialUSB = new SerialUSBHost();
assert(device_disconnected_sem);
// Install USB Host driver. Should only be called once in entire application
ESP_LOGI(TAG, "Installing USB Host");
const usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
// Create a task that will handle USB library events
BaseType_t task_created = xTaskCreate(usb_lib_task, "usb_lib", 4096, NULL, 10, NULL);
assert(task_created == pdTRUE);
ESP_LOGI(TAG, "Installing CDC-ACM driver");
ESP_ERROR_CHECK(cdc_acm_host_install(NULL));
// Register VCP drivers to VCP service
VCP::register_driver<FT23x>();
VCP::register_driver<CP210x>();
VCP::register_driver<CH34x>();
} }
void loop() { void loop() {
@ -168,5 +117,5 @@ void loop() {
// We are done. Wait for device disconnection and start over // We are done. Wait for device disconnection and start over
ESP_LOGI(TAG, "Done. You can reconnect the VCP device to run again."); ESP_LOGI(TAG, "Done. You can reconnect the VCP device to run again.");
xSemaphoreTake(device_disconnected_sem, portMAX_DELAY); xSemaphoreTake(serialUSB->device_disconnected_sem, portMAX_DELAY);
} }