Add support for full keyboards

This commit is contained in:
Johannes Marbach 2021-09-04 15:30:58 +02:00
parent 19031ce99f
commit 94ae4e2b1d
9 changed files with 224 additions and 276 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -24,7 +24,7 @@
#include <linux/input.h>
#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;
}

View file

@ -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);
/**********************

146
libinput_xkb.c Normal file
View file

@ -0,0 +1,146 @@
/**
* @file libinput_xkb.c
*
*/
/*********************
* INCLUDES
*********************/
#include "libinput_xkb.h"
#if USE_LIBINPUT || USE_BSD_LIBINPUT
#include <stdio.h>
#include <stdlib.h>
#include <xkbcommon/xkbcommon.h>
/*********************
* 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 */

58
libinput_xkb.h Normal file
View file

@ -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 */

View file

@ -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*/

4
main.c
View file

@ -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;