| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- /*
- * Copyright (c) 2025, sakumisu
- * Copyright (c) 2025, RCSN
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- //Refer to https://github.com/espressif/esp-bsp/blob/master/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_usbhid.c
- #include "usbh_core.h"
- #include "usbh_hid.h"
- #include "usbh_hid_lvgl.h"
- /* LVGL image of cursor */
- LV_IMG_DECLARE(img_cursor)
- const uint8_t keycode2ascii[57][2] = {
- {0, 0}, /* HID_KEY_NO_PRESS */
- {0, 0}, /* HID_KEY_ROLLOVER */
- {0, 0}, /* HID_KEY_POST_FAIL */
- {0, 0}, /* HID_KEY_ERROR_UNDEFINED */
- {'a', 'A'}, /* HID_KEY_A */
- {'b', 'B'}, /* HID_KEY_B */
- {'c', 'C'}, /* HID_KEY_C */
- {'d', 'D'}, /* HID_KEY_D */
- {'e', 'E'}, /* HID_KEY_E */
- {'f', 'F'}, /* HID_KEY_F */
- {'g', 'G'}, /* HID_KEY_G */
- {'h', 'H'}, /* HID_KEY_H */
- {'i', 'I'}, /* HID_KEY_I */
- {'j', 'J'}, /* HID_KEY_J */
- {'k', 'K'}, /* HID_KEY_K */
- {'l', 'L'}, /* HID_KEY_L */
- {'m', 'M'}, /* HID_KEY_M */
- {'n', 'N'}, /* HID_KEY_N */
- {'o', 'O'}, /* HID_KEY_O */
- {'p', 'P'}, /* HID_KEY_P */
- {'q', 'Q'}, /* HID_KEY_Q */
- {'r', 'R'}, /* HID_KEY_R */
- {'s', 'S'}, /* HID_KEY_S */
- {'t', 'T'}, /* HID_KEY_T */
- {'u', 'U'}, /* HID_KEY_U */
- {'v', 'V'}, /* HID_KEY_V */
- {'w', 'W'}, /* HID_KEY_W */
- {'x', 'X'}, /* HID_KEY_X */
- {'y', 'Y'}, /* HID_KEY_Y */
- {'z', 'Z'}, /* HID_KEY_Z */
- {'1', '!'}, /* HID_KEY_1 */
- {'2', '@'}, /* HID_KEY_2 */
- {'3', '#'}, /* HID_KEY_3 */
- {'4', '$'}, /* HID_KEY_4 */
- {'5', '%'}, /* HID_KEY_5 */
- {'6', '^'}, /* HID_KEY_6 */
- {'7', '&'}, /* HID_KEY_7 */
- {'8', '*'}, /* HID_KEY_8 */
- {'9', '('}, /* HID_KEY_9 */
- {'0', ')'}, /* HID_KEY_0 */
- {'\r', '\r'}, /* HID_KEY_ENTER */
- {0, 0}, /* HID_KEY_ESC */
- {'\b', 0}, /* HID_KEY_DEL */
- {0, 0}, /* HID_KEY_TAB */
- {' ', ' '}, /* HID_KEY_SPACE */
- {'-', '_'}, /* HID_KEY_MINUS */
- {'=', '+'}, /* HID_KEY_EQUAL */
- {'[', '{'}, /* HID_KEY_OPEN_BRACKET */
- {']', '}'}, /* HID_KEY_CLOSE_BRACKET */
- {'\\', '|'}, /* HID_KEY_BACK_SLASH */
- {'\\', '|'}, /* HID_KEY_SHARP */
- {';', ':'}, /* HID_KEY_COLON */
- {'\'', '"'}, /* HID_KEY_QUOTE */
- {'`', '~'}, /* HID_KEY_TILDE */
- {',', '<'}, /* HID_KEY_LESS */
- {'.', '>'}, /* HID_KEY_GREATER */
- {'/', '?'} /* HID_KEY_SLASH */
- };
- struct usbh_hid_lvgl {
- struct {
- lv_indev_t *indev; /* LVGL mouse input device driver */
- uint8_t sensitivity; /* Mouse sensitivity (cannot be zero) */
- int16_t x; /* Mouse X coordinate */
- int16_t y; /* Mouse Y coordinate */
- bool left_button; /* Mouse left button state */
- } mouse;
- struct {
- lv_indev_t *indev; /* LVGL keyboard input device driver */
- uint32_t last_key;
- bool pressed;
- } kb;
- };
- static struct usbh_hid_lvgl g_hid_lvgl;
- USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_mouse_buffer[64];
- USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_keyboard_buffer[64];
- #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
- static void usbh_hid_lvgl_read_mouse(lv_indev_t *indev_drv, lv_indev_data_t *data)
- {
- int16_t width = 0;
- int16_t height = 0;
- struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
- lv_display_t *disp = lv_indev_get_display(indev_drv);
- if (lv_display_get_rotation(disp) == LV_DISPLAY_ROTATION_0 || lv_display_get_rotation(disp) == LV_DISPLAY_ROTATION_180) {
- width = lv_display_get_physical_horizontal_resolution(disp);
- height = lv_display_get_vertical_resolution(disp);
- } else {
- width = lv_display_get_vertical_resolution(disp);
- height = lv_display_get_physical_horizontal_resolution(disp);
- }
- /* Screen borders */
- if (ctx->mouse.x < 0) {
- ctx->mouse.x = 0;
- } else if (ctx->mouse.x >= width * ctx->mouse.sensitivity) {
- ctx->mouse.x = (width * ctx->mouse.sensitivity) - 1;
- }
- if (ctx->mouse.y < 0) {
- ctx->mouse.y = 0;
- } else if (ctx->mouse.y >= height * ctx->mouse.sensitivity) {
- ctx->mouse.y = (height * ctx->mouse.sensitivity) - 1;
- }
- /* Get coordinates by rotation with sensitivity */
- switch (lv_display_get_rotation(disp)) {
- case LV_DISPLAY_ROTATION_0:
- data->point.x = ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.y = ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- case LV_DISPLAY_ROTATION_90:
- data->point.y = width - ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.x = ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- case LV_DISPLAY_ROTATION_180:
- data->point.x = width - ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.y = height - ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- case LV_DISPLAY_ROTATION_270:
- data->point.y = ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.x = height - ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- }
- if (ctx->mouse.left_button) {
- data->state = LV_INDEV_STATE_PRESSED;
- } else {
- data->state = LV_INDEV_STATE_RELEASED;
- }
- }
- static void usbh_hid_lvgl_read_keyboard(lv_indev_t *indev_drv, lv_indev_data_t *data)
- {
- (void)indev_drv;
- struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
- data->key = ctx->kb.last_key;
- if (ctx->kb.pressed) {
- data->state = LV_INDEV_STATE_PRESSED;
- ctx->kb.pressed = false;
- } else {
- data->state = LV_INDEV_STATE_RELEASED;
- ctx->kb.last_key = 0;
- }
- }
- #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
- static lv_indev_drv_t indev_drv;
- static lv_indev_drv_t keyboard_drv;
- static void hpm_lvgl_indev_read_cb(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
- {
- int16_t width = 0;
- int16_t height = 0;
- struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
-
- if ((indev_drv->disp->driver->rotated == LV_DISP_ROT_NONE) || (indev_drv->disp->driver->rotated == LV_DISP_ROT_180)) {
- width = indev_drv->disp->driver->hor_res;
- height = indev_drv->disp->driver->ver_res;
- } else {
- width = indev_drv->disp->driver->ver_res;
- height = indev_drv->disp->driver->hor_res;
- }
- /* Screen borders */
- if (ctx->mouse.x < 0) {
- ctx->mouse.x = 0;
- } else if (ctx->mouse.x >= width * ctx->mouse.sensitivity) {
- ctx->mouse.x = (width * ctx->mouse.sensitivity) - 1;
- }
- if (ctx->mouse.y < 0) {
- ctx->mouse.y = 0;
- } else if (ctx->mouse.y >= height * ctx->mouse.sensitivity) {
- ctx->mouse.y = (height * ctx->mouse.sensitivity) - 1;
- }
- /* Get coordinates by rotation with sensitivity */
- switch (indev_drv->disp->driver->rotated) {
- case LV_DISP_ROT_NONE:
- data->point.x = ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.y = ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- case LV_DISP_ROT_90:
- data->point.y = width - ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.x = ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- case LV_DISP_ROT_180:
- data->point.x = width - ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.y = height - ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- case LV_DISP_ROT_270:
- data->point.y = ctx->mouse.x / ctx->mouse.sensitivity;
- data->point.x = height - ctx->mouse.y / ctx->mouse.sensitivity;
- break;
- }
- if (ctx->mouse.left_button) {
- data->state = LV_INDEV_STATE_PRESSED;
- } else {
- data->state = LV_INDEV_STATE_RELEASED;
- }
- }
- static void usbh_hid_lvgl_read_keyboard(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
- {
- (void)indev_drv;
- struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
- data->key = ctx->kb.last_key;
- if (ctx->kb.pressed) {
- data->state = LV_INDEV_STATE_PRESSED;
- ctx->kb.pressed = false;
- } else {
- data->state = LV_INDEV_STATE_RELEASED;
- ctx->kb.last_key = 0;
- }
- }
- #endif
- lv_indev_t *usbh_hid_lvgl_add_mouse(uint8_t sensitivity)
- {
- int32_t ver_res, hor_res;
- lv_indev_t *indev;
- /* Initialize USB HID */
- struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
- /* Mouse sensitivity cannot be zero */
- hid_ctx->mouse.sensitivity = (sensitivity == 0 ? 1 : sensitivity);
- #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
- ver_res = lv_display_get_vertical_resolution(lv_display_get_default());
- hor_res = lv_display_get_physical_horizontal_resolution(lv_display_get_default());
- #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
- lv_disp_t * disp = lv_disp_get_default();
- ver_res = disp->driver->hor_res;
- hor_res = disp->driver->ver_res;
- #endif
- /* Default coordinates to screen center */
- hid_ctx->mouse.x = (hor_res * hid_ctx->mouse.sensitivity) / 2;
- hid_ctx->mouse.y = (ver_res * hid_ctx->mouse.sensitivity) / 2;
- /* Register a mouse input device */
- #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
- indev = lv_indev_create();
- lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
- lv_indev_set_read_cb(indev, usbh_hid_lvgl_read_mouse);
- lv_indev_set_driver_data(indev, hid_ctx);
- hid_ctx->mouse.indev = indev;
- #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
- lv_indev_drv_init(&indev_drv);
- indev_drv.read_cb = hpm_lvgl_indev_read_cb;
- indev_drv.type = LV_INDEV_TYPE_POINTER;
- indev_drv.user_data = (void *)hid_ctx;
- indev = lv_indev_drv_register(&indev_drv);
- #endif
- /* Set image of cursor */
- lv_obj_t *cursor;
- cursor = lv_img_create(lv_scr_act());
- lv_img_set_src(cursor, &img_cursor);
- lv_indev_set_cursor(indev, cursor);
- return indev;
- }
- lv_indev_t *usbh_hid_lvgl_add_keyboard(void)
- {
- lv_indev_t *indev;
- /* Initialize USB HID */
- struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
- /* Register a keyboard input device */
- #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
- indev = lv_indev_create();
- lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
- lv_indev_set_read_cb(indev, usbh_hid_lvgl_read_keyboard);
- lv_indev_set_driver_data(indev, hid_ctx);
- hid_ctx->kb.indev = indev;
- #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
- lv_indev_drv_init(&keyboard_drv);
- keyboard_drv.read_cb = usbh_hid_lvgl_read_keyboard;
- keyboard_drv.type = LV_INDEV_TYPE_KEYPAD;
- keyboard_drv.user_data = (void *)hid_ctx;
- indev = lv_indev_drv_register(&keyboard_drv);
- #endif
- return indev;
- }
- void usbh_hid_mouse_callback(void *arg, int nbytes)
- {
- struct usbh_hid *hid_class = (struct usbh_hid *)arg;
- if (nbytes > 0) {
- struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
- hid_ctx->mouse.left_button = hid_mouse_buffer[0];
- hid_ctx->mouse.x += (int8_t)hid_mouse_buffer[1];
- hid_ctx->mouse.y += (int8_t)hid_mouse_buffer[2];
- usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_mouse_buffer, hid_class->intin->wMaxPacketSize, 0,
- usbh_hid_mouse_callback, hid_class);
- usbh_submit_urb(&hid_class->intin_urb);
- } else if (nbytes == -USB_ERR_NAK) { /* only dwc2 should do this */
- usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_mouse_buffer, hid_class->intin->wMaxPacketSize, 0,
- usbh_hid_mouse_callback, hid_class);
- usbh_submit_urb(&hid_class->intin_urb);
- } else {
- }
- }
- static char usb_hid_get_keyboard_char(uint8_t key, uint8_t shift)
- {
- char ret_key = 0;
- static bool cap_lock = false;
- if (shift > 1) {
- shift = 1;
- }
- if ((key >= HID_KBD_USAGE_A) && (key <= HID_KBD_USAGE_QUESTION)) {
- ret_key = (cap_lock == false) ? keycode2ascii[key][0] : keycode2ascii[key][1];
- } else if ((key >= HID_KBD_USAGE_1) && (key <= HID_KBD_USAGE_QUESTION)) {
- ret_key = keycode2ascii[key][shift];
- } else if ((key >= HID_KBD_USAGE_KPD1) && (key <= HID_KBD_USAGE_KPD0)) {
- ret_key = keycode2ascii[(key - HID_KBD_USAGE_KPD1) + HID_KBD_USAGE_1][0];
- } else if ((key >= HID_KBD_USAGE_KPDDIV) && (key <= HID_KBD_USAGE_KPDEMTER)) {
- switch (key) {
- case HID_KBD_USAGE_KPDDIV:
- ret_key = '/';
- break;
- case HID_KBD_USAGE_KPDMUL:
- ret_key = '*';
- break;
- case HID_KBD_USAGE_KPDHMINUS:
- ret_key = '-';
- break;
- case HID_KBD_USAGE_KPDPLUS:
- ret_key = '+';
- break;
- default:
- break;
- }
- } else if (key == HID_KBD_USAGE_KPDDELETE) {
- ret_key = '.';
- } else if (key == HID_KBD_USAGE_CAPSLOCK) {
- cap_lock = !cap_lock;
- }
- return ret_key;
- }
- void usbh_hid_keyboard_callback(void *arg, int nbytes)
- {
- struct usbh_hid *hid_class = (struct usbh_hid *)arg;
- if (nbytes > 0) {
- struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
- struct usb_hid_kbd_report *keyboard = (struct usb_hid_kbd_report *)hid_keyboard_buffer;
- for (int i = 0; i < 6; i++) {
- if ((keyboard->key[i] <= HID_KBD_USAGE_MAX) && (keyboard->key[i] > HID_KBD_USAGE_NONE)) {
- char key = 0;
- /* LVGL special keys */
- if (keyboard->key[i] == HID_KBD_USAGE_TAB) {
- if (((keyboard->modifier & HID_MODIFIER_LSHIFT) || (keyboard->modifier & HID_MODIFIER_RSHIFT))) {
- key = LV_KEY_PREV;
- } else {
- key = LV_KEY_NEXT;
- }
- } else if (keyboard->key[i] == HID_KBD_USAGE_RIGHT) {
- key = LV_KEY_RIGHT;
- } else if (keyboard->key[i] == HID_KBD_USAGE_LEFT) {
- key = LV_KEY_LEFT;
- } else if (keyboard->key[i] == HID_KBD_USAGE_DOWN) {
- key = LV_KEY_DOWN;
- } else if (keyboard->key[i] == HID_KBD_USAGE_UP) {
- key = LV_KEY_UP;
- } else if (keyboard->key[i] == HID_KBD_USAGE_ENTER || keyboard->key[i] == HID_KBD_USAGE_KPDEMTER) {
- key = LV_KEY_ENTER;
- } else if (keyboard->key[i] == HID_KBD_USAGE_DELETE) {
- key = LV_KEY_BACKSPACE;
- } else if (keyboard->key[i] == HID_KBD_USAGE_HOME) {
- key = LV_KEY_HOME;
- } else if (keyboard->key[i] == HID_KBD_USAGE_END) {
- key = LV_KEY_END;
- } else if (keyboard->key[i] == HID_KBD_USAGE_DELFWD) {
- key = LV_KEY_DEL;
- } else {
- /* Get ASCII char */
- key = usb_hid_get_keyboard_char(keyboard->key[i], ((keyboard->modifier & HID_MODIFIER_LSHIFT) || (keyboard->modifier & HID_MODIFIER_RSHIFT)));
- }
- if (key == 0) {
- USB_LOG_ERR("Not recognized key: %c (%d)\r\n", keyboard->key[i], keyboard->key[i]);
- }
- hid_ctx->kb.last_key = key;
- hid_ctx->kb.pressed = true;
- }
- }
- usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
- usbh_hid_keyboard_callback, hid_class);
- usbh_submit_urb(&hid_class->intin_urb);
- } else if (nbytes == -USB_ERR_NAK) { /* only dwc2 should do this */
- usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
- usbh_hid_keyboard_callback, hid_class);
- usbh_submit_urb(&hid_class->intin_urb);
- } else {
- }
- }
- extern int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol);
- void usbh_hid_run(struct usbh_hid *hid_class)
- {
- usbh_hid_set_protocol(hid_class, 0);
- if (hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceProtocol == HID_PROTOCOL_KEYBOARD) {
- usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
- usbh_hid_keyboard_callback, hid_class);
- usbh_submit_urb(&hid_class->intin_urb);
- } else if (hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceProtocol == HID_PROTOCOL_MOUSE) {
- usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_mouse_buffer, hid_class->intin->wMaxPacketSize, 0,
- usbh_hid_mouse_callback, hid_class);
- usbh_submit_urb(&hid_class->intin_urb);
- } else {
- }
- }
- void usbh_hid_stop(struct usbh_hid *hid_class)
- {
- (void)hid_class;
- }
|