usbh_hid_lvgl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. * Copyright (c) 2025, sakumisu
  3. * Copyright (c) 2025, RCSN
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. //Refer to https://github.com/espressif/esp-bsp/blob/master/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_usbhid.c
  8. #include "usbh_core.h"
  9. #include "usbh_hid.h"
  10. #include "usbh_hid_lvgl.h"
  11. /* LVGL image of cursor */
  12. LV_IMG_DECLARE(img_cursor)
  13. const uint8_t keycode2ascii[57][2] = {
  14. {0, 0}, /* HID_KEY_NO_PRESS */
  15. {0, 0}, /* HID_KEY_ROLLOVER */
  16. {0, 0}, /* HID_KEY_POST_FAIL */
  17. {0, 0}, /* HID_KEY_ERROR_UNDEFINED */
  18. {'a', 'A'}, /* HID_KEY_A */
  19. {'b', 'B'}, /* HID_KEY_B */
  20. {'c', 'C'}, /* HID_KEY_C */
  21. {'d', 'D'}, /* HID_KEY_D */
  22. {'e', 'E'}, /* HID_KEY_E */
  23. {'f', 'F'}, /* HID_KEY_F */
  24. {'g', 'G'}, /* HID_KEY_G */
  25. {'h', 'H'}, /* HID_KEY_H */
  26. {'i', 'I'}, /* HID_KEY_I */
  27. {'j', 'J'}, /* HID_KEY_J */
  28. {'k', 'K'}, /* HID_KEY_K */
  29. {'l', 'L'}, /* HID_KEY_L */
  30. {'m', 'M'}, /* HID_KEY_M */
  31. {'n', 'N'}, /* HID_KEY_N */
  32. {'o', 'O'}, /* HID_KEY_O */
  33. {'p', 'P'}, /* HID_KEY_P */
  34. {'q', 'Q'}, /* HID_KEY_Q */
  35. {'r', 'R'}, /* HID_KEY_R */
  36. {'s', 'S'}, /* HID_KEY_S */
  37. {'t', 'T'}, /* HID_KEY_T */
  38. {'u', 'U'}, /* HID_KEY_U */
  39. {'v', 'V'}, /* HID_KEY_V */
  40. {'w', 'W'}, /* HID_KEY_W */
  41. {'x', 'X'}, /* HID_KEY_X */
  42. {'y', 'Y'}, /* HID_KEY_Y */
  43. {'z', 'Z'}, /* HID_KEY_Z */
  44. {'1', '!'}, /* HID_KEY_1 */
  45. {'2', '@'}, /* HID_KEY_2 */
  46. {'3', '#'}, /* HID_KEY_3 */
  47. {'4', '$'}, /* HID_KEY_4 */
  48. {'5', '%'}, /* HID_KEY_5 */
  49. {'6', '^'}, /* HID_KEY_6 */
  50. {'7', '&'}, /* HID_KEY_7 */
  51. {'8', '*'}, /* HID_KEY_8 */
  52. {'9', '('}, /* HID_KEY_9 */
  53. {'0', ')'}, /* HID_KEY_0 */
  54. {'\r', '\r'}, /* HID_KEY_ENTER */
  55. {0, 0}, /* HID_KEY_ESC */
  56. {'\b', 0}, /* HID_KEY_DEL */
  57. {0, 0}, /* HID_KEY_TAB */
  58. {' ', ' '}, /* HID_KEY_SPACE */
  59. {'-', '_'}, /* HID_KEY_MINUS */
  60. {'=', '+'}, /* HID_KEY_EQUAL */
  61. {'[', '{'}, /* HID_KEY_OPEN_BRACKET */
  62. {']', '}'}, /* HID_KEY_CLOSE_BRACKET */
  63. {'\\', '|'}, /* HID_KEY_BACK_SLASH */
  64. {'\\', '|'}, /* HID_KEY_SHARP */
  65. {';', ':'}, /* HID_KEY_COLON */
  66. {'\'', '"'}, /* HID_KEY_QUOTE */
  67. {'`', '~'}, /* HID_KEY_TILDE */
  68. {',', '<'}, /* HID_KEY_LESS */
  69. {'.', '>'}, /* HID_KEY_GREATER */
  70. {'/', '?'} /* HID_KEY_SLASH */
  71. };
  72. struct usbh_hid_lvgl {
  73. struct {
  74. lv_indev_t *indev; /* LVGL mouse input device driver */
  75. uint8_t sensitivity; /* Mouse sensitivity (cannot be zero) */
  76. int16_t x; /* Mouse X coordinate */
  77. int16_t y; /* Mouse Y coordinate */
  78. bool left_button; /* Mouse left button state */
  79. } mouse;
  80. struct {
  81. lv_indev_t *indev; /* LVGL keyboard input device driver */
  82. uint32_t last_key;
  83. bool pressed;
  84. } kb;
  85. };
  86. static struct usbh_hid_lvgl g_hid_lvgl;
  87. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_mouse_buffer[64];
  88. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_keyboard_buffer[64];
  89. #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
  90. static void usbh_hid_lvgl_read_mouse(lv_indev_t *indev_drv, lv_indev_data_t *data)
  91. {
  92. int16_t width = 0;
  93. int16_t height = 0;
  94. struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
  95. lv_display_t *disp = lv_indev_get_display(indev_drv);
  96. if (lv_display_get_rotation(disp) == LV_DISPLAY_ROTATION_0 || lv_display_get_rotation(disp) == LV_DISPLAY_ROTATION_180) {
  97. width = lv_display_get_physical_horizontal_resolution(disp);
  98. height = lv_display_get_vertical_resolution(disp);
  99. } else {
  100. width = lv_display_get_vertical_resolution(disp);
  101. height = lv_display_get_physical_horizontal_resolution(disp);
  102. }
  103. /* Screen borders */
  104. if (ctx->mouse.x < 0) {
  105. ctx->mouse.x = 0;
  106. } else if (ctx->mouse.x >= width * ctx->mouse.sensitivity) {
  107. ctx->mouse.x = (width * ctx->mouse.sensitivity) - 1;
  108. }
  109. if (ctx->mouse.y < 0) {
  110. ctx->mouse.y = 0;
  111. } else if (ctx->mouse.y >= height * ctx->mouse.sensitivity) {
  112. ctx->mouse.y = (height * ctx->mouse.sensitivity) - 1;
  113. }
  114. /* Get coordinates by rotation with sensitivity */
  115. switch (lv_display_get_rotation(disp)) {
  116. case LV_DISPLAY_ROTATION_0:
  117. data->point.x = ctx->mouse.x / ctx->mouse.sensitivity;
  118. data->point.y = ctx->mouse.y / ctx->mouse.sensitivity;
  119. break;
  120. case LV_DISPLAY_ROTATION_90:
  121. data->point.y = width - ctx->mouse.x / ctx->mouse.sensitivity;
  122. data->point.x = ctx->mouse.y / ctx->mouse.sensitivity;
  123. break;
  124. case LV_DISPLAY_ROTATION_180:
  125. data->point.x = width - ctx->mouse.x / ctx->mouse.sensitivity;
  126. data->point.y = height - ctx->mouse.y / ctx->mouse.sensitivity;
  127. break;
  128. case LV_DISPLAY_ROTATION_270:
  129. data->point.y = ctx->mouse.x / ctx->mouse.sensitivity;
  130. data->point.x = height - ctx->mouse.y / ctx->mouse.sensitivity;
  131. break;
  132. }
  133. if (ctx->mouse.left_button) {
  134. data->state = LV_INDEV_STATE_PRESSED;
  135. } else {
  136. data->state = LV_INDEV_STATE_RELEASED;
  137. }
  138. }
  139. static void usbh_hid_lvgl_read_keyboard(lv_indev_t *indev_drv, lv_indev_data_t *data)
  140. {
  141. (void)indev_drv;
  142. struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
  143. data->key = ctx->kb.last_key;
  144. if (ctx->kb.pressed) {
  145. data->state = LV_INDEV_STATE_PRESSED;
  146. ctx->kb.pressed = false;
  147. } else {
  148. data->state = LV_INDEV_STATE_RELEASED;
  149. ctx->kb.last_key = 0;
  150. }
  151. }
  152. #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
  153. static lv_indev_drv_t indev_drv;
  154. static lv_indev_drv_t keyboard_drv;
  155. static void hpm_lvgl_indev_read_cb(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
  156. {
  157. int16_t width = 0;
  158. int16_t height = 0;
  159. struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
  160. if ((indev_drv->disp->driver->rotated == LV_DISP_ROT_NONE) || (indev_drv->disp->driver->rotated == LV_DISP_ROT_180)) {
  161. width = indev_drv->disp->driver->hor_res;
  162. height = indev_drv->disp->driver->ver_res;
  163. } else {
  164. width = indev_drv->disp->driver->ver_res;
  165. height = indev_drv->disp->driver->hor_res;
  166. }
  167. /* Screen borders */
  168. if (ctx->mouse.x < 0) {
  169. ctx->mouse.x = 0;
  170. } else if (ctx->mouse.x >= width * ctx->mouse.sensitivity) {
  171. ctx->mouse.x = (width * ctx->mouse.sensitivity) - 1;
  172. }
  173. if (ctx->mouse.y < 0) {
  174. ctx->mouse.y = 0;
  175. } else if (ctx->mouse.y >= height * ctx->mouse.sensitivity) {
  176. ctx->mouse.y = (height * ctx->mouse.sensitivity) - 1;
  177. }
  178. /* Get coordinates by rotation with sensitivity */
  179. switch (indev_drv->disp->driver->rotated) {
  180. case LV_DISP_ROT_NONE:
  181. data->point.x = ctx->mouse.x / ctx->mouse.sensitivity;
  182. data->point.y = ctx->mouse.y / ctx->mouse.sensitivity;
  183. break;
  184. case LV_DISP_ROT_90:
  185. data->point.y = width - ctx->mouse.x / ctx->mouse.sensitivity;
  186. data->point.x = ctx->mouse.y / ctx->mouse.sensitivity;
  187. break;
  188. case LV_DISP_ROT_180:
  189. data->point.x = width - ctx->mouse.x / ctx->mouse.sensitivity;
  190. data->point.y = height - ctx->mouse.y / ctx->mouse.sensitivity;
  191. break;
  192. case LV_DISP_ROT_270:
  193. data->point.y = ctx->mouse.x / ctx->mouse.sensitivity;
  194. data->point.x = height - ctx->mouse.y / ctx->mouse.sensitivity;
  195. break;
  196. }
  197. if (ctx->mouse.left_button) {
  198. data->state = LV_INDEV_STATE_PRESSED;
  199. } else {
  200. data->state = LV_INDEV_STATE_RELEASED;
  201. }
  202. }
  203. static void usbh_hid_lvgl_read_keyboard(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
  204. {
  205. (void)indev_drv;
  206. struct usbh_hid_lvgl *ctx = &g_hid_lvgl;
  207. data->key = ctx->kb.last_key;
  208. if (ctx->kb.pressed) {
  209. data->state = LV_INDEV_STATE_PRESSED;
  210. ctx->kb.pressed = false;
  211. } else {
  212. data->state = LV_INDEV_STATE_RELEASED;
  213. ctx->kb.last_key = 0;
  214. }
  215. }
  216. #endif
  217. lv_indev_t *usbh_hid_lvgl_add_mouse(uint8_t sensitivity)
  218. {
  219. int32_t ver_res, hor_res;
  220. lv_indev_t *indev;
  221. /* Initialize USB HID */
  222. struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
  223. /* Mouse sensitivity cannot be zero */
  224. hid_ctx->mouse.sensitivity = (sensitivity == 0 ? 1 : sensitivity);
  225. #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
  226. ver_res = lv_display_get_vertical_resolution(lv_display_get_default());
  227. hor_res = lv_display_get_physical_horizontal_resolution(lv_display_get_default());
  228. #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
  229. lv_disp_t * disp = lv_disp_get_default();
  230. ver_res = disp->driver->hor_res;
  231. hor_res = disp->driver->ver_res;
  232. #endif
  233. /* Default coordinates to screen center */
  234. hid_ctx->mouse.x = (hor_res * hid_ctx->mouse.sensitivity) / 2;
  235. hid_ctx->mouse.y = (ver_res * hid_ctx->mouse.sensitivity) / 2;
  236. /* Register a mouse input device */
  237. #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
  238. indev = lv_indev_create();
  239. lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  240. lv_indev_set_read_cb(indev, usbh_hid_lvgl_read_mouse);
  241. lv_indev_set_driver_data(indev, hid_ctx);
  242. hid_ctx->mouse.indev = indev;
  243. #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
  244. lv_indev_drv_init(&indev_drv);
  245. indev_drv.read_cb = hpm_lvgl_indev_read_cb;
  246. indev_drv.type = LV_INDEV_TYPE_POINTER;
  247. indev_drv.user_data = (void *)hid_ctx;
  248. indev = lv_indev_drv_register(&indev_drv);
  249. #endif
  250. /* Set image of cursor */
  251. lv_obj_t *cursor;
  252. cursor = lv_img_create(lv_scr_act());
  253. lv_img_set_src(cursor, &img_cursor);
  254. lv_indev_set_cursor(indev, cursor);
  255. return indev;
  256. }
  257. lv_indev_t *usbh_hid_lvgl_add_keyboard(void)
  258. {
  259. lv_indev_t *indev;
  260. /* Initialize USB HID */
  261. struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
  262. /* Register a keyboard input device */
  263. #if defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 9)
  264. indev = lv_indev_create();
  265. lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
  266. lv_indev_set_read_cb(indev, usbh_hid_lvgl_read_keyboard);
  267. lv_indev_set_driver_data(indev, hid_ctx);
  268. hid_ctx->kb.indev = indev;
  269. #elif defined(LVGL_VERSION_MAJOR) && (LVGL_VERSION_MAJOR == 8)
  270. lv_indev_drv_init(&keyboard_drv);
  271. keyboard_drv.read_cb = usbh_hid_lvgl_read_keyboard;
  272. keyboard_drv.type = LV_INDEV_TYPE_KEYPAD;
  273. keyboard_drv.user_data = (void *)hid_ctx;
  274. indev = lv_indev_drv_register(&keyboard_drv);
  275. #endif
  276. return indev;
  277. }
  278. void usbh_hid_mouse_callback(void *arg, int nbytes)
  279. {
  280. struct usbh_hid *hid_class = (struct usbh_hid *)arg;
  281. if (nbytes > 0) {
  282. struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
  283. hid_ctx->mouse.left_button = hid_mouse_buffer[0];
  284. hid_ctx->mouse.x += (int8_t)hid_mouse_buffer[1];
  285. hid_ctx->mouse.y += (int8_t)hid_mouse_buffer[2];
  286. usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_mouse_buffer, hid_class->intin->wMaxPacketSize, 0,
  287. usbh_hid_mouse_callback, hid_class);
  288. usbh_submit_urb(&hid_class->intin_urb);
  289. } else if (nbytes == -USB_ERR_NAK) { /* only dwc2 should do this */
  290. usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_mouse_buffer, hid_class->intin->wMaxPacketSize, 0,
  291. usbh_hid_mouse_callback, hid_class);
  292. usbh_submit_urb(&hid_class->intin_urb);
  293. } else {
  294. }
  295. }
  296. static char usb_hid_get_keyboard_char(uint8_t key, uint8_t shift)
  297. {
  298. char ret_key = 0;
  299. static bool cap_lock = false;
  300. if (shift > 1) {
  301. shift = 1;
  302. }
  303. if ((key >= HID_KBD_USAGE_A) && (key <= HID_KBD_USAGE_QUESTION)) {
  304. ret_key = (cap_lock == false) ? keycode2ascii[key][0] : keycode2ascii[key][1];
  305. } else if ((key >= HID_KBD_USAGE_1) && (key <= HID_KBD_USAGE_QUESTION)) {
  306. ret_key = keycode2ascii[key][shift];
  307. } else if ((key >= HID_KBD_USAGE_KPD1) && (key <= HID_KBD_USAGE_KPD0)) {
  308. ret_key = keycode2ascii[(key - HID_KBD_USAGE_KPD1) + HID_KBD_USAGE_1][0];
  309. } else if ((key >= HID_KBD_USAGE_KPDDIV) && (key <= HID_KBD_USAGE_KPDEMTER)) {
  310. switch (key) {
  311. case HID_KBD_USAGE_KPDDIV:
  312. ret_key = '/';
  313. break;
  314. case HID_KBD_USAGE_KPDMUL:
  315. ret_key = '*';
  316. break;
  317. case HID_KBD_USAGE_KPDHMINUS:
  318. ret_key = '-';
  319. break;
  320. case HID_KBD_USAGE_KPDPLUS:
  321. ret_key = '+';
  322. break;
  323. default:
  324. break;
  325. }
  326. } else if (key == HID_KBD_USAGE_KPDDELETE) {
  327. ret_key = '.';
  328. } else if (key == HID_KBD_USAGE_CAPSLOCK) {
  329. cap_lock = !cap_lock;
  330. }
  331. return ret_key;
  332. }
  333. void usbh_hid_keyboard_callback(void *arg, int nbytes)
  334. {
  335. struct usbh_hid *hid_class = (struct usbh_hid *)arg;
  336. if (nbytes > 0) {
  337. struct usbh_hid_lvgl *hid_ctx = &g_hid_lvgl;
  338. struct usb_hid_kbd_report *keyboard = (struct usb_hid_kbd_report *)hid_keyboard_buffer;
  339. for (int i = 0; i < 6; i++) {
  340. if ((keyboard->key[i] <= HID_KBD_USAGE_MAX) && (keyboard->key[i] > HID_KBD_USAGE_NONE)) {
  341. char key = 0;
  342. /* LVGL special keys */
  343. if (keyboard->key[i] == HID_KBD_USAGE_TAB) {
  344. if (((keyboard->modifier & HID_MODIFIER_LSHIFT) || (keyboard->modifier & HID_MODIFIER_RSHIFT))) {
  345. key = LV_KEY_PREV;
  346. } else {
  347. key = LV_KEY_NEXT;
  348. }
  349. } else if (keyboard->key[i] == HID_KBD_USAGE_RIGHT) {
  350. key = LV_KEY_RIGHT;
  351. } else if (keyboard->key[i] == HID_KBD_USAGE_LEFT) {
  352. key = LV_KEY_LEFT;
  353. } else if (keyboard->key[i] == HID_KBD_USAGE_DOWN) {
  354. key = LV_KEY_DOWN;
  355. } else if (keyboard->key[i] == HID_KBD_USAGE_UP) {
  356. key = LV_KEY_UP;
  357. } else if (keyboard->key[i] == HID_KBD_USAGE_ENTER || keyboard->key[i] == HID_KBD_USAGE_KPDEMTER) {
  358. key = LV_KEY_ENTER;
  359. } else if (keyboard->key[i] == HID_KBD_USAGE_DELETE) {
  360. key = LV_KEY_BACKSPACE;
  361. } else if (keyboard->key[i] == HID_KBD_USAGE_HOME) {
  362. key = LV_KEY_HOME;
  363. } else if (keyboard->key[i] == HID_KBD_USAGE_END) {
  364. key = LV_KEY_END;
  365. } else if (keyboard->key[i] == HID_KBD_USAGE_DELFWD) {
  366. key = LV_KEY_DEL;
  367. } else {
  368. /* Get ASCII char */
  369. key = usb_hid_get_keyboard_char(keyboard->key[i], ((keyboard->modifier & HID_MODIFIER_LSHIFT) || (keyboard->modifier & HID_MODIFIER_RSHIFT)));
  370. }
  371. if (key == 0) {
  372. USB_LOG_ERR("Not recognized key: %c (%d)\r\n", keyboard->key[i], keyboard->key[i]);
  373. }
  374. hid_ctx->kb.last_key = key;
  375. hid_ctx->kb.pressed = true;
  376. }
  377. }
  378. usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
  379. usbh_hid_keyboard_callback, hid_class);
  380. usbh_submit_urb(&hid_class->intin_urb);
  381. } else if (nbytes == -USB_ERR_NAK) { /* only dwc2 should do this */
  382. usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
  383. usbh_hid_keyboard_callback, hid_class);
  384. usbh_submit_urb(&hid_class->intin_urb);
  385. } else {
  386. }
  387. }
  388. extern int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol);
  389. void usbh_hid_run(struct usbh_hid *hid_class)
  390. {
  391. usbh_hid_set_protocol(hid_class, 0);
  392. if (hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceProtocol == HID_PROTOCOL_KEYBOARD) {
  393. usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
  394. usbh_hid_keyboard_callback, hid_class);
  395. usbh_submit_urb(&hid_class->intin_urb);
  396. } else if (hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceProtocol == HID_PROTOCOL_MOUSE) {
  397. usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_mouse_buffer, hid_class->intin->wMaxPacketSize, 0,
  398. usbh_hid_mouse_callback, hid_class);
  399. usbh_submit_urb(&hid_class->intin_urb);
  400. } else {
  401. }
  402. }
  403. void usbh_hid_stop(struct usbh_hid *hid_class)
  404. {
  405. (void)hid_class;
  406. }