summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2025-04-15 12:05:23 +0800
committersakumisu <[email protected]>2025-04-15 12:05:23 +0800
commit215db93943aa6ce89694f4df0fc45806668532ef (patch)
tree86a506857fd921697d59cc0bd92b9a107903aaf8
parentc916f63bc3e9eb726d67955eee7c69a33fbb8ce8 (diff)
feat(platform): add lvgl mouse&keyboard support
Signed-off-by: sakumisu <[email protected]>
-rw-r--r--platform/lvgl/image_cursor.c66
-rw-r--r--platform/lvgl/usbh_hid_lvgl.c327
-rw-r--r--platform/lvgl/usbh_hid_lvgl.h14
3 files changed, 407 insertions, 0 deletions
diff --git a/platform/lvgl/image_cursor.c b/platform/lvgl/image_cursor.c
new file mode 100644
index 00000000..0d062174
--- /dev/null
+++ b/platform/lvgl/image_cursor.c
@@ -0,0 +1,66 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef __has_include
+#if __has_include("lvgl.h")
+#ifndef LV_LVGL_H_INCLUDE_SIMPLE
+#define LV_LVGL_H_INCLUDE_SIMPLE
+#endif
+#endif
+#endif
+
+#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
+#include "lvgl.h"
+#else
+#include "lvgl/lvgl.h"
+#endif
+
+
+#ifndef LV_ATTRIBUTE_MEM_ALIGN
+#define LV_ATTRIBUTE_MEM_ALIGN
+#endif
+
+#ifndef LV_ATTRIBUTE_IMG_DUST
+#define LV_ATTRIBUTE_IMG_DUST
+#endif
+
+static const
+LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_DUST
+uint8_t img_cursor_20px_map[] = {
+
+ 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0xfc, 0x5b, 0x5b, 0x5b, 0xf1, 0x93, 0x93, 0x93, 0xfc, 0x41, 0x41, 0x41, 0xf9, 0x1e, 0x1e, 0x1e, 0xfe, 0x06, 0x06, 0x06, 0xf4, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xe4, 0x93, 0x93, 0x93, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xe3, 0xe3, 0xf9, 0xc8, 0xc8, 0xc8, 0xfe, 0x6c, 0x6c, 0x6c, 0xf3, 0x20, 0x20, 0x20, 0xfe, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xae, 0x41, 0x41, 0x41, 0xf9, 0xe3, 0xe3, 0xe3, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xfa, 0xac, 0xac, 0xac, 0xf0, 0x6f, 0x6f, 0x6f, 0xfb, 0x26, 0x26, 0x26, 0xf9, 0x0f, 0x0f, 0x0f, 0xff, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x1e, 0x1e, 0x1e, 0xfe, 0xc8, 0xc8, 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xfb, 0xd4, 0xd4, 0xd4, 0xf9, 0xae, 0xae, 0xae, 0xf6, 0x48, 0x48, 0x48, 0xf5, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x06, 0x06, 0x06, 0xf4, 0x6c, 0x6c, 0x6c, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0xf5, 0x7e, 0x7e, 0x7e, 0xf5, 0x12, 0x12, 0x12, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x20, 0x20, 0x20, 0xfe, 0xfb, 0xfb, 0xfb, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xef, 0xef, 0xf4, 0x73, 0x73, 0x73, 0xfc, 0x12, 0x12, 0x12, 0xfd, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xf8, 0xac, 0xac, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xf9, 0x2e, 0x2e, 0x2e, 0xfd, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0xd7, 0x6f, 0x6f, 0x6f, 0xfb, 0xfc, 0xfc, 0xfc, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xf9, 0x2e, 0x2e, 0x2e, 0xfd, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x9c, 0x26, 0x26, 0x26, 0xf9, 0xd4, 0xd4, 0xd4, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0xca, 0xca, 0xfa, 0x2b, 0x2b, 0x2b, 0xfc, 0x03, 0x03, 0x03, 0xdd, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x0f, 0x0f, 0x0f, 0xff, 0xae, 0xae, 0xae, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xb0, 0xb0, 0xfa, 0x2b, 0x2b, 0x2b, 0xfc, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe8, 0x48, 0x48, 0x48, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xf9, 0xc8, 0xc8, 0xc8, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0xca, 0xca, 0xfa, 0x2b, 0x2b, 0x2b, 0xfd, 0x03, 0x03, 0x03, 0xdd, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x1f, 0x1f, 0x1f, 0xff, 0xf2, 0xf2, 0xf2, 0xf5, 0xf0, 0xf0, 0xf0, 0xf4, 0x2e, 0x2e, 0x2e, 0xfd, 0x2e, 0x2e, 0x2e, 0xfd, 0xca, 0xca, 0xca, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xb0, 0xb0, 0xfa, 0x2b, 0x2b, 0x2b, 0xfc, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x2c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0xf0, 0x7e, 0x7e, 0x7e, 0xf5, 0x73, 0x73, 0x73, 0xfc, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xdd, 0x2b, 0x2b, 0x2b, 0xfc, 0xb0, 0xb0, 0xb0, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb1, 0xb1, 0xb1, 0xef, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xd7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xcb, 0x12, 0x12, 0x12, 0xfd, 0x12, 0x12, 0x12, 0xfd, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x37, 0x03, 0x03, 0x03, 0xdd, 0x2b, 0x2b, 0x2b, 0xfd, 0xca, 0xca, 0xca, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xfc, 0x86, 0x86, 0x86, 0xf2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xc2, 0x2b, 0x2b, 0x2b, 0xfc, 0xb0, 0xb0, 0xb0, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xfc, 0x74, 0x74, 0x74, 0xf8, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x16,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x03, 0x03, 0x03, 0xdd, 0x2b, 0x2b, 0x2b, 0xfc, 0xb1, 0xb1, 0xb1, 0xef, 0x86, 0x86, 0x86, 0xf2, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+};
+
+const lv_img_dsc_t img_cursor = {
+ .header.magic = LV_IMAGE_HEADER_MAGIC,
+ .header.cf = LV_COLOR_FORMAT_ARGB8888,
+ .header.flags = 0,
+ .header.w = 20,
+ .header.h = 20,
+ .header.stride = 80,
+ .data_size = 1600,
+ .data = img_cursor_20px_map,
+}; \ No newline at end of file
diff --git a/platform/lvgl/usbh_hid_lvgl.c b/platform/lvgl/usbh_hid_lvgl.c
new file mode 100644
index 00000000..253c10a0
--- /dev/null
+++ b/platform/lvgl/usbh_hid_lvgl.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * 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)
+
+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];
+
+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;
+ }
+ 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;
+ }
+
+ /* 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)
+{
+ 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;
+ }
+}
+
+lv_indev_t *usbh_hid_lvgl_add_mouse(uint8_t sensitivity)
+{
+ 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);
+
+ int32_t ver_res = lv_display_get_vertical_resolution(lv_display_get_default());
+ int32_t hor_res = lv_display_get_physical_horizontal_resolution(lv_display_get_default());
+
+ /* 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 */
+ 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;
+
+ /* 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 */
+ 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;
+
+ 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;
+
+ 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 */ // HOTFIX: for NonUS Keyboards repeat HID_KEY_BACK_SLASH
+ {';', ':'}, /* HID_KEY_COLON */
+ {'\'', '"'}, /* HID_KEY_QUOTE */
+ {'`', '~'}, /* HID_KEY_TILDE */
+ {',', '<'}, /* HID_KEY_LESS */
+ {'.', '>'}, /* HID_KEY_GREATER */
+ {'/', '?'} /* HID_KEY_SLASH */
+ };
+
+ if (shift > 1) {
+ shift = 1;
+ }
+
+ if ((key >= HID_KBD_USAGE_A) && (key <= HID_KBD_USAGE_QUESTION)) {
+ ret_key = keycode2ascii[key][shift];
+ }
+
+ 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) {
+ char key = 0;
+
+ /* LVGL special keys */
+ if (keyboard->key[i] == HID_KBD_USAGE_TAB) {
+ if (((keyboard->modifier & HID_MODIFER_LSHIFT) || (keyboard->modifier & HID_MODIFER_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_DEL;
+ } 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 {
+ /* Get ASCII char */
+ key = usb_hid_get_keyboard_char(keyboard->key[i], ((keyboard->modifier & HID_MODIFER_LSHIFT) || (keyboard->modifier & HID_MODIFER_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_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_keyboard_buffer, hid_class->intin->wMaxPacketSize, 0,
+ usbh_hid_mouse_callback, hid_class);
+ usbh_submit_urb(&hid_class->intin_urb);
+ } else {
+ }
+}
+
+void usbh_hid_run(struct usbh_hid *hid_class)
+{
+ 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)
+{
+} \ No newline at end of file
diff --git a/platform/lvgl/usbh_hid_lvgl.h b/platform/lvgl/usbh_hid_lvgl.h
new file mode 100644
index 00000000..50d05093
--- /dev/null
+++ b/platform/lvgl/usbh_hid_lvgl.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_HID_LVGL_H
+#define USBH_HID_LVGL_H
+
+#include "lvgl.h"
+
+lv_indev_t *usbh_hid_lvgl_add_mouse(uint8_t sensitivity);
+lv_indev_t *usbh_hid_lvgl_add_keyboard(void);
+
+#endif \ No newline at end of file