21 #include "../../SDL_internal.h" 26 #ifdef SDL_INPUT_LINUXKD 32 #include <sys/ioctl.h> 34 #include <linux/keyboard.h> 36 #include <linux/tiocl.h> 40 #include "../../events/SDL_events_c.h" 46 #define K_UNICODE 0x03 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 63 static k_handler_fn K_HANDLERS;
64 static k_handler_fn *k_handler[16] = { K_HANDLERS };
73 static 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);
198 static int kbd_cleanup_sigactions_installed = 0;
199 static int kbd_cleanup_atexit_installed = 0;
201 static struct sigaction old_sigaction[NSIG];
203 static int fatal_signals[] =
206 SIGHUP, SIGQUIT, SIGILL, SIGABRT,
207 SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
211 static void kbd_cleanup(
void)
217 kbd_cleanup_state =
NULL;
219 fprintf(stderr,
"(SDL restoring keyboard) ");
220 ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
224 SDL_EVDEV_kbd_reraise_signal(
int sig)
229 siginfo_t* SDL_EVDEV_kdb_cleanup_siginfo =
NULL;
230 void* SDL_EVDEV_kdb_cleanup_ucontext =
NULL;
232 static void kbd_cleanup_signal_action(
int signum, siginfo_t* info,
void* ucontext)
234 struct sigaction* old_action_p = &(old_sigaction[signum]);
238 sigaction(signum, old_action_p,
NULL);
241 sigemptyset(&sigset);
242 sigaddset(&sigset, signum);
243 sigprocmask(SIG_UNBLOCK, &sigset,
NULL);
246 SDL_EVDEV_kdb_cleanup_siginfo = info;
247 SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
253 SDL_EVDEV_kbd_reraise_signal(signum);
256 static void kbd_unregister_emerg_cleanup()
260 kbd_cleanup_state =
NULL;
262 if (!kbd_cleanup_sigactions_installed) {
265 kbd_cleanup_sigactions_installed = 0;
267 for (tabidx = 0; tabidx <
sizeof(fatal_signals) /
sizeof(fatal_signals[0]); ++tabidx) {
268 struct sigaction* old_action_p;
269 struct sigaction cur_action;
270 signum = fatal_signals[tabidx];
271 old_action_p = &(old_sigaction[signum]);
274 if (sigaction(signum,
NULL, &cur_action))
278 if (!(cur_action.sa_flags & SA_SIGINFO)
279 || cur_action.sa_sigaction != &kbd_cleanup_signal_action)
283 sigaction(signum, old_action_p,
NULL);
287 static void kbd_cleanup_atexit(
void)
293 kbd_unregister_emerg_cleanup();
300 if (kbd_cleanup_state !=
NULL) {
303 kbd_cleanup_state = kbd;
305 if (!kbd_cleanup_atexit_installed) {
310 atexit(kbd_cleanup_atexit);
311 kbd_cleanup_atexit_installed = 1;
314 if (kbd_cleanup_sigactions_installed) {
317 kbd_cleanup_sigactions_installed = 1;
319 for (tabidx = 0; tabidx <
sizeof(fatal_signals) /
sizeof(fatal_signals[0]); ++tabidx) {
320 struct sigaction* old_action_p;
321 struct sigaction new_action;
322 signum = fatal_signals[tabidx];
323 old_action_p = &(old_sigaction[signum]);
324 if (sigaction(signum,
NULL, old_action_p))
330 if ((signum == SIGHUP || signum == SIGPIPE)
331 && (old_action_p->sa_handler != SIG_DFL
332 || (
void (*)(int))old_action_p->sa_sigaction != SIG_DFL))
335 new_action = *old_action_p;
336 new_action.sa_flags |= SA_SIGINFO;
337 new_action.sa_sigaction = &kbd_cleanup_signal_action;
338 sigaction(signum, &new_action,
NULL);
348 char shift_state[2] = {TIOCL_GETSHIFTSTATE, 0};
358 kbd->console_fd = open(
"/dev/tty", O_RDONLY);
360 if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
361 kbd->shift_state = *shift_state;
364 if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
365 kbd->ledflagstate = flag_state;
369 if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
374 if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
376 ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
378 if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
379 for (i = 0; i < MAX_NR_KEYMAPS; ++
i) {
380 if (kbd->key_maps[i]) {
390 if (getenv(
"SDL_INPUT_LINUX_KEEP_KBD") ==
NULL) {
394 ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
400 kbd_register_emerg_cleanup(kbd);
406 SDL_EVDEV_dump_accents(kbd);
409 SDL_EVDEV_dump_keymap(kbd);
421 kbd_unregister_emerg_cleanup();
423 if (kbd->console_fd >= 0) {
425 ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
427 close(kbd->console_fd);
428 kbd->console_fd = -1;
433 for (i = 0; i < MAX_NR_KEYMAPS; ++
i) {
434 if (kbd->key_maps[i]) {
450 if (kbd->text_len < (
sizeof(kbd->text)-1)) {
451 kbd->text[kbd->text_len++] = (char)c;
460 else if (c < 0x800) {
462 put_queue(kbd, 0xc0 | (c >> 6));
463 put_queue(kbd, 0x80 | (c & 0x3f));
464 }
else if (c < 0x10000) {
465 if (c >= 0xD800 && c < 0xE000)
470 put_queue(kbd, 0xe0 | (c >> 12));
471 put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
472 put_queue(kbd, 0x80 | (c & 0x3f));
473 }
else if (c < 0x110000) {
475 put_queue(kbd, 0xf0 | (c >> 18));
476 put_queue(kbd, 0x80 | ((c >> 12) & 0x3f));
477 put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
478 put_queue(kbd, 0x80 | (c & 0x3f));
491 unsigned int d = kbd->diacr;
496 for (i = 0; i < kbd->accents->kb_cnt; i++) {
497 if (kbd->accents->kbdiacr[i].diacr == d &&
498 kbd->accents->kbdiacr[i].base == ch) {
499 return kbd->accents->kbdiacr[
i].result;
503 if (ch ==
' ' || ch == d)
513 return ((kbd->ledflagstate >> flag) & 1);
518 kbd->ledflagstate |= 1 << flag;
523 kbd->ledflagstate &= ~(1 << flag);
528 kbd->lockstate ^= 1 << flag;
533 kbd->slockstate ^= 1 << flag;
538 kbd->ledflagstate ^= 1 << flag;
548 put_utf8(kbd, kbd->diacr);
558 chg_vc_kbd_led(kbd, K_CAPSLOCK);
566 set_vc_kbd_led(kbd, K_CAPSLOCK);
572 chg_vc_kbd_led(kbd, K_NUMLOCK);
594 if (fn_handler[value])
595 fn_handler[
value](kbd);
608 value = handle_diacr(kbd, value);
610 if (kbd->dead_key_next) {
615 put_utf8(kbd, value);
623 kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);
628 const unsigned char ret_diacr[NR_DEAD] = {
'`',
'\'',
'^',
'~',
'"',
',' };
630 k_deadunicode(kbd, ret_diacr[value], up_flag);
635 k_deadunicode(kbd, value, up_flag);
652 static const char pad_chars[] =
"0123456789+-*/\015,.?()#";
657 if (!vc_kbd_led(kbd, K_NUMLOCK)) {
662 put_queue(kbd, pad_chars[value]);
667 int old_state = kbd->shift_state;
675 if (value == KVAL(K_CAPSSHIFT)) {
676 value = KVAL(K_SHIFT);
678 clr_vc_kbd_led(kbd, K_CAPSLOCK);
686 if (kbd->shift_down[value])
687 kbd->shift_down[
value]--;
689 kbd->shift_down[
value]++;
691 if (kbd->shift_down[value])
692 kbd->shift_state |= (1 <<
value);
694 kbd->shift_state &= ~(1 <<
value);
697 if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
698 put_utf8(kbd, kbd->npadch);
723 if (kbd->npadch == -1)
726 kbd->npadch = kbd->npadch * base +
value;
731 if (up_flag || kbd->rep)
734 chg_vc_kbd_lock(kbd, value);
739 k_shift(kbd, value, up_flag);
740 if (up_flag || kbd->rep)
743 chg_vc_kbd_slock(kbd, value);
745 if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
747 chg_vc_kbd_slock(kbd, value);
758 unsigned char shift_final;
760 unsigned short *key_map;
761 unsigned short keysym;
767 kbd->rep = (down == 2);
769 shift_final = (kbd->shift_state | kbd->slockstate) ^ kbd->lockstate;
770 key_map = kbd->key_maps[shift_final];
773 kbd->shift_state = 0;
779 if (keycode < NR_KEYS) {
780 keysym = key_map[keycode];
789 put_utf8(kbd, keysym);
795 if (type == KT_LETTER) {
798 if (vc_kbd_led(kbd, K_CAPSLOCK)) {
799 key_map = kbd->key_maps[shift_final ^ (1 << KG_SHIFT)];
801 keysym = key_map[keycode];
806 (*k_handler[
type])(kbd, keysym & 0xff, !down);
808 if (type != KT_SLOCK) {
813 if (kbd->text_len > 0) {
814 kbd->text[kbd->text_len] =
'\0';
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
static struct kbdiacrs default_accents
#define SDL_GetHintBoolean
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst base
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)
int SDL_SendKeyboardText(const char *text)
void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
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)
GLsizei const GLfloat * value
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)
SDL_EVDEV_keyboard_state * SDL_EVDEV_kbd_init(void)
static char text[MAX_TEXT_LENGTH]
#define SDL_HINT_NO_SIGNAL_HANDLERS
Tell SDL not to catch the SIGINT or SIGTERM signals.
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
static unsigned short * default_key_maps[MAX_NR_KEYMAPS]
GLuint GLuint GLsizei GLenum type
#define SDL_arraysize(array)
struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state