21#include "../../SDL_internal.h"
26#ifdef SDL_INPUT_LINUXKD
34#include <linux/keyboard.h>
36#include <linux/tiocl.h>
40#include "../../events/SDL_events_c.h"
57 k_self, k_fn, k_spec, k_pad,\
58 k_dead, k_cons, k_cur, k_shift,\
59 k_meta, k_ascii, k_lock, k_lowercase,\
60 k_slock, k_dead2, k_brl, k_ignore
63static k_handler_fn K_HANDLERS;
64static k_handler_fn *k_handler[16] = { K_HANDLERS };
73static fn_handler_fn *fn_handler[] =
91 unsigned short **key_maps;
92 unsigned char shift_down[NR_SHIFT];
95 struct kbdiacrs *accents;
98 unsigned char lockstate;
99 unsigned char slockstate;
100 unsigned char ledflagstate;
103 unsigned int text_len;
111 printf(
"static struct kbdiacrs default_accents = {\n");
112 printf(
" %d,\n", kbd->accents->kb_cnt);
114 for (
i = 0;
i < kbd->accents->kb_cnt; ++
i) {
115 struct kbdiacr *diacr = &kbd->accents->kbdiacr[
i];
116 printf(
" { 0x%.2x, 0x%.2x, 0x%.2x },\n",
117 diacr->diacr, diacr->base, diacr->result);
120 printf(
" { 0x00, 0x00, 0x00 },\n");
133 for (
i = 0;
i < MAX_NR_KEYMAPS; ++
i) {
134 if (kbd->key_maps[
i]) {
135 printf(
"static unsigned short default_key_map_%d[NR_KEYS] = {",
i);
136 for (
j = 0;
j < NR_KEYS; ++
j) {
140 printf(
"0x%.4x, ", kbd->key_maps[
i][
j]);
146 printf(
"static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
147 for (
i = 0;
i < MAX_NR_KEYMAPS; ++
i) {
148 if (kbd->key_maps[
i]) {
149 printf(
" default_key_map_%d,\n",
i);
162 kbd->key_maps = (
unsigned short **)
SDL_calloc(MAX_NR_KEYMAPS,
sizeof(
unsigned short *));
163 if (!kbd->key_maps) {
167 for (
i = 0;
i < MAX_NR_KEYMAPS; ++
i) {
172 if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
176 if (kbe.kb_value == K_NOSUCHMAP) {
180 kbd->key_maps[
i] = (
unsigned short *)
SDL_malloc(NR_KEYS *
sizeof(
unsigned short));
181 if (!kbd->key_maps[
i]) {
185 for (
j = 0;
j < NR_KEYS; ++
j) {
188 if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
191 kbd->key_maps[
i][
j] = (kbe.kb_value ^ 0xf000);
198static int kbd_cleanup_sigactions_installed = 0;
199static int kbd_cleanup_atexit_installed = 0;
201static struct sigaction old_sigaction[NSIG];
203static int fatal_signals[] =
206 SIGHUP, SIGQUIT, SIGILL, SIGABRT,
207 SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
211static void kbd_cleanup(
void)
217 kbd_cleanup_state =
NULL;
219 ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
223SDL_EVDEV_kbd_reraise_signal(
int sig)
228siginfo_t* SDL_EVDEV_kdb_cleanup_siginfo =
NULL;
229void* SDL_EVDEV_kdb_cleanup_ucontext =
NULL;
231static void kbd_cleanup_signal_action(
int signum, siginfo_t* info,
void* ucontext)
233 struct sigaction* old_action_p = &(old_sigaction[signum]);
237 sigaction(signum, old_action_p,
NULL);
240 sigemptyset(&sigset);
241 sigaddset(&sigset, signum);
242 sigprocmask(SIG_UNBLOCK, &sigset,
NULL);
245 SDL_EVDEV_kdb_cleanup_siginfo = info;
246 SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
252 SDL_EVDEV_kbd_reraise_signal(signum);
255static void kbd_unregister_emerg_cleanup()
259 kbd_cleanup_state =
NULL;
261 if (!kbd_cleanup_sigactions_installed) {
264 kbd_cleanup_sigactions_installed = 0;
266 for (tabidx = 0; tabidx <
sizeof(fatal_signals) /
sizeof(fatal_signals[0]); ++tabidx) {
267 struct sigaction* old_action_p;
268 struct sigaction cur_action;
269 signum = fatal_signals[tabidx];
270 old_action_p = &(old_sigaction[signum]);
273 if (sigaction(signum,
NULL, &cur_action))
277 if (!(cur_action.sa_flags & SA_SIGINFO)
278 || cur_action.sa_sigaction != &kbd_cleanup_signal_action)
282 sigaction(signum, old_action_p,
NULL);
286static void kbd_cleanup_atexit(
void)
292 kbd_unregister_emerg_cleanup();
299 if (kbd_cleanup_state !=
NULL) {
302 kbd_cleanup_state = kbd;
304 if (!kbd_cleanup_atexit_installed) {
309 atexit(kbd_cleanup_atexit);
310 kbd_cleanup_atexit_installed = 1;
313 if (kbd_cleanup_sigactions_installed) {
316 kbd_cleanup_sigactions_installed = 1;
318 for (tabidx = 0; tabidx <
sizeof(fatal_signals) /
sizeof(fatal_signals[0]); ++tabidx) {
319 struct sigaction* old_action_p;
320 struct sigaction new_action;
321 signum = fatal_signals[tabidx];
322 old_action_p = &(old_sigaction[signum]);
323 if (sigaction(signum,
NULL, old_action_p))
329 if ((signum == SIGHUP || signum == SIGPIPE)
330 && (old_action_p->sa_handler != SIG_DFL
331 || (
void (*)(int))old_action_p->sa_sigaction != SIG_DFL))
334 new_action = *old_action_p;
335 new_action.sa_flags |= SA_SIGINFO;
336 new_action.sa_sigaction = &kbd_cleanup_signal_action;
337 sigaction(signum, &new_action,
NULL);
347 char shift_state[
sizeof (long) ] = {TIOCL_GETSHIFTSTATE, 0};
357 kbd->console_fd = open(
"/dev/tty", O_RDONLY);
359 if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
360 kbd->shift_state = *shift_state;
363 if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
364 kbd->ledflagstate = flag_state;
368 if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
373 if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
375 ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
377 if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
378 for (
i = 0;
i < MAX_NR_KEYMAPS; ++
i) {
379 if (kbd->key_maps[
i]) {
389 if (getenv(
"SDL_INPUT_LINUX_KEEP_KBD") ==
NULL) {
393 ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
399 kbd_register_emerg_cleanup(kbd);
405 SDL_EVDEV_dump_accents(kbd);
408 SDL_EVDEV_dump_keymap(kbd);
420 kbd_unregister_emerg_cleanup();
422 if (kbd->console_fd >= 0) {
424 ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
426 close(kbd->console_fd);
427 kbd->console_fd = -1;
432 for (
i = 0;
i < MAX_NR_KEYMAPS; ++
i) {
433 if (kbd->key_maps[
i]) {
449 if (kbd->text_len < (
sizeof(kbd->text)-1)) {
450 kbd->text[kbd->text_len++] = (char)
c;
459 else if (
c < 0x800) {
461 put_queue(kbd, 0xc0 | (
c >> 6));
462 put_queue(kbd, 0x80 | (
c & 0x3f));
463 }
else if (
c < 0x10000) {
464 if (
c >= 0xD800 &&
c < 0xE000)
469 put_queue(kbd, 0xe0 | (
c >> 12));
470 put_queue(kbd, 0x80 | ((
c >> 6) & 0x3f));
471 put_queue(kbd, 0x80 | (
c & 0x3f));
472 }
else if (
c < 0x110000) {
474 put_queue(kbd, 0xf0 | (
c >> 18));
475 put_queue(kbd, 0x80 | ((
c >> 12) & 0x3f));
476 put_queue(kbd, 0x80 | ((
c >> 6) & 0x3f));
477 put_queue(kbd, 0x80 | (
c & 0x3f));
490 unsigned int d = kbd->diacr;
495 for (
i = 0;
i < kbd->accents->kb_cnt;
i++) {
496 if (kbd->accents->kbdiacr[
i].diacr ==
d &&
497 kbd->accents->kbdiacr[
i].base == ch) {
498 return kbd->accents->kbdiacr[
i].result;
502 if (ch ==
' ' || ch ==
d)
512 return (kbd->ledflagstate & flag) != 0;
517 kbd->ledflagstate |= flag;
518 ioctl(kbd->console_fd, KDSETLED, (
unsigned long)(kbd->ledflagstate));
523 kbd->ledflagstate &= ~flag;
524 ioctl(kbd->console_fd, KDSETLED, (
unsigned long)(kbd->ledflagstate));
529 kbd->lockstate ^= 1 << flag;
534 kbd->slockstate ^= 1 << flag;
539 kbd->ledflagstate ^= flag;
540 ioctl(kbd->console_fd, KDSETLED, (
unsigned long)(kbd->ledflagstate));
550 put_utf8(kbd, kbd->diacr);
560 chg_vc_kbd_led(kbd, K_CAPSLOCK);
568 set_vc_kbd_led(kbd, K_CAPSLOCK);
574 chg_vc_kbd_led(kbd, K_NUMLOCK);
596 if (fn_handler[
value])
597 fn_handler[
value](kbd);
612 if (kbd->dead_key_next) {
617 put_utf8(kbd,
value);
625 kbd->diacr = (kbd->diacr ? handle_diacr(kbd,
value) :
value);
630 const unsigned char ret_diacr[NR_DEAD] = {
'`',
'\'',
'^',
'~',
'"',
',' };
632 k_deadunicode(kbd, ret_diacr[
value], up_flag);
637 k_deadunicode(kbd,
value, up_flag);
654 static const char pad_chars[] =
"0123456789+-*/\015,.?()#";
659 if (!vc_kbd_led(kbd, K_NUMLOCK)) {
664 put_queue(kbd, pad_chars[
value]);
669 int old_state = kbd->shift_state;
677 if (
value == KVAL(K_CAPSSHIFT)) {
678 value = KVAL(K_SHIFT);
680 clr_vc_kbd_led(kbd, K_CAPSLOCK);
688 if (kbd->shift_down[
value])
689 kbd->shift_down[
value]--;
691 kbd->shift_down[
value]++;
693 if (kbd->shift_down[
value])
694 kbd->shift_state |= (1 <<
value);
696 kbd->shift_state &= ~(1 <<
value);
699 if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
700 put_utf8(kbd, kbd->npadch);
725 if (kbd->npadch == -1)
728 kbd->npadch = kbd->npadch * base +
value;
733 if (up_flag || kbd->rep)
736 chg_vc_kbd_lock(kbd,
value);
741 k_shift(kbd,
value, up_flag);
742 if (up_flag || kbd->rep)
745 chg_vc_kbd_slock(kbd,
value);
747 if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
749 chg_vc_kbd_slock(kbd,
value);
760 unsigned char shift_final;
762 unsigned short *key_map;
763 unsigned short keysym;
769 kbd->rep = (down == 2);
771 shift_final = (kbd->shift_state | kbd->slockstate) ^ kbd->lockstate;
772 key_map = kbd->key_maps[shift_final];
775 kbd->shift_state = 0;
781 if (keycode < NR_KEYS) {
782 keysym = key_map[keycode];
791 put_utf8(kbd, keysym);
797 if (
type == KT_LETTER) {
800 if (vc_kbd_led(kbd, K_CAPSLOCK)) {
801 key_map = kbd->key_maps[shift_final ^ (1 << KG_SHIFT)];
803 keysym = key_map[keycode];
808 (*k_handler[
type])(kbd, keysym & 0xff, !down);
810 if (
type != KT_SLOCK) {
815 if (kbd->text_len > 0) {
816 kbd->text[kbd->text_len] =
'\0';
#define SDL_GetHintBoolean
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
SDL_EVDEV_keyboard_state * SDL_EVDEV_kbd_init(void)
struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state
static struct kbdiacrs default_accents
static unsigned short * default_key_maps[MAX_NR_KEYMAPS]
#define SDL_HINT_NO_SIGNAL_HANDLERS
Tell SDL not to catch the SIGINT or SIGTERM signals.
int SDL_SendKeyboardText(const char *text)
GLuint GLuint GLsizei GLenum type
GLsizei const GLfloat * value
#define SDL_arraysize(array)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
static char text[MAX_TEXT_LENGTH]