diff --git a/Makefile b/Makefile index e1b3b2c..2cd6bac 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,12 @@ CC ?= gcc LVGL_DIR_NAME ?= lvgl LVGL_DIR ?= ${shell pwd} CFLAGS ?= -O3 -g0 -I$(LVGL_DIR)/ -Wall -Wshadow -Wundef -Wmissing-prototypes -Wno-discarded-qualifiers -Wall -Wextra -Wno-unused-function -Wno-error=strict-prototypes -Wpointer-arith -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wmaybe-uninitialized -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wno-cast-qual -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wformat-security -Wno-ignored-qualifiers -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated -Wempty-body -Wtype-limits -Wshift-negative-value -Wstack-usage=2048 -Wno-unused-value -Wno-unused-parameter -Wno-missing-field-initializers -Wuninitialized -Wmaybe-uninitialized -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wpointer-arith -Wno-cast-qual -Wmissing-prototypes -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wno-discarded-qualifiers -Wformat-security -Wno-ignored-qualifiers -Wno-sign-compare -LDFLAGS ?= -lm -linput +LDFLAGS ?= -lm -linput -lxkbcommon BIN = unl0kr #Collect the files to compile -MAINSRC = ./main.c ./libinput_device_discovery.c ./libinput_keymap.c ./libinput_multi.c +MAINSRC = ./main.c ./libinput_device_discovery.c ./libinput_multi.c ./libinput_xkb.c include $(LVGL_DIR)/lvgl/lvgl.mk include $(LVGL_DIR)/lv_drivers/lv_drivers.mk diff --git a/libinput_keymap.c b/libinput_keymap.c deleted file mode 100644 index fc9b08c..0000000 --- a/libinput_keymap.c +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @file libinput_keymap.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "libinput_keymap.h" -#if USE_LIBINPUT || USE_BSD_LIBINPUT - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ -const MappedKey mapped_keys[LV_NUM_KEYS] = { - LV_MAPPED_KEY_NONE, // KEY_RESERVED - LV_MAPPED_KEY_NONE, // KEY_ESC - LV_MAPPED_KEY_1, // KEY_1 - LV_MAPPED_KEY_2, // KEY_2 - LV_MAPPED_KEY_3, // KEY_3 - LV_MAPPED_KEY_4, // KEY_4 - LV_MAPPED_KEY_5, // KEY_5 - LV_MAPPED_KEY_6, // KEY_6 - LV_MAPPED_KEY_7, // KEY_7 - LV_MAPPED_KEY_8, // KEY_8 - LV_MAPPED_KEY_9, // KEY_9 - LV_MAPPED_KEY_0, // KEY_0 - LV_MAPPED_KEY_MINUS, // KEY_MINUS - LV_MAPPED_KEY_EQUAL, // KEY_EQUAL - LV_MAPPED_KEY_NONE, // KEY_BACKSPACE - LV_MAPPED_KEY_NONE, // KEY_TAB - LV_MAPPED_KEY_Q, // KEY_Q - LV_MAPPED_KEY_W, // KEY_W - LV_MAPPED_KEY_E, // KEY_E - LV_MAPPED_KEY_R, // KEY_R - LV_MAPPED_KEY_T, // KEY_T - LV_MAPPED_KEY_Y, // KEY_Y - LV_MAPPED_KEY_U, // KEY_U - LV_MAPPED_KEY_I, // KEY_I - LV_MAPPED_KEY_O, // KEY_O - LV_MAPPED_KEY_P, // KEY_P - LV_MAPPED_KEY_LEFTBRACE, // KEY_LEFTBRACE - LV_MAPPED_KEY_RIGHTBRACE, // KEY_RIGHTBRACE - LV_MAPPED_KEY_NONE, // KEY_ENTER - LV_MAPPED_KEY_NONE, // KEY_LEFTCTRL - LV_MAPPED_KEY_A, // KEY_A - LV_MAPPED_KEY_S, // KEY_S - LV_MAPPED_KEY_D, // KEY_D - LV_MAPPED_KEY_F, // KEY_F - LV_MAPPED_KEY_G, // KEY_G - LV_MAPPED_KEY_H, // KEY_H - LV_MAPPED_KEY_J, // KEY_J - LV_MAPPED_KEY_K, // KEY_K - LV_MAPPED_KEY_L, // KEY_L - LV_MAPPED_KEY_SEMICOLON, // KEY_SEMICOLON - LV_MAPPED_KEY_APOSTROPHE, // KEY_APOSTROPHE - LV_MAPPED_KEY_GRAVE, // KEY_GRAVE - LV_MAPPED_KEY_NONE, // KEY_LEFTSHIFT - LV_MAPPED_KEY_BACKSLASH, // KEY_BACKSLASH - LV_MAPPED_KEY_Z, // KEY_Z - LV_MAPPED_KEY_X, // KEY_X - LV_MAPPED_KEY_C, // KEY_C - LV_MAPPED_KEY_V, // KEY_V - LV_MAPPED_KEY_B, // KEY_B - LV_MAPPED_KEY_N, // KEY_N - LV_MAPPED_KEY_M, // KEY_M - LV_MAPPED_KEY_COMMA, // KEY_COMMA - LV_MAPPED_KEY_DOT, // KEY_DOT - LV_MAPPED_KEY_SLASH // KEY_SLASH -}; - -const char keymap_lower[LV_NUM_KEYS_MAPPED] = { - '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', - 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', - 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/' -}; - -const char keymap_upper[LV_NUM_KEYS_MAPPED] = { - '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|', - 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', - 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?' -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */ diff --git a/libinput_keymap.h b/libinput_keymap.h deleted file mode 100644 index e22f6a6..0000000 --- a/libinput_keymap.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file libinput_keymap.h - * - */ - -#ifndef LVGL_LIBINPUT_KEYMAP_H -#define LVGL_LIBINPUT_KEYMAP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -// #ifndef LV_DRV_NO_CONF -// #ifdef LV_CONF_INCLUDE_SIMPLE -#include "lv_drv_conf.h" -// #else -// #include "../../lv_drv_conf.h" -// #endif -// #endif - -#if USE_LIBINPUT || USE_BSD_LIBINPUT - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -/********************* - * DEFINES - *********************/ - -#define LV_NUM_KEYS 54 -#define LV_NUM_KEYS_MAPPED 47 - -/********************** - * TYPEDEFS - **********************/ - -typedef enum { - LV_MAPPED_KEY_NONE = -1, - LV_MAPPED_KEY_GRAVE = 0, - LV_MAPPED_KEY_1 = 1, - LV_MAPPED_KEY_2 = 2, - LV_MAPPED_KEY_3 = 3, - LV_MAPPED_KEY_4 = 4, - LV_MAPPED_KEY_5 = 5, - LV_MAPPED_KEY_6 = 6, - LV_MAPPED_KEY_7 = 7, - LV_MAPPED_KEY_8 = 8, - LV_MAPPED_KEY_9 = 9, - LV_MAPPED_KEY_0 = 10, - LV_MAPPED_KEY_MINUS = 11, - LV_MAPPED_KEY_EQUAL = 12, - LV_MAPPED_KEY_Q = 13, - LV_MAPPED_KEY_W = 14, - LV_MAPPED_KEY_E = 15, - LV_MAPPED_KEY_R = 16, - LV_MAPPED_KEY_T = 17, - LV_MAPPED_KEY_Y = 18, - LV_MAPPED_KEY_U = 19, - LV_MAPPED_KEY_I = 20, - LV_MAPPED_KEY_O = 21, - LV_MAPPED_KEY_P = 22, - LV_MAPPED_KEY_LEFTBRACE = 23, - LV_MAPPED_KEY_RIGHTBRACE = 24, - LV_MAPPED_KEY_BACKSLASH = 25, - LV_MAPPED_KEY_A = 26, - LV_MAPPED_KEY_S = 27, - LV_MAPPED_KEY_D = 28, - LV_MAPPED_KEY_F = 29, - LV_MAPPED_KEY_G = 30, - LV_MAPPED_KEY_H = 31, - LV_MAPPED_KEY_J = 32, - LV_MAPPED_KEY_K = 33, - LV_MAPPED_KEY_L = 34, - LV_MAPPED_KEY_SEMICOLON = 35, - LV_MAPPED_KEY_APOSTROPHE = 36, - LV_MAPPED_KEY_Z = 37, - LV_MAPPED_KEY_X = 38, - LV_MAPPED_KEY_C = 39, - LV_MAPPED_KEY_V = 40, - LV_MAPPED_KEY_B = 41, - LV_MAPPED_KEY_N = 42, - LV_MAPPED_KEY_M = 43, - LV_MAPPED_KEY_COMMA = 44, - LV_MAPPED_KEY_DOT = 45, - LV_MAPPED_KEY_SLASH = 46 -} MappedKey; - -/********************** - * STATIC VARIABLES - **********************/ - -extern const MappedKey mapped_keys[LV_NUM_KEYS]; -extern const char keymap_lower[LV_NUM_KEYS_MAPPED]; -extern const char keymap_upper[LV_NUM_KEYS_MAPPED]; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/********************** - * MACROS - **********************/ - -#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LVGL_LIBINPUT_KEYMAP_H */ diff --git a/libinput_multi.c b/libinput_multi.c index af36665..d259a16 100644 --- a/libinput_multi.c +++ b/libinput_multi.c @@ -24,7 +24,7 @@ #include #endif -#include "libinput_keymap.h" +#include "libinput_xkb.h" /********************* * DEFINES @@ -44,6 +44,7 @@ typedef struct { int button; int libinput_key_val; struct libinput_device *device; + void *keyboard_state; int libinput_fd; struct libinput *libinput_context; @@ -56,7 +57,6 @@ typedef struct { static const int timeout = 0; // do not block static const nfds_t nfds = 1; static lv_point_t most_recent_touch_point = { .x = 0, .y = 0}; -static bool shift_down = false; static const struct libinput_interface interface = { .open_restricted = open_restricted, @@ -127,6 +127,8 @@ void libinput_multi_init_driver(lv_indev_drv_t * indev_drv) { state->fds[0].events = POLLIN; state->fds[0].revents = 0; + state->keyboard_state = libinput_xkb_create_state(); + indev_drv->user_data = (void *)state; } @@ -143,6 +145,8 @@ void libinput_multi_deinit_driver(lv_indev_drv_t * indev_drv) { libinput_unref(state->libinput_context); + // TODO: dealloc keyboard state + free(indev_drv->user_data); indev_drv->user_data = NULL; } @@ -154,12 +158,12 @@ void libinput_multi_deinit_driver(lv_indev_drv_t * indev_drv) { * @param data store the libinput data here * @return false: because the points are not buffered, so no more data to be read */ -bool libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) +void libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { libinput_multi_state *state = (libinput_multi_state *)indev_drv->user_data; if (!state) { perror("unable to read state from driver:"); - return false; + return; } struct libinput_event *event; @@ -209,43 +213,9 @@ bool libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) keyboard_event = libinput_event_get_keyboard_event(event); enum libinput_key_state key_state = libinput_event_keyboard_get_key_state(keyboard_event); uint32_t code = libinput_event_keyboard_get_key(keyboard_event); - if (code == KEY_LEFTSHIFT || code == KEY_RIGHTSHIFT) { - shift_down = key_state == LIBINPUT_KEY_STATE_PRESSED; - break; - } - state->button = (key_state == LIBINPUT_KEY_STATE_RELEASED) ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR; - switch(code) { - case KEY_BACKSPACE: - state->libinput_key_val = LV_KEY_BACKSPACE; - break; - case KEY_ENTER: - state->libinput_key_val = LV_KEY_ENTER; - break; - case KEY_PREVIOUS: - state->libinput_key_val = LV_KEY_PREV; - break; - case KEY_NEXT: - state->libinput_key_val = LV_KEY_NEXT; - break; - case KEY_UP: - state->libinput_key_val = LV_KEY_UP; - break; - case KEY_LEFT: - state->libinput_key_val = LV_KEY_LEFT; - break; - case KEY_RIGHT: - state->libinput_key_val = LV_KEY_RIGHT; - break; - case KEY_DOWN: - state->libinput_key_val = LV_KEY_DOWN; - break; - default: - if (code < LV_NUM_KEYS && mapped_keys[code] != LV_MAPPED_KEY_NONE) { - state->libinput_key_val = (shift_down ? keymap_upper : keymap_lower)[mapped_keys[code]]; - } else { - state->libinput_key_val = 0; - } - break; + state->libinput_key_val = libinput_xkb_process_key(code, key_state == LIBINPUT_KEY_STATE_PRESSED, state->keyboard_state); + if (state->libinput_key_val != 0) { + state->button = (key_state == LIBINPUT_KEY_STATE_RELEASED) ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR; // } break; default: @@ -258,8 +228,6 @@ report_most_recent_state: data->point.y = most_recent_touch_point.y; data->state = state->button; data->key = state->libinput_key_val; - - return false; } diff --git a/libinput_multi.h b/libinput_multi.h index 6c4df94..56aa9b7 100644 --- a/libinput_multi.h +++ b/libinput_multi.h @@ -65,7 +65,7 @@ bool libinput_multi_set_file(lv_indev_drv_t * indev_drv, char* dev_name); * @param data store the libinput data here * @return false: because the points are not buffered, so no more data to be read */ -bool libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); +void libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); /********************** diff --git a/libinput_xkb.c b/libinput_xkb.c new file mode 100644 index 0000000..a085ecf --- /dev/null +++ b/libinput_xkb.c @@ -0,0 +1,146 @@ +/** + * @file libinput_xkb.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "libinput_xkb.h" +#if USE_LIBINPUT || USE_BSD_LIBINPUT + +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ +static struct xkb_context *ctx = NULL; +static struct xkb_keymap *keymap = NULL; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +bool libinput_xkb_init(void) { + if (ctx) { + perror("context is already initialised"); + return true; + } + + ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!ctx) { + perror("could not create new XKB context"); + return false; + } + + struct xkb_rule_names names = { + .rules = NULL, + .model = "pc105", + .layout = "de", + .variant = "nodeadkeys", + .options = NULL + }; + + keymap = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!keymap) { + perror("could not create XKB keymap"); + return false; + } + + keymap = xkb_keymap_ref(keymap); + if (!keymap) { + perror("could not reference XKB keymap"); + return false; + } + + return true; +} + +void *libinput_xkb_create_state(void) { + struct xkb_state *state = xkb_state_new(keymap); + if (!state) { + perror("could not create XKB state"); + return false; + } + + state = xkb_state_ref(state); + if (!state) { + perror("could not reference XKB state"); + return false; + } + + return state; +} + +uint32_t libinput_xkb_process_key(uint32_t scancode, bool down, void *state) { + /* Offset the evdev scancode by 8, see https://xkbcommon.org/doc/current/xkbcommon_8h.html#ac29aee92124c08d1953910ab28ee1997 */ + xkb_keycode_t keycode = scancode + 8; + + uint32_t result = 0; + + switch (xkb_state_key_get_one_sym(state, keycode)) { + case XKB_KEY_BackSpace: + result = LV_KEY_BACKSPACE; + break; + case XKB_KEY_Return: + result = LV_KEY_ENTER; + break; + case XKB_KEY_Prior: + result = LV_KEY_PREV; + break; + case XKB_KEY_Next: + result = LV_KEY_NEXT; + break; + case XKB_KEY_Up: + result = LV_KEY_UP; + break; + case XKB_KEY_Left: + result = LV_KEY_LEFT; + break; + case XKB_KEY_Right: + result = LV_KEY_RIGHT; + break; + case XKB_KEY_Down: + result = LV_KEY_DOWN; + break; + default: + break; + } + + if (result == 0) { + char buffer[4] = { 0, 0, 0, 0 }; + int size = xkb_state_key_get_utf8((struct xkb_state *)state, keycode, NULL, 0) + 1; + if (size > 1) { + xkb_state_key_get_utf8((struct xkb_state *)state, keycode, buffer, size); + memcpy(&result, buffer, 4); + } + } + + xkb_state_update_key((struct xkb_state *)state, keycode, down ? XKB_KEY_DOWN : XKB_KEY_UP); + + return result; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */ diff --git a/libinput_xkb.h b/libinput_xkb.h new file mode 100644 index 0000000..a8f4f21 --- /dev/null +++ b/libinput_xkb.h @@ -0,0 +1,58 @@ +/** + * @file libinput_xkb.h + * + */ + +#ifndef LVGL_LIBINPUT_XKB_H +#define LVGL_LIBINPUT_XKB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +// #ifndef LV_DRV_NO_CONF +// #ifdef LV_CONF_INCLUDE_SIMPLE +#include "lv_drv_conf.h" +// #else +// #include "../../lv_drv_conf.h" +// #endif +// #endif + +#if USE_LIBINPUT || USE_BSD_LIBINPUT + +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +bool libinput_xkb_init(void); +void *libinput_xkb_create_state(void); +uint32_t libinput_xkb_process_key(uint32_t code, bool down, void *state); + +/********************** + * MACROS + **********************/ + +#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LVGL_LIBINPUT_XKB_H */ diff --git a/lv_drv_conf.h b/lv_drv_conf.h index 36f5577..6c7f009 100644 --- a/lv_drv_conf.h +++ b/lv_drv_conf.h @@ -383,14 +383,14 @@ #endif #if USE_LIBINPUT || USE_BSD_LIBINPUT -# define LIBINPUT_NAME "?" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ +# define LIBINPUT_NAME "/dev/input/event4" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ #endif /*USE_LIBINPUT*/ /*------------------------------------------------- * Mouse or touchpad as evdev interface (for Linux based systems) *------------------------------------------------*/ #ifndef USE_EVDEV -# define USE_EVDEV 0 +# define USE_EVDEV 1 #endif #ifndef USE_BSD_EVDEV @@ -398,7 +398,7 @@ #endif #if USE_EVDEV || USE_BSD_EVDEV -# define EVDEV_NAME "/dev/input/event8" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ +# define EVDEV_NAME "/dev/input/event4" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ # define EVDEV_SWAP_AXES 0 /*Swap the x and y axes of the touchscreen*/ # define EVDEV_CALIBRATE 1 /*Scale and offset the touchscreen coordinates by using maximum and minimum values for each axis*/ diff --git a/main.c b/main.c index 4602f15..028e7e1 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include "libinput_device_discovery.h" #include "libinput_multi.h" +#include "libinput_xkb.h" // Mouse cursor image (from https://github.com/lvgl/lv_sim_emscripten/blob/master/mouse_cursor_icon.c) @@ -135,9 +136,10 @@ void keyboard_event_cancel_cb(lv_event_t *e) { int main(void) { - // Initialise lvgl & framebuffer driver + // Initialise lvgl, framebuffer driver and XKB system lv_init(); fbdev_init(); + libinput_xkb_init(); // Query display size uint32_t hor_res;