diff --git a/examples/peripherals/usb/device/cherryusb_serial_device/CMakeLists.txt b/examples/peripherals/usb/device/cherryusb_serial_device/CMakeLists.txt index e0a468eee7..96ff33bcfa 100644 --- a/examples/peripherals/usb/device/cherryusb_serial_device/CMakeLists.txt +++ b/examples/peripherals/usb/device/cherryusb_serial_device/CMakeLists.txt @@ -1,6 +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) +cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmake/project.cmake) idf_build_set_property(MINIMAL_BUILD ON) diff --git a/examples/peripherals/usb/device/cherryusb_serial_device/main/device_cdc_main.c b/examples/peripherals/usb/device/cherryusb_serial_device/main/device_cdc_main.c index 67ead58589..520b62da63 100644 --- a/examples/peripherals/usb/device/cherryusb_serial_device/main/device_cdc_main.c +++ b/examples/peripherals/usb/device/cherryusb_serial_device/main/device_cdc_main.c @@ -33,10 +33,11 @@ static TaskHandle_t s_task_handle = NULL; #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x01 #define CDC_INT_EP 0x83 - +#if CDC_ACM_CHANNEL_NUM >= 2 #define CDC_IN_EP1 0x82 #define CDC_OUT_EP1 0x02 #define CDC_INT_EP1 0x84 +#endif #define USBD_VID 0xFFFF #define USBD_PID 0xFFFF @@ -44,7 +45,7 @@ static TaskHandle_t s_task_handle = NULL; #define USBD_LANGID_STRING 1033 /*!< config descriptor size */ -#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4) +#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * CDC_ACM_CHANNEL_NUM) #define CDC_FS_MAX_MPS 64 #define CDC_HS_MAX_MPS 512 @@ -85,7 +86,6 @@ static uint32_t s_mps = CDC_MAX_MPS; static DRAM_DMA_ALIGNED_ATTR uint8_t read_buffer[CDC_ACM_CHANNEL_NUM][READ_BUFFER_SIZE]; static DRAM_DMA_ALIGNED_ATTR uint8_t write_buffer[CDC_ACM_CHANNEL_NUM][WRITE_BUFFER_SIZE]; -#ifdef CONFIG_USBDEV_ADVANCE_DESC static const uint8_t device_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01) }; @@ -170,90 +170,8 @@ const struct usb_descriptor cdc_descriptor = { .device_quality_descriptor_callback = device_quality_descriptor_callback, .string_descriptor_callback = string_descriptor_callback }; -#else -/*!< global descriptor */ -static const uint8_t cdc_descriptor[] = { - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), - USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTERFACES_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), - CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02), -#ifdef CONFIG_EXAMPLE_CHERRYUSB_CDC_ACM_TWO_CHANNEL - CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP1, CDC_OUT_EP1, CDC_IN_EP1, CDC_MAX_MPS, 0x02), -#endif - /////////////////////////////////////// - /// string0 descriptor - /////////////////////////////////////// - USB_LANGID_INIT(USBD_LANGID_STRING), - /////////////////////////////////////// - /// string1 descriptor - /////////////////////////////////////// - 0x14, /* bLength */ - USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'C', 0x00, /* wcChar0 */ - 'h', 0x00, /* wcChar1 */ - 'e', 0x00, /* wcChar2 */ - 'r', 0x00, /* wcChar3 */ - 'r', 0x00, /* wcChar4 */ - 'y', 0x00, /* wcChar5 */ - 'U', 0x00, /* wcChar6 */ - 'S', 0x00, /* wcChar7 */ - 'B', 0x00, /* wcChar8 */ - /////////////////////////////////////// - /// string2 descriptor - /////////////////////////////////////// - 0x26, /* bLength */ - USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'C', 0x00, /* wcChar0 */ - 'h', 0x00, /* wcChar1 */ - 'e', 0x00, /* wcChar2 */ - 'r', 0x00, /* wcChar3 */ - 'r', 0x00, /* wcChar4 */ - 'y', 0x00, /* wcChar5 */ - 'U', 0x00, /* wcChar6 */ - 'S', 0x00, /* wcChar7 */ - 'B', 0x00, /* wcChar8 */ - ' ', 0x00, /* wcChar9 */ - 'C', 0x00, /* wcChar10 */ - 'D', 0x00, /* wcChar11 */ - 'C', 0x00, /* wcChar12 */ - ' ', 0x00, /* wcChar13 */ - 'D', 0x00, /* wcChar14 */ - 'E', 0x00, /* wcChar15 */ - 'M', 0x00, /* wcChar16 */ - 'O', 0x00, /* wcChar17 */ - /////////////////////////////////////// - /// string3 descriptor - /////////////////////////////////////// - 0x16, /* bLength */ - USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - '2', 0x00, /* wcChar0 */ - '0', 0x00, /* wcChar1 */ - '2', 0x00, /* wcChar2 */ - '5', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '6', 0x00, /* wcChar5 */ - '0', 0x00, /* wcChar6 */ - '5', 0x00, /* wcChar7 */ - '1', 0x00, /* wcChar8 */ - '8', 0x00, /* wcChar9 */ -#ifdef CONFIG_USB_HS - /////////////////////////////////////// - /// device qualifier descriptor - /////////////////////////////////////// - 0x0a, - USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, - 0x00, - 0x02, - 0x00, - 0x00, - 0x00, - 0x40, - 0x00, - 0x00, -#endif - 0x00 -}; -#endif +//Note: This callback is in the interrupt context void usbd_event_handler(uint8_t busid, uint8_t event) { switch (event) { @@ -285,6 +203,7 @@ void usbd_event_handler(uint8_t busid, uint8_t event) } } +//Note: This callback is in the interrupt context static void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) { ESP_EARLY_LOGI(TAG, "ep 0x%02X actual out len:%d", ep, nbytes); @@ -321,6 +240,7 @@ static void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) } } +//Note: This callback is in the interrupt context static void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) { BaseType_t HPTaskAwoken = pdFALSE; @@ -373,11 +293,8 @@ struct usbd_interface intf3; static void cdc_acm_init(void) { -#ifdef CONFIG_USBDEV_ADVANCE_DESC usbd_desc_register(0, &cdc_descriptor); -#else - usbd_desc_register(0, cdc_descriptor); -#endif + usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf0)); usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1)); usbd_add_endpoint(0, &cdc_out_ep); @@ -396,11 +313,13 @@ static void cdc_acm_init(void) #endif } +//Note: This callback is in the interrupt context void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr) { ESP_EARLY_LOGI(TAG, "intf:%u, dtr:%d", intf, dtr); } +//Note: This callback is in the interrupt context void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts) { ESP_EARLY_LOGI(TAG, "intf:%u, rts:%d", intf, rts); @@ -470,22 +389,22 @@ void cdc_acm_task(void *arg) void app_main(void) { #if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP -reinit : + while (1) #endif - - xTaskCreatePinnedToCore(&cdc_acm_task, "cdc_acm_task", 1024 * 3, NULL, 10, &s_task_handle, 0); + { + xTaskCreatePinnedToCore(&cdc_acm_task, "cdc_acm_task", 1024 * 3, NULL, 10, &s_task_handle, 0); #if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP - for (int i = 10; i >= 0; i--) { - ESP_LOGW(TAG, "Deinit usb after %d seconds...", i); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - ESP_LOGW(TAG, "Notify deinit usb"); - xTaskNotify(s_task_handle, NOTIFY_EXIT_BIT, eSetBits); - while (s_task_handle) { - vTaskDelay(100 / portTICK_PERIOD_MS); - } - goto reinit; + for (int i = 10; i >= 0; i--) { + ESP_LOGW(TAG, "Deinit usb after %d seconds...", i); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + ESP_LOGW(TAG, "Notify deinit usb"); + xTaskNotify(s_task_handle, NOTIFY_EXIT_BIT, eSetBits); + while (s_task_handle) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } #endif + } } diff --git a/examples/peripherals/usb/device/cherryusb_serial_device/main/idf_component.yml b/examples/peripherals/usb/device/cherryusb_serial_device/main/idf_component.yml index bc5baa8d76..a92de9e1a2 100644 --- a/examples/peripherals/usb/device/cherryusb_serial_device/main/idf_component.yml +++ b/examples/peripherals/usb/device/cherryusb_serial_device/main/idf_component.yml @@ -1,3 +1,3 @@ ## IDF Component Manager Manifest File dependencies: - cherry-embedded/cherryusb: ~=1.5.1~8 + cherry-embedded/cherryusb: 1.5.2~1 diff --git a/examples/peripherals/usb/host/cherryusb_host/CMakeLists.txt b/examples/peripherals/usb/host/cherryusb_host/CMakeLists.txt index 580c0a8d0f..9b84404469 100644 --- a/examples/peripherals/usb/host/cherryusb_host/CMakeLists.txt +++ b/examples/peripherals/usb/host/cherryusb_host/CMakeLists.txt @@ -1,6 +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) +cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmake/project.cmake) idf_build_set_property(MINIMAL_BUILD ON) diff --git a/examples/peripherals/usb/host/cherryusb_host/main/CMakeLists.txt b/examples/peripherals/usb/host/cherryusb_host/main/CMakeLists.txt index d2254d31ca..2da571cbb7 100644 --- a/examples/peripherals/usb/host/cherryusb_host/main/CMakeLists.txt +++ b/examples/peripherals/usb/host/cherryusb_host/main/CMakeLists.txt @@ -7,6 +7,7 @@ endif() if(CONFIG_CHERRYUSB_HOST_CDC_ACM OR CONFIG_CHERRYUSB_HOST_FTDI OR CONFIG_CHERRYUSB_HOST_CH34X OR CONFIG_CHERRYUSB_HOST_CP210X OR CONFIG_CHERRYUSB_HOST_PL2303) list(APPEND srcs "cdc_acm.c") + set(CHERRYUSB_HOST_CDC_ACM_INCLUDE TRUE) endif() if(CONFIG_CHERRYUSB_HOST_MSC) @@ -15,40 +16,20 @@ endif() idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." - PRIV_REQUIRES esp_timer fatfs + PRIV_REQUIRES esp_timer fatfs esp_ringbuf ) if(CONFIG_CHERRYUSB_HOST_HID) # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_hid_run_real") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_hid") endif() -if(CONFIG_CHERRYUSB_HOST_CDC_ACM) - # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_cdc_acm_run_real") -endif() - -if(CONFIG_CHERRYUSB_HOST_FTDI) - # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_ftdi_run_real") -endif() - -if(CONFIG_CHERRYUSB_HOST_CH34X) - # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_ch34x_run_real") -endif() - -if(CONFIG_CHERRYUSB_HOST_CP210X) - # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_cp210x_run_real") -endif() - -if(CONFIG_CHERRYUSB_HOST_PL2303) - # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_pl2303_run_real") +if(CHERRYUSB_HOST_CDC_ACM_INCLUDE) + # Make sure the definitions in cdc_acm.c are linked correctly + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_cdc_acm") endif() if(CONFIG_CHERRYUSB_HOST_MSC) - # Make sure the definitions in hid.c are linked correctly - target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_msc_run_real") + # Make sure the definitions in msc.c are linked correctly + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_msc") endif() diff --git a/examples/peripherals/usb/host/cherryusb_host/main/cdc_acm.c b/examples/peripherals/usb/host/cherryusb_host/main/cdc_acm.c index 586ef17b6e..ce720ef85c 100644 --- a/examples/peripherals/usb/host/cherryusb_host/main/cdc_acm.c +++ b/examples/peripherals/usb/host/cherryusb_host/main/cdc_acm.c @@ -7,6 +7,7 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/ringbuf.h" #include "esp_heap_caps.h" #include "esp_log.h" @@ -30,6 +31,10 @@ static char *TAG = "CDC_ACM"; +#define RINGBUF_SIZE 1024 +static RingbufHandle_t s_recv_ringbuf = NULL; +static TaskHandle_t s_printf_task_handle = NULL; + typedef enum { SERIAL_TYPE_CDC_ACM = 0, SERIAL_TYPE_FTDI, @@ -54,6 +59,10 @@ typedef struct { static void free_serial_buffer(serial_t *serial); static esp_err_t serial_start_in(serial_t *serial); +void ld_include_cdc_acm(void) +{ +} + #define alloc_serial_buffer(serial_class, serial_type, out_serial) \ { \ out_serial = heap_caps_calloc(1, sizeof(serial_t), MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ @@ -87,9 +96,10 @@ static void free_serial_buffer(serial_t *serial) heap_caps_free(serial); } +//Note: This callback is in the interrupt context static void serial_in_cb(void *arg, int nbytes) { - // ESP_EARLY_LOGE(TAG, "in_cb: %d bytes", nbytes); + BaseType_t xTaskWoken = pdFALSE; serial_t *serial = (serial_t *)arg; uint8_t *data = serial->in_buffer; if (nbytes < 0) { @@ -105,17 +115,14 @@ static void serial_in_cb(void *arg, int nbytes) nbytes -= 2; } - for (size_t i = 0; i < nbytes; i++) { - if (data[i] >= 0x20 && data[i] <= 0x7e) { - esp_rom_printf("%c", data[i]); - } else { - esp_rom_printf("[%02x]", data[i]); - if (data[i] == '\n') { - esp_rom_printf("\n"); - } + if (s_recv_ringbuf) { + if (xRingbufferSendFromISR(s_recv_ringbuf, data, nbytes, &xTaskWoken) != pdTRUE) { + ESP_LOGD(TAG, "Ringbuffer send failed"); } } - + if (xTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } serial_start_in(serial); } @@ -130,7 +137,7 @@ static esp_err_t serial_start_in(serial_t *serial) return ESP_OK; } -esp_err_t serial_out(serial_t *serial, uint8_t *data, size_t len, uint32_t timeout) +static esp_err_t serial_out(serial_t *serial, uint8_t *data, size_t len, uint32_t timeout) { int ret; if (len > serial->bulkout->wMaxPacketSize) { @@ -145,6 +152,36 @@ esp_err_t serial_out(serial_t *serial, uint8_t *data, size_t len, uint32_t timeo return ESP_OK; } +static void usbh_cdc_acm_printf_task(void *arg) +{ + while (1) { + size_t length = 0; + char *data = (char *)xRingbufferReceive(s_recv_ringbuf, &length, portMAX_DELAY); + if (data == NULL) { + continue; + } + ESP_LOGI(TAG, "Data received"); + ESP_LOG_BUFFER_HEXDUMP(TAG, data, length, ESP_LOG_INFO); + vRingbufferReturnItem(s_recv_ringbuf, (void *)data); + fflush(stdout); + } + vTaskDelete(NULL); +} + +static void creat_printf_task(void) +{ + if (s_recv_ringbuf == NULL) { + s_recv_ringbuf = xRingbufferCreate(RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF); + if (s_recv_ringbuf == NULL) { + ESP_LOGE(TAG, "ringbuf create failed"); + return; + } + } + if (s_printf_task_handle == NULL) { + xTaskCreate(usbh_cdc_acm_printf_task, "usbh_cdc_acm_printf_task", 4096, NULL, 5, &s_printf_task_handle); + } +} + #if CONFIG_CHERRYUSB_HOST_CDC_ACM void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) @@ -155,6 +192,7 @@ void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) ESP_LOGW(TAG, "Malloc failed"); return; } + creat_printf_task(); cdc_acm_class->user_data = serial; struct cdc_line_coding linecoding = { @@ -170,8 +208,6 @@ void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) serial_out(serial, (uint8_t *)data, sizeof(data), 1000); } -void usbh_cdc_acm_run_real(struct usbh_cdc_acm *cdc_acm_class) __attribute__((alias("usbh_cdc_acm_run"))); - void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class) { free_serial_buffer(cdc_acm_class->user_data); @@ -188,6 +224,7 @@ void usbh_ftdi_run(struct usbh_ftdi *ftdi_class) ESP_LOGW(TAG, "Malloc failed"); return; } + creat_printf_task(); ftdi_class->user_data = serial; struct cdc_line_coding linecoding = { @@ -204,8 +241,6 @@ void usbh_ftdi_run(struct usbh_ftdi *ftdi_class) serial_out(serial, (uint8_t *)data, sizeof(data), 1000); } -void usbh_ftdi_run_real(struct usbh_ftdi *cdc_acm_class) __attribute__((alias("usbh_ftdi_run"))); - void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class) { free_serial_buffer(ftdi_class->user_data); @@ -221,6 +256,7 @@ void usbh_ch34x_run(struct usbh_ch34x *ch34x_class) ESP_LOGW(TAG, "Malloc failed"); return; } + creat_printf_task(); ch34x_class->user_data = serial; struct cdc_line_coding linecoding = { @@ -236,8 +272,6 @@ void usbh_ch34x_run(struct usbh_ch34x *ch34x_class) serial_out(serial, (uint8_t *)data, sizeof(data), 1000); } -void usbh_ch34x_run_real(struct usbh_ch34x *cdc_acm_class) __attribute__((alias("usbh_ch34x_run"))); - void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class) { free_serial_buffer(ch34x_class->user_data); @@ -253,6 +287,7 @@ void usbh_cp210x_run(struct usbh_cp210x *cp210x_class) ESP_LOGW(TAG, "Malloc failed"); return; } + creat_printf_task(); cp210x_class->user_data = serial; struct cdc_line_coding linecoding = { @@ -268,8 +303,6 @@ void usbh_cp210x_run(struct usbh_cp210x *cp210x_class) serial_out(serial, (uint8_t *)data, sizeof(data), 1000); } -void usbh_cp210x_run_real(struct usbh_cp210x *cdc_acm_class) __attribute__((alias("usbh_cp210x_run"))); - void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class) { free_serial_buffer(cp210x_class->user_data); @@ -285,6 +318,7 @@ void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class) ESP_LOGW(TAG, "Malloc failed"); return; } + creat_printf_task(); pl2303_class->user_data = serial; struct cdc_line_coding linecoding = { @@ -300,8 +334,6 @@ void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class) serial_out(serial, (uint8_t *)data, sizeof(data), 1000); } -void usbh_pl2303_run_real(struct usbh_pl2303 *cdc_acm_class) __attribute__((alias("usbh_pl2303_run"))); - void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class) { free_serial_buffer(pl2303_class->user_data); diff --git a/examples/peripherals/usb/host/cherryusb_host/main/hid.c b/examples/peripherals/usb/host/cherryusb_host/main/hid.c index ebd9d65cbb..eeb75bad65 100644 --- a/examples/peripherals/usb/host/cherryusb_host/main/hid.c +++ b/examples/peripherals/usb/host/cherryusb_host/main/hid.c @@ -7,6 +7,7 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/queue.h" #include "esp_timer.h" #include "esp_log.h" @@ -33,6 +34,19 @@ typedef struct { uint8_t key_code; } key_event_t; +/** + * @brief hid msg + */ +typedef struct { + uint8_t protocol; + uint16_t len; + uint8_t data[64]; +} hid_msg_t; + +#define QUEUE_LEN 10 +static QueueHandle_t s_msg_queue = NULL; +static TaskHandle_t s_msg_task_handle = NULL; + /* Main char symbol for ENTER key */ #define KEYBOARD_ENTER_MAIN_CHAR '\r' /* When set to 1 pressing ENTER will be extending with LineFeed during serial debug output */ @@ -41,8 +55,8 @@ typedef struct { #define KEYBOARD_ENTER_ALT_ESCAPE 1 #if KEYBOARD_ENTER_ALT_ESCAPE -static bool escaping = false; -static unsigned char escap_hex = 0; +static bool is_ansi = false; +static unsigned int alt_code = 0; #endif /** @@ -108,6 +122,28 @@ const uint8_t keycode2ascii [57][2] = { {'/', '?'} /* HID_KBD_USAGE_QUESTION */ }; +void ld_include_hid(void) +{ +} + +/** + * @brief HID Keyboard print char symbol + * + * @param[in] key_char Keyboard char to stdout + */ +static inline void hid_keyboard_print_char(unsigned int key_char) +{ + if (!!key_char) { + putchar(key_char); +#if (KEYBOARD_ENTER_LF_EXTEND) + if (KEYBOARD_ENTER_MAIN_CHAR == key_char) { + putchar('\n'); + } +#endif // KEYBOARD_ENTER_LF_EXTEND + fflush(stdout); + } +} + /** * @brief Makes new line depending on report output protocol type * @@ -119,14 +155,15 @@ static void hid_print_new_device_report_header(int proto) if (prev_proto_output != proto) { prev_proto_output = proto; - esp_rom_printf("\r\n"); + printf("\r\n"); if (proto == HID_PROTOCOL_MOUSE) { - esp_rom_printf("Mouse\r\n"); + printf("Mouse\r\n"); } else if (proto == HID_PROTOCOL_KEYBOARD) { - esp_rom_printf("Keyboard\r\n"); + printf("Keyboard\r\n"); } else { - esp_rom_printf("Generic\r\n"); + printf("Generic\r\n"); } + fflush(stdout); } } @@ -164,6 +201,62 @@ static inline bool hid_keyboard_is_modifier_alt(uint8_t modifier) } return false; } + +/** + * @brief HID Keyboard alt code process(Called when ALT is pressed) + * + * @param[in] key_code Entered key value + * @return true Key values that qualify for ALT escape processing + * @return false Key values that do not comply with ALT escape processing + * + */ +static inline bool hid_keyboard_alt_code_processing(uint8_t key_code) +{ + if ((key_code < HID_KBD_USAGE_KPD1) || (key_code > HID_KBD_USAGE_KPD0)) { + return false; + } + if (key_code == HID_KBD_USAGE_KPD0) { + if (alt_code == 0) { + is_ansi = true; + return true; + } + /* Note: Since the keyboard code 0 of the numeric keypad is not keyboard code 1 minus 1, the + * conversion is performed here to facilitate subsequent calculations of the input numbers. + */ + key_code = HID_KBD_USAGE_KPD1 - 1; + } + alt_code = alt_code * 10 + (key_code - (HID_KBD_USAGE_KPD1 - 1)); + return true; +} + +/** + * @brief HID Keyboard alt code process complete(Called when ALT is not pressed) + */ +static inline void hid_keyboard_alt_code_process_complete(void) +{ + if (alt_code > 0) { + alt_code = alt_code & 0xff; + if (is_ansi || alt_code == 0) { + char utf8_buffer[8] = { 0 }; + if (alt_code == 0) { + alt_code = 0x100; + } + //ANSI is processed as UTF8 + if (alt_code <= 0x7F) { + utf8_buffer[0] = (char)alt_code; + } else { + utf8_buffer[0] = 0xC0 | ((alt_code >> 6) & 0x1F); + utf8_buffer[1] = 0x80 | (alt_code & 0x3F); + } + printf("%s", utf8_buffer); + fflush(stdout); + } else { + hid_keyboard_print_char(alt_code); + } + alt_code = 0; + } + is_ansi = false; +} #endif /** @@ -183,14 +276,10 @@ static inline bool hid_keyboard_get_char(uint8_t modifier, uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0; #if KEYBOARD_ENTER_ALT_ESCAPE - if (escaping) { - if ((key_code >= HID_KBD_USAGE_KPD1) && (key_code <= HID_KBD_USAGE_KPD0)) { - if (key_code == HID_KBD_USAGE_KPD0) { - key_code = HID_KBD_USAGE_KPD1 - 1; - } - escap_hex = escap_hex * 10 + (key_code - (HID_KBD_USAGE_KPD1 - 1)); + if (hid_keyboard_is_modifier_alt(modifier)) { + if (hid_keyboard_alt_code_processing(key_code)) { + return false; } - return false; } #endif @@ -204,23 +293,6 @@ static inline bool hid_keyboard_get_char(uint8_t modifier, return true; } -/** - * @brief HID Keyboard print char symbol - * - * @param[in] key_char Keyboard char to stdout - */ -static inline void hid_keyboard_print_char(unsigned int key_char) -{ - if (!!key_char) { - esp_rom_printf("%c", key_char); -#if (KEYBOARD_ENTER_LF_EXTEND) - if (KEYBOARD_ENTER_MAIN_CHAR == key_char) { - esp_rom_printf("\n"); - } -#endif // KEYBOARD_ENTER_LF_EXTEND - } -} - /** * @brief Key Event. Key event with the key code, state and modifier. * @@ -272,16 +344,8 @@ static void usbh_hid_keyboard_report_callback(void *arg, int nbytes) key_event_t key_event; #if KEYBOARD_ENTER_ALT_ESCAPE - if (hid_keyboard_is_modifier_alt(kb_report->modifier)) { - if (escaping == false) { - escaping = true; - escap_hex = 0; - } - } else { - if (escaping && escap_hex > 0) { - escaping = false; - hid_keyboard_print_char(escap_hex); - } + if (!hid_keyboard_is_modifier_alt(kb_report->modifier)) { + hid_keyboard_alt_code_process_complete(); } #endif @@ -326,24 +390,27 @@ static void usbh_hid_mouse_report_callback(void *arg, int nbytes) hid_print_new_device_report_header(HID_PROTOCOL_MOUSE); - esp_rom_printf("X: %06d\tY: %06d\t|%c|%c|\n", - x_pos, y_pos, - ((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_LEFT) ? 'o' : ' '), - ((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_RIGHT) ? 'o' : ' ')); + printf("X: %06d\tY: %06d\t|%c|%c|\n", + x_pos, y_pos, + ((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_LEFT) ? 'o' : ' '), + ((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_RIGHT) ? 'o' : ' ')); + fflush(stdout); } static void usbh_hid_generic_report_callback(void *arg, int nbytes) { - uint8_t *data = arg; + char *data = arg; hid_print_new_device_report_header(HID_PROTOCOL_NONE); - for (size_t i = 0; i < nbytes; i++) { - esp_rom_printf("%02x ", data[i]); + for (int i = 0; i < nbytes; i++) { + printf("%02X", data[i]); } - esp_rom_printf("\r"); + putchar('\r'); } +//Note: This callback is in the interrupt context static void usbh_hid_callback(void *arg, int nbytes) { + BaseType_t xTaskWoken = pdFALSE; struct usbh_hid *hid_class = (struct usbh_hid *)arg; hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data; @@ -354,18 +421,34 @@ static void usbh_hid_callback(void *arg, int nbytes) uint8_t sub_class = hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceSubClass; uint8_t protocol = hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceProtocol; - usbh_complete_callback_t complete_cb = usbh_hid_generic_report_callback; - if (sub_class == HID_SUBCLASS_BOOTIF) { - if (protocol == HID_PROTOCOL_KEYBOARD) { - complete_cb = usbh_hid_keyboard_report_callback; - } else if (protocol == HID_PROTOCOL_MOUSE) { - complete_cb = usbh_hid_mouse_report_callback; + if (s_msg_queue) { + hid_msg_t msg; + if (nbytes <= sizeof(msg.data)) { + msg.protocol = HID_PROTOCOL_NONE; + if (sub_class == HID_SUBCLASS_BOOTIF) { + if (protocol == HID_PROTOCOL_KEYBOARD) { + msg.protocol = HID_PROTOCOL_KEYBOARD; + } else if (protocol == HID_PROTOCOL_MOUSE) { + msg.protocol = HID_PROTOCOL_MOUSE; + } + } + msg.len = nbytes; + memcpy(msg.data, hid_intin->buffer, nbytes); + if (xQueueSendFromISR(s_msg_queue, &msg, &xTaskWoken) != pdTRUE) { + ESP_EARLY_LOGD(TAG, "msg queue full"); + } + } else { + ESP_EARLY_LOGD(TAG, "nbytes(%d) > sizeof(msg.data)", nbytes); } + } - complete_cb(hid_intin->buffer, nbytes); hid_intin->is_active = false; + if (xTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } } +//Note: If the dispatch_method of esp_timer is ESP_TIMER_ISR, the callback is in the interrupt context. static void intin_timer_cb(void *arg) { int ret; @@ -389,6 +472,39 @@ static void intin_timer_cb(void *arg) } } +static void usbh_hid_msg_task(void *arg) +{ + hid_msg_t msg; + while (1) { + BaseType_t err = xQueueReceive(s_msg_queue, &msg, portMAX_DELAY); + if (err != pdTRUE) { + continue; + } + if (msg.protocol == HID_PROTOCOL_KEYBOARD) { + usbh_hid_keyboard_report_callback(msg.data, msg.len); + } else if (msg.protocol == HID_PROTOCOL_MOUSE) { + usbh_hid_mouse_report_callback(msg.data, msg.len); + } else { + usbh_hid_generic_report_callback(msg.data, msg.len); + } + } + vTaskDelete(NULL); +} + +static void creat_msg_task(void) +{ + if (s_msg_queue == NULL) { + s_msg_queue = xQueueCreate(QUEUE_LEN, sizeof(hid_msg_t)); + if (s_msg_queue == NULL) { + ESP_LOGE(TAG, "ringbuf create failed"); + return; + } + } + if (s_msg_task_handle == NULL) { + xTaskCreate(usbh_hid_msg_task, "usbh_hid_msg_task", 4096, NULL, 5, &s_msg_task_handle); + } +} + void usbh_hid_run(struct usbh_hid *hid_class) { int ret; @@ -404,6 +520,8 @@ void usbh_hid_run(struct usbh_hid *hid_class) } } + creat_msg_task(); + if (hid_class->intin == NULL) { ESP_LOGW(TAG, "no intin ep desc"); return; @@ -449,8 +567,6 @@ error: heap_caps_free(hid_intin); } -void usbh_hid_run_real(struct usbh_hid *) __attribute__((alias("usbh_hid_run"))); - void usbh_hid_stop(struct usbh_hid *hid_class) { hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data; diff --git a/examples/peripherals/usb/host/cherryusb_host/main/idf_component.yml b/examples/peripherals/usb/host/cherryusb_host/main/idf_component.yml index bc5baa8d76..a92de9e1a2 100644 --- a/examples/peripherals/usb/host/cherryusb_host/main/idf_component.yml +++ b/examples/peripherals/usb/host/cherryusb_host/main/idf_component.yml @@ -1,3 +1,3 @@ ## IDF Component Manager Manifest File dependencies: - cherry-embedded/cherryusb: ~=1.5.1~8 + cherry-embedded/cherryusb: 1.5.2~1 diff --git a/examples/peripherals/usb/host/cherryusb_host/main/main.c b/examples/peripherals/usb/host/cherryusb_host/main/main.c index 19410e15f2..a9aab4675e 100644 --- a/examples/peripherals/usb/host/cherryusb_host/main/main.c +++ b/examples/peripherals/usb/host/cherryusb_host/main/main.c @@ -41,25 +41,25 @@ void app_main(void) #endif #if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP -reinit: + while (1) #endif - + { #if CONFIG_EXAMPLE_USB_HOST_RHPORT_HS - usbh_initialize(0, ESP_USB_HS0_BASE); + usbh_initialize(0, ESP_USB_HS0_BASE); #else - usbh_initialize(0, ESP_USB_FS0_BASE); + usbh_initialize(0, ESP_USB_FS0_BASE); #endif - ESP_LOGI(TAG, "Init usb"); + ESP_LOGI(TAG, "Init usb"); #if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP - for (int i = 10; i >= 0; i--) { - ESP_LOGW(TAG, "Deinit usb after %d seconds...", i); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - ESP_LOGW(TAG, "Deinit usb"); - usbh_deinitialize(0); - goto reinit; + for (int i = 10; i >= 0; i--) { + ESP_LOGW(TAG, "Deinit usb after %d seconds...", i); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + ESP_LOGW(TAG, "Deinit usb"); + usbh_deinitialize(0); #endif + } } diff --git a/examples/peripherals/usb/host/cherryusb_host/main/msc.c b/examples/peripherals/usb/host/cherryusb_host/main/msc.c index ef888417fa..97f897c812 100644 --- a/examples/peripherals/usb/host/cherryusb_host/main/msc.c +++ b/examples/peripherals/usb/host/cherryusb_host/main/msc.c @@ -36,6 +36,10 @@ static SemaphoreHandle_t s_buff_mux = NULL; static size_t s_buff_size = 0; static uint8_t *s_buff = NULL; +void ld_include_msc(void) +{ +} + static DSTATUS usb_disk_initialize(BYTE pdrv) { return RES_OK; @@ -394,8 +398,6 @@ void usbh_msc_run(struct usbh_msc *msc_class) return; } -void usbh_msc_run_real(struct usbh_msc *) __attribute__((alias("usbh_msc_run"))); - void usbh_msc_stop(struct usbh_msc *msc_class) { msc_host_vfs_unregister(msc_class); diff --git a/examples/peripherals/usb/host/hid/main/hid_host_example.c b/examples/peripherals/usb/host/hid/main/hid_host_example.c index be8ee95cc2..29d016c462 100644 --- a/examples/peripherals/usb/host/hid/main/hid_host_example.c +++ b/examples/peripherals/usb/host/hid/main/hid_host_example.c @@ -87,8 +87,8 @@ typedef struct { #define KEYBOARD_ENTER_ALT_ESCAPE 1 #if KEYBOARD_ENTER_ALT_ESCAPE -static bool escaping = false; -static unsigned char escap_hex = 0; +static bool is_ansi = false; +static unsigned int alt_code = 0; #endif /** @@ -154,6 +154,24 @@ const uint8_t keycode2ascii [57][2] = { {'/', '?'} /* HID_KEY_SLASH */ }; +/** + * @brief HID Keyboard print char symbol + * + * @param[in] key_char Keyboard char to stdout + */ +static inline void hid_keyboard_print_char(unsigned int key_char) +{ + if (!!key_char) { + putchar(key_char); +#if (KEYBOARD_ENTER_LF_EXTEND) + if (KEYBOARD_ENTER_MAIN_CHAR == key_char) { + putchar('\n'); + } +#endif // KEYBOARD_ENTER_LF_EXTEND + fflush(stdout); + } +} + /** * @brief Makes new line depending on report output protocol type * @@ -211,6 +229,62 @@ static inline bool hid_keyboard_is_modifier_alt(uint8_t modifier) } return false; } + +/** + * @brief HID Keyboard alt code process(Called when ALT is pressed) + * + * @param[in] key_code Entered key value + * @return true Key values that qualify for ALT escape processing + * @return false Key values that do not comply with ALT escape processing + * + */ +static inline bool hid_keyboard_alt_code_processing(uint8_t key_code) +{ + if ((key_code < HID_KEY_KEYPAD_1) || (key_code > HID_KEY_KEYPAD_0)) { + return false; + } + if (key_code == HID_KEY_KEYPAD_0) { + if (alt_code == 0) { + is_ansi = true; + return true; + } + /* Note: Since the keyboard code 0 of the numeric keypad is not keyboard code 1 minus 1, the + * conversion is performed here to facilitate subsequent calculations of the input numbers. + */ + key_code = HID_KEY_KEYPAD_1 - 1; + } + alt_code = alt_code * 10 + (key_code - (HID_KEY_KEYPAD_1 - 1)); + return true; +} + +/** + * @brief HID Keyboard alt code process complete(Called when ALT is not pressed) + */ +static inline void hid_keyboard_alt_code_process_complete(void) +{ + if (alt_code > 0) { + alt_code = alt_code & 0xff; + if (is_ansi || alt_code == 0) { + char utf8_buffer[8] = { 0 }; + if (alt_code == 0) { + alt_code = 0x100; + } + //ANSI is processed as UTF8 + if (alt_code <= 0x7F) { + utf8_buffer[0] = (char)alt_code; + } else { + utf8_buffer[0] = 0xC0 | ((alt_code >> 6) & 0x1F); + utf8_buffer[1] = 0x80 | (alt_code & 0x3F); + } + printf("%s", utf8_buffer); + fflush(stdout); + } else { + hid_keyboard_print_char(alt_code); + } + alt_code = 0; + } + is_ansi = false; +} #endif /** @@ -230,14 +304,12 @@ static inline bool hid_keyboard_get_char(uint8_t modifier, uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0; #if KEYBOARD_ENTER_ALT_ESCAPE - if (escaping) { - if ((key_code >= HID_KEY_KEYPAD_1) && (key_code <= HID_KEY_KEYPAD_0)) { - if (key_code == HID_KEY_KEYPAD_0) { - key_code = HID_KEY_KEYPAD_1 - 1; - } - escap_hex = escap_hex * 10 + (key_code - (HID_KEY_KEYPAD_1 - 1)); + if (hid_keyboard_is_modifier_alt(modifier)) { + // ALT modifier is still pressed + if (hid_keyboard_alt_code_processing(key_code)) { + // ALT code processed, no need to go further + return false; } - return false; } #endif @@ -251,24 +323,6 @@ static inline bool hid_keyboard_get_char(uint8_t modifier, return true; } -/** - * @brief HID Keyboard print char symbol - * - * @param[in] key_char Keyboard char to stdout - */ -static inline void hid_keyboard_print_char(unsigned int key_char) -{ - if (!!key_char) { - putchar(key_char); -#if (KEYBOARD_ENTER_LF_EXTEND) - if (KEYBOARD_ENTER_MAIN_CHAR == key_char) { - putchar('\n'); - } -#endif // KEYBOARD_ENTER_LF_EXTEND - fflush(stdout); - } -} - /** * @brief Key Event. Key event with the key code, state and modifier. * @@ -328,16 +382,8 @@ static void hid_host_keyboard_report_callback(const uint8_t *const data, const i key_event_t key_event; #if KEYBOARD_ENTER_ALT_ESCAPE - if (hid_keyboard_is_modifier_alt(kb_report->modifier.val)) { - if (escaping == false) { - escaping = true; - escap_hex = 0; - } - } else { - if (escaping && escap_hex > 0) { - escaping = false; - hid_keyboard_print_char(escap_hex); - } + if (!hid_keyboard_is_modifier_alt(kb_report->modifier.val)) { + hid_keyboard_alt_code_process_complete(); } #endif