#include "../include/SerialUSBHost.h" static SemaphoreHandle_t device_disconnected_sem;//XXX static cdc_acm_host_device_config_t dev_config = { .connection_timeout_ms = 5000, // 5 seconds, enough time to plug the device in or experiment with timeout .out_buffer_size = 512, .in_buffer_size = 512, .event_cb = SerialUSBHost::handle_event, .data_cb = SerialUSBHost::handle_rx, .user_arg = NULL, }; static cdc_acm_line_coding_t line_coding; static const char *TAG = "VCP example"; /** * @brief Data received callback * * Just pass received data to stdout * * @param[in] data Pointer to received data * @param[in] data_len Length of received data in bytes * @param[in] arg Argument we passed to the device open function * @return * true: We have processed the received data * false: We expect more data */ bool SerialUSBHost::handle_rx(const uint8_t *data, size_t data_len, void *arg) { //ESP_LOGI("USB_HANDLE", "Recivend data !!"); printf("%.*s", data_len, data); return true; } /** * @brief Device event callback * * Apart from handling device disconnection it doesn't do anything useful * * @param[in] event Device event type and data * @param[in] user_ctx Argument we passed to the device open function */ void SerialUSBHost::handle_event(const cdc_acm_host_dev_event_data_t *event, void *user_ctx) { switch (event->type) { case CDC_ACM_HOST_ERROR: ESP_LOGE(TAG, "CDC-ACM error has occurred, err_no = %d", event->data.error); break; case CDC_ACM_HOST_DEVICE_DISCONNECTED: ESP_LOGI(TAG, "Device suddenly disconnected"); xSemaphoreGive(device_disconnected_sem); break; case CDC_ACM_HOST_SERIAL_STATE: ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val); break; case CDC_ACM_HOST_NETWORK_CONNECTION: default: break; } } 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 } } } void SerialUSBHost::init(uint32_t baudrate, uint8_t stop_bits, uint8_t parity, uint8_t dataBits) { const String TAG = "SerialUSBHost_constructor"; 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::VCP::register_driver(); esp_usb::VCP::register_driver(); line_coding.dwDTERate = baudrate; line_coding.bCharFormat = stop_bits; line_coding.bParityType = parity; line_coding.bDataBits = dataBits; } void SerialUSBHost::takeSem() {//XXX xSemaphoreTake(device_disconnected_sem, portMAX_DELAY); } cdc_acm_host_device_config_t* SerialUSBHost::getDevConfig() { return &dev_config; } cdc_acm_line_coding_t* SerialUSBHost::getLineCoding() { return &line_coding; }