mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 18:10:57 +02:00
fix(usb): fix ths bug that ALT escape input for USB HID keyboard
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# The following lines of boilerplate have to be in your project's
|
# The following lines of boilerplate have to be in your project's
|
||||||
# CMakeLists in this exact order for cmake to work correctly
|
# 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)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
idf_build_set_property(MINIMAL_BUILD ON)
|
idf_build_set_property(MINIMAL_BUILD ON)
|
||||||
|
@@ -33,10 +33,11 @@ static TaskHandle_t s_task_handle = NULL;
|
|||||||
#define CDC_IN_EP 0x81
|
#define CDC_IN_EP 0x81
|
||||||
#define CDC_OUT_EP 0x01
|
#define CDC_OUT_EP 0x01
|
||||||
#define CDC_INT_EP 0x83
|
#define CDC_INT_EP 0x83
|
||||||
|
#if CDC_ACM_CHANNEL_NUM >= 2
|
||||||
#define CDC_IN_EP1 0x82
|
#define CDC_IN_EP1 0x82
|
||||||
#define CDC_OUT_EP1 0x02
|
#define CDC_OUT_EP1 0x02
|
||||||
#define CDC_INT_EP1 0x84
|
#define CDC_INT_EP1 0x84
|
||||||
|
#endif
|
||||||
|
|
||||||
#define USBD_VID 0xFFFF
|
#define USBD_VID 0xFFFF
|
||||||
#define USBD_PID 0xFFFF
|
#define USBD_PID 0xFFFF
|
||||||
@@ -44,7 +45,7 @@ static TaskHandle_t s_task_handle = NULL;
|
|||||||
#define USBD_LANGID_STRING 1033
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
/*!< config descriptor size */
|
/*!< 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_FS_MAX_MPS 64
|
||||||
#define CDC_HS_MAX_MPS 512
|
#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 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];
|
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[] = {
|
static const uint8_t device_descriptor[] = {
|
||||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
|
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,
|
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||||
.string_descriptor_callback = string_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)
|
void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||||
{
|
{
|
||||||
switch (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)
|
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);
|
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)
|
static void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||||
{
|
{
|
||||||
BaseType_t HPTaskAwoken = pdFALSE;
|
BaseType_t HPTaskAwoken = pdFALSE;
|
||||||
@@ -373,11 +293,8 @@ struct usbd_interface intf3;
|
|||||||
|
|
||||||
static void cdc_acm_init(void)
|
static void cdc_acm_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USBDEV_ADVANCE_DESC
|
|
||||||
usbd_desc_register(0, &cdc_descriptor);
|
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, &intf0));
|
||||||
usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1));
|
usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1));
|
||||||
usbd_add_endpoint(0, &cdc_out_ep);
|
usbd_add_endpoint(0, &cdc_out_ep);
|
||||||
@@ -396,11 +313,13 @@ static void cdc_acm_init(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Note: This callback is in the interrupt context
|
||||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||||
{
|
{
|
||||||
ESP_EARLY_LOGI(TAG, "intf:%u, dtr:%d", intf, 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)
|
void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
|
||||||
{
|
{
|
||||||
ESP_EARLY_LOGI(TAG, "intf:%u, rts:%d", intf, rts);
|
ESP_EARLY_LOGI(TAG, "intf:%u, rts:%d", intf, rts);
|
||||||
@@ -470,9 +389,9 @@ void cdc_acm_task(void *arg)
|
|||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
||||||
reinit :
|
while (1)
|
||||||
#endif
|
#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
|
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
||||||
@@ -485,7 +404,7 @@ reinit :
|
|||||||
while (s_task_handle) {
|
while (s_task_handle) {
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
goto reinit;
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
cherry-embedded/cherryusb: ~=1.5.1~8
|
cherry-embedded/cherryusb: 1.5.2~1
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# The following lines of boilerplate have to be in your project's
|
# The following lines of boilerplate have to be in your project's
|
||||||
# CMakeLists in this exact order for cmake to work correctly
|
# 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)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
idf_build_set_property(MINIMAL_BUILD ON)
|
idf_build_set_property(MINIMAL_BUILD ON)
|
||||||
|
@@ -7,6 +7,7 @@ endif()
|
|||||||
if(CONFIG_CHERRYUSB_HOST_CDC_ACM OR CONFIG_CHERRYUSB_HOST_FTDI OR CONFIG_CHERRYUSB_HOST_CH34X OR
|
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)
|
CONFIG_CHERRYUSB_HOST_CP210X OR CONFIG_CHERRYUSB_HOST_PL2303)
|
||||||
list(APPEND srcs "cdc_acm.c")
|
list(APPEND srcs "cdc_acm.c")
|
||||||
|
set(CHERRYUSB_HOST_CDC_ACM_INCLUDE TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_CHERRYUSB_HOST_MSC)
|
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||||
@@ -15,40 +16,20 @@ endif()
|
|||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES esp_timer fatfs
|
PRIV_REQUIRES esp_timer fatfs esp_ringbuf
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_CHERRYUSB_HOST_HID)
|
if(CONFIG_CHERRYUSB_HOST_HID)
|
||||||
# Make sure the definitions in hid.c are linked correctly
|
# 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()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_CHERRYUSB_HOST_CDC_ACM)
|
if(CHERRYUSB_HOST_CDC_ACM_INCLUDE)
|
||||||
# Make sure the definitions in hid.c are linked correctly
|
# Make sure the definitions in cdc_acm.c are linked correctly
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_cdc_acm_run_real")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_cdc_acm")
|
||||||
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")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_CHERRYUSB_HOST_MSC)
|
if(CONFIG_CHERRYUSB_HOST_MSC)
|
||||||
# Make sure the definitions in hid.c are linked correctly
|
# Make sure the definitions in msc.c are linked correctly
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usbh_msc_run_real")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_msc")
|
||||||
endif()
|
endif()
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/ringbuf.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
@@ -30,6 +31,10 @@
|
|||||||
|
|
||||||
static char *TAG = "CDC_ACM";
|
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 {
|
typedef enum {
|
||||||
SERIAL_TYPE_CDC_ACM = 0,
|
SERIAL_TYPE_CDC_ACM = 0,
|
||||||
SERIAL_TYPE_FTDI,
|
SERIAL_TYPE_FTDI,
|
||||||
@@ -54,6 +59,10 @@ typedef struct {
|
|||||||
static void free_serial_buffer(serial_t *serial);
|
static void free_serial_buffer(serial_t *serial);
|
||||||
static esp_err_t serial_start_in(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) \
|
#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); \
|
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);
|
heap_caps_free(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Note: This callback is in the interrupt context
|
||||||
static void serial_in_cb(void *arg, int nbytes)
|
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;
|
serial_t *serial = (serial_t *)arg;
|
||||||
uint8_t *data = serial->in_buffer;
|
uint8_t *data = serial->in_buffer;
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
@@ -105,17 +115,14 @@ static void serial_in_cb(void *arg, int nbytes)
|
|||||||
nbytes -= 2;
|
nbytes -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
if (s_recv_ringbuf) {
|
||||||
if (data[i] >= 0x20 && data[i] <= 0x7e) {
|
if (xRingbufferSendFromISR(s_recv_ringbuf, data, nbytes, &xTaskWoken) != pdTRUE) {
|
||||||
esp_rom_printf("%c", data[i]);
|
ESP_LOGD(TAG, "Ringbuffer send failed");
|
||||||
} else {
|
|
||||||
esp_rom_printf("[%02x]", data[i]);
|
|
||||||
if (data[i] == '\n') {
|
|
||||||
esp_rom_printf("\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (xTaskWoken == pdTRUE) {
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_start_in(serial);
|
serial_start_in(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +137,7 @@ static esp_err_t serial_start_in(serial_t *serial)
|
|||||||
return ESP_OK;
|
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;
|
int ret;
|
||||||
if (len > serial->bulkout->wMaxPacketSize) {
|
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;
|
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
|
#if CONFIG_CHERRYUSB_HOST_CDC_ACM
|
||||||
|
|
||||||
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
|
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");
|
ESP_LOGW(TAG, "Malloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
creat_printf_task();
|
||||||
cdc_acm_class->user_data = serial;
|
cdc_acm_class->user_data = serial;
|
||||||
|
|
||||||
struct cdc_line_coding linecoding = {
|
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);
|
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)
|
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
|
||||||
{
|
{
|
||||||
free_serial_buffer(cdc_acm_class->user_data);
|
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");
|
ESP_LOGW(TAG, "Malloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
creat_printf_task();
|
||||||
ftdi_class->user_data = serial;
|
ftdi_class->user_data = serial;
|
||||||
|
|
||||||
struct cdc_line_coding linecoding = {
|
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);
|
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)
|
void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
|
||||||
{
|
{
|
||||||
free_serial_buffer(ftdi_class->user_data);
|
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");
|
ESP_LOGW(TAG, "Malloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
creat_printf_task();
|
||||||
ch34x_class->user_data = serial;
|
ch34x_class->user_data = serial;
|
||||||
|
|
||||||
struct cdc_line_coding linecoding = {
|
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);
|
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)
|
void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
|
||||||
{
|
{
|
||||||
free_serial_buffer(ch34x_class->user_data);
|
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");
|
ESP_LOGW(TAG, "Malloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
creat_printf_task();
|
||||||
cp210x_class->user_data = serial;
|
cp210x_class->user_data = serial;
|
||||||
|
|
||||||
struct cdc_line_coding linecoding = {
|
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);
|
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)
|
void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
|
||||||
{
|
{
|
||||||
free_serial_buffer(cp210x_class->user_data);
|
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");
|
ESP_LOGW(TAG, "Malloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
creat_printf_task();
|
||||||
pl2303_class->user_data = serial;
|
pl2303_class->user_data = serial;
|
||||||
|
|
||||||
struct cdc_line_coding linecoding = {
|
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);
|
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)
|
void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
|
||||||
{
|
{
|
||||||
free_serial_buffer(pl2303_class->user_data);
|
free_serial_buffer(pl2303_class->user_data);
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
@@ -33,6 +34,19 @@ typedef struct {
|
|||||||
uint8_t key_code;
|
uint8_t key_code;
|
||||||
} key_event_t;
|
} 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 */
|
/* Main char symbol for ENTER key */
|
||||||
#define KEYBOARD_ENTER_MAIN_CHAR '\r'
|
#define KEYBOARD_ENTER_MAIN_CHAR '\r'
|
||||||
/* When set to 1 pressing ENTER will be extending with LineFeed during serial debug output */
|
/* 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
|
#define KEYBOARD_ENTER_ALT_ESCAPE 1
|
||||||
|
|
||||||
#if KEYBOARD_ENTER_ALT_ESCAPE
|
#if KEYBOARD_ENTER_ALT_ESCAPE
|
||||||
static bool escaping = false;
|
static bool is_ansi = false;
|
||||||
static unsigned char escap_hex = 0;
|
static unsigned int alt_code = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,6 +122,28 @@ const uint8_t keycode2ascii [57][2] = {
|
|||||||
{'/', '?'} /* HID_KBD_USAGE_QUESTION */
|
{'/', '?'} /* 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
|
* @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) {
|
if (prev_proto_output != proto) {
|
||||||
prev_proto_output = proto;
|
prev_proto_output = proto;
|
||||||
esp_rom_printf("\r\n");
|
printf("\r\n");
|
||||||
if (proto == HID_PROTOCOL_MOUSE) {
|
if (proto == HID_PROTOCOL_MOUSE) {
|
||||||
esp_rom_printf("Mouse\r\n");
|
printf("Mouse\r\n");
|
||||||
} else if (proto == HID_PROTOCOL_KEYBOARD) {
|
} else if (proto == HID_PROTOCOL_KEYBOARD) {
|
||||||
esp_rom_printf("Keyboard\r\n");
|
printf("Keyboard\r\n");
|
||||||
} else {
|
} 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;
|
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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -183,15 +276,11 @@ static inline bool hid_keyboard_get_char(uint8_t modifier,
|
|||||||
uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0;
|
uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0;
|
||||||
|
|
||||||
#if KEYBOARD_ENTER_ALT_ESCAPE
|
#if KEYBOARD_ENTER_ALT_ESCAPE
|
||||||
if (escaping) {
|
if (hid_keyboard_is_modifier_alt(modifier)) {
|
||||||
if ((key_code >= HID_KBD_USAGE_KPD1) && (key_code <= HID_KBD_USAGE_KPD0)) {
|
if (hid_keyboard_alt_code_processing(key_code)) {
|
||||||
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));
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((key_code >= HID_KBD_USAGE_A) && (key_code <= HID_KBD_USAGE_QUESTION)) {
|
if ((key_code >= HID_KBD_USAGE_A) && (key_code <= HID_KBD_USAGE_QUESTION)) {
|
||||||
@@ -204,23 +293,6 @@ static inline bool hid_keyboard_get_char(uint8_t modifier,
|
|||||||
return true;
|
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.
|
* @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;
|
key_event_t key_event;
|
||||||
|
|
||||||
#if KEYBOARD_ENTER_ALT_ESCAPE
|
#if KEYBOARD_ENTER_ALT_ESCAPE
|
||||||
if (hid_keyboard_is_modifier_alt(kb_report->modifier)) {
|
if (!hid_keyboard_is_modifier_alt(kb_report->modifier)) {
|
||||||
if (escaping == false) {
|
hid_keyboard_alt_code_process_complete();
|
||||||
escaping = true;
|
|
||||||
escap_hex = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (escaping && escap_hex > 0) {
|
|
||||||
escaping = false;
|
|
||||||
hid_keyboard_print_char(escap_hex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
hid_print_new_device_report_header(HID_PROTOCOL_MOUSE);
|
||||||
|
|
||||||
esp_rom_printf("X: %06d\tY: %06d\t|%c|%c|\n",
|
printf("X: %06d\tY: %06d\t|%c|%c|\n",
|
||||||
x_pos, y_pos,
|
x_pos, y_pos,
|
||||||
((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_LEFT) ? 'o' : ' '),
|
((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_LEFT) ? 'o' : ' '),
|
||||||
((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_RIGHT) ? 'o' : ' '));
|
((mouse_report->buttons & HID_MOUSE_INPUT_BUTTON_RIGHT) ? 'o' : ' '));
|
||||||
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbh_hid_generic_report_callback(void *arg, int nbytes)
|
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);
|
hid_print_new_device_report_header(HID_PROTOCOL_NONE);
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
for (int i = 0; i < nbytes; i++) {
|
||||||
esp_rom_printf("%02x ", data[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)
|
static void usbh_hid_callback(void *arg, int nbytes)
|
||||||
{
|
{
|
||||||
|
BaseType_t xTaskWoken = pdFALSE;
|
||||||
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||||
hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data;
|
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 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;
|
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 (s_msg_queue) {
|
||||||
|
hid_msg_t msg;
|
||||||
|
if (nbytes <= sizeof(msg.data)) {
|
||||||
|
msg.protocol = HID_PROTOCOL_NONE;
|
||||||
if (sub_class == HID_SUBCLASS_BOOTIF) {
|
if (sub_class == HID_SUBCLASS_BOOTIF) {
|
||||||
if (protocol == HID_PROTOCOL_KEYBOARD) {
|
if (protocol == HID_PROTOCOL_KEYBOARD) {
|
||||||
complete_cb = usbh_hid_keyboard_report_callback;
|
msg.protocol = HID_PROTOCOL_KEYBOARD;
|
||||||
} else if (protocol == HID_PROTOCOL_MOUSE) {
|
} else if (protocol == HID_PROTOCOL_MOUSE) {
|
||||||
complete_cb = usbh_hid_mouse_report_callback;
|
msg.protocol = HID_PROTOCOL_MOUSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
complete_cb(hid_intin->buffer, nbytes);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
hid_intin->is_active = false;
|
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)
|
static void intin_timer_cb(void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
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)
|
void usbh_hid_run(struct usbh_hid *hid_class)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -404,6 +520,8 @@ void usbh_hid_run(struct usbh_hid *hid_class)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
creat_msg_task();
|
||||||
|
|
||||||
if (hid_class->intin == NULL) {
|
if (hid_class->intin == NULL) {
|
||||||
ESP_LOGW(TAG, "no intin ep desc");
|
ESP_LOGW(TAG, "no intin ep desc");
|
||||||
return;
|
return;
|
||||||
@@ -449,8 +567,6 @@ error:
|
|||||||
heap_caps_free(hid_intin);
|
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)
|
void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||||
{
|
{
|
||||||
hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data;
|
hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data;
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
cherry-embedded/cherryusb: ~=1.5.1~8
|
cherry-embedded/cherryusb: 1.5.2~1
|
||||||
|
@@ -41,9 +41,9 @@ void app_main(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
||||||
reinit:
|
while (1)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
#if CONFIG_EXAMPLE_USB_HOST_RHPORT_HS
|
#if CONFIG_EXAMPLE_USB_HOST_RHPORT_HS
|
||||||
usbh_initialize(0, ESP_USB_HS0_BASE);
|
usbh_initialize(0, ESP_USB_HS0_BASE);
|
||||||
#else
|
#else
|
||||||
@@ -59,7 +59,7 @@ reinit:
|
|||||||
}
|
}
|
||||||
ESP_LOGW(TAG, "Deinit usb");
|
ESP_LOGW(TAG, "Deinit usb");
|
||||||
usbh_deinitialize(0);
|
usbh_deinitialize(0);
|
||||||
goto reinit;
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,10 @@ static SemaphoreHandle_t s_buff_mux = NULL;
|
|||||||
static size_t s_buff_size = 0;
|
static size_t s_buff_size = 0;
|
||||||
static uint8_t *s_buff = NULL;
|
static uint8_t *s_buff = NULL;
|
||||||
|
|
||||||
|
void ld_include_msc(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static DSTATUS usb_disk_initialize(BYTE pdrv)
|
static DSTATUS usb_disk_initialize(BYTE pdrv)
|
||||||
{
|
{
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
@@ -394,8 +398,6 @@ void usbh_msc_run(struct usbh_msc *msc_class)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbh_msc_run_real(struct usbh_msc *) __attribute__((alias("usbh_msc_run")));
|
|
||||||
|
|
||||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||||
{
|
{
|
||||||
msc_host_vfs_unregister(msc_class);
|
msc_host_vfs_unregister(msc_class);
|
||||||
|
@@ -87,8 +87,8 @@ typedef struct {
|
|||||||
#define KEYBOARD_ENTER_ALT_ESCAPE 1
|
#define KEYBOARD_ENTER_ALT_ESCAPE 1
|
||||||
|
|
||||||
#if KEYBOARD_ENTER_ALT_ESCAPE
|
#if KEYBOARD_ENTER_ALT_ESCAPE
|
||||||
static bool escaping = false;
|
static bool is_ansi = false;
|
||||||
static unsigned char escap_hex = 0;
|
static unsigned int alt_code = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,6 +154,24 @@ const uint8_t keycode2ascii [57][2] = {
|
|||||||
{'/', '?'} /* HID_KEY_SLASH */
|
{'/', '?'} /* 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
|
* @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;
|
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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,15 +304,13 @@ static inline bool hid_keyboard_get_char(uint8_t modifier,
|
|||||||
uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0;
|
uint8_t mod = (hid_keyboard_is_modifier_shift(modifier)) ? 1 : 0;
|
||||||
|
|
||||||
#if KEYBOARD_ENTER_ALT_ESCAPE
|
#if KEYBOARD_ENTER_ALT_ESCAPE
|
||||||
if (escaping) {
|
if (hid_keyboard_is_modifier_alt(modifier)) {
|
||||||
if ((key_code >= HID_KEY_KEYPAD_1) && (key_code <= HID_KEY_KEYPAD_0)) {
|
// ALT modifier is still pressed
|
||||||
if (key_code == HID_KEY_KEYPAD_0) {
|
if (hid_keyboard_alt_code_processing(key_code)) {
|
||||||
key_code = HID_KEY_KEYPAD_1 - 1;
|
// ALT code processed, no need to go further
|
||||||
}
|
|
||||||
escap_hex = escap_hex * 10 + (key_code - (HID_KEY_KEYPAD_1 - 1));
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((key_code >= HID_KEY_A) && (key_code <= HID_KEY_SLASH)) {
|
if ((key_code >= HID_KEY_A) && (key_code <= HID_KEY_SLASH)) {
|
||||||
@@ -251,24 +323,6 @@ static inline bool hid_keyboard_get_char(uint8_t modifier,
|
|||||||
return true;
|
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.
|
* @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;
|
key_event_t key_event;
|
||||||
|
|
||||||
#if KEYBOARD_ENTER_ALT_ESCAPE
|
#if KEYBOARD_ENTER_ALT_ESCAPE
|
||||||
if (hid_keyboard_is_modifier_alt(kb_report->modifier.val)) {
|
if (!hid_keyboard_is_modifier_alt(kb_report->modifier.val)) {
|
||||||
if (escaping == false) {
|
hid_keyboard_alt_code_process_complete();
|
||||||
escaping = true;
|
|
||||||
escap_hex = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (escaping && escap_hex > 0) {
|
|
||||||
escaping = false;
|
|
||||||
hid_keyboard_print_char(escap_hex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user