2 * (C) Gražvydas "notaz" Ignotas, 2010
4 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
5 * See the COPYING file in the top-level directory.
12 #include <sys/ioctl.h>
16 #include <linux/input.h>
21 static int osdl_evdev_devs[32];
22 static int osdl_evdev_dev_count;
24 static short osdl_evdev_map[KEY_CNT] = {
61 [KEY_SPACE] = SDLK_SPACE,
62 [KEY_BACKSPACE] = SDLK_BACKSPACE,
64 [KEY_DOT] = SDLK_PERIOD,
65 [KEY_ENTER] = SDLK_RETURN,
66 [KEY_LEFTSHIFT] = SDLK_LSHIFT,
67 [KEY_COMMA] = SDLK_COMMA,
68 // [KEY_BRIGHTNESSUP] =
69 // [KEY_BRIGHTNESSDOWN] =
72 [KEY_INSERT] = SDLK_INSERT,
73 [KEY_EQUAL] = SDLK_EQUALS,
74 [KEY_KPPLUS] = SDLK_KP_PLUS,
75 [KEY_BACKSLASH] = SDLK_BACKSLASH,
76 [KEY_RIGHTBRACE]= SDLK_RIGHTBRACKET,
77 [KEY_KPMINUS] = SDLK_KP_MINUS,
78 [KEY_QUESTION] = SDLK_QUESTION,
79 [KEY_LEFTBRACE] = SDLK_LEFTBRACKET,
80 [KEY_SLASH] = SDLK_SLASH,
82 [KEY_APOSTROPHE]= SDLK_QUOTE,
83 [KEY_ESC] = SDLK_ESCAPE,
84 [KEY_CAPSLOCK] = SDLK_CAPSLOCK,
85 [KEY_SEMICOLON] = SDLK_SEMICOLON,
98 [KEY_F13] = KEY_F13, /* apostrophe, differs from Fn-A? */
99 [KEY_F14] = KEY_F14, /* pipe/bar */
100 [KEY_F15] = KEY_F15, /* dash */
101 [KEY_F16] = SDLK_HASH, /* # (pound/hash) */
102 [KEY_F17] = SDLK_EXCLAIM, /* ! */
103 // [KEY_F18] = /* £ (pound) */
104 [KEY_F19] = SDLK_QUOTEDBL,/* " */
105 [KEY_F20] = SDLK_AT, /* @ */
106 [KEY_F21] = SDLK_SEMICOLON,/* : */
111 [KEY_DOWN] = SDLK_DOWN,
112 [KEY_LEFT] = SDLK_LEFT,
113 [KEY_RIGHT] = SDLK_RIGHT,
114 [KEY_HOME] = SDLK_HOME,
115 [KEY_END] = SDLK_END,
116 [KEY_PAGEUP] = SDLK_PAGEUP,
117 [KEY_PAGEDOWN] = SDLK_PAGEDOWN,
118 [KEY_LEFTALT] = SDLK_LALT,
119 [KEY_LEFTCTRL] = SDLK_LCTRL,
121 [KEY_RIGHTSHIFT]= SDLK_RSHIFT,
122 [KEY_RIGHTCTRL] = SDLK_RCTRL,
125 static const char * const osdl_evdev_keys[KEY_CNT] = {
126 [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
127 [KEY_1] = "1", [KEY_2] = "2",
128 [KEY_3] = "3", [KEY_4] = "4",
129 [KEY_5] = "5", [KEY_6] = "6",
130 [KEY_7] = "7", [KEY_8] = "8",
131 [KEY_9] = "9", [KEY_0] = "0",
132 [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal",
133 [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab",
134 [KEY_Q] = "Q", [KEY_W] = "W",
135 [KEY_E] = "E", [KEY_R] = "R",
136 [KEY_T] = "T", [KEY_Y] = "Y",
137 [KEY_U] = "U", [KEY_I] = "I",
138 [KEY_O] = "O", [KEY_P] = "P",
139 [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace",
140 [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl",
141 [KEY_A] = "A", [KEY_S] = "S",
142 [KEY_D] = "D", [KEY_F] = "F",
143 [KEY_G] = "G", [KEY_H] = "H",
144 [KEY_J] = "J", [KEY_K] = "K",
145 [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon",
146 [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave",
147 [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash",
148 [KEY_Z] = "Z", [KEY_X] = "X",
149 [KEY_C] = "C", [KEY_V] = "V",
150 [KEY_B] = "B", [KEY_N] = "N",
151 [KEY_M] = "M", [KEY_COMMA] = "Comma",
152 [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash",
153 [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk",
154 [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space",
155 [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1",
156 [KEY_F2] = "F2", [KEY_F3] = "F3",
157 [KEY_F4] = "F4", [KEY_F5] = "F5",
158 [KEY_F6] = "F6", [KEY_F7] = "F7",
159 [KEY_F8] = "F8", [KEY_F9] = "F9",
160 [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock",
161 [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7",
162 [KEY_KP8] = "KP8", [KEY_KP9] = "KP9",
163 [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4",
164 [KEY_KP5] = "KP5", [KEY_KP6] = "KP6",
165 [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1",
166 [KEY_KP2] = "KP2", [KEY_KP3] = "KP3",
167 [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot",
168 [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
169 [KEY_F11] = "F11", [KEY_F12] = "F12",
170 [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter",
171 [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash",
172 [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt",
173 [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home",
174 [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp",
175 [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right",
176 [KEY_END] = "End", [KEY_DOWN] = "Down",
177 [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert",
178 [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro",
179 [KEY_HELP] = "Help", [KEY_MENU] = "Menu",
180 [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction",
181 [BTN_0] = "Btn0", [BTN_1] = "Btn1",
182 [BTN_2] = "Btn2", [BTN_3] = "Btn3",
183 [BTN_4] = "Btn4", [BTN_5] = "Btn5",
184 [BTN_6] = "Btn6", [BTN_7] = "Btn7",
185 [BTN_8] = "Btn8", [BTN_9] = "Btn9",
186 [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn",
187 [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn",
188 [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn",
189 [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn",
190 [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn",
191 [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn",
192 [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn",
193 [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2",
194 [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4",
195 [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6",
196 [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA",
197 [BTN_B] = "BtnB", [BTN_C] = "BtnC",
198 [BTN_X] = "BtnX", [BTN_Y] = "BtnY",
199 [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL",
200 [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2",
201 [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
202 [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
203 [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
204 [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
205 [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
206 [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
207 [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
210 #define DNKEY(x) [SDLK_##x] = #x
211 static const char * const sdl_keynames[SDLK_LAST] = {
435 void omapsdl_input_bind(const char *kname, const char *sdlname)
439 if (kname == NULL || strncasecmp(kname, "ev_", 3) != 0)
442 for (i = 0; i < ARRAY_SIZE(osdl_evdev_keys); i++) {
443 if (osdl_evdev_keys[i] == NULL)
445 if (strcasecmp(osdl_evdev_keys[i], kname + 3) == 0)
449 if (i >= ARRAY_SIZE(osdl_evdev_keys))
453 if (sdlname == NULL || strncasecmp(sdlname, "SDLK_", 5) != 0)
456 for (i = 0; i < ARRAY_SIZE(sdl_keynames); i++) {
457 if (sdl_keynames[i] == NULL)
459 if (strcasecmp(sdl_keynames[i], sdlname + 5) == 0)
463 if (i >= ARRAY_SIZE(sdl_keynames))
466 osdl_evdev_map[kc] = i;
470 err("can't resolve evdev key '%s'", kname);
474 err("can't resolve SDL key '%s'", sdlname);
477 #define KEYBITS_BIT(keybits, x) (keybits[(x)/sizeof(keybits[0])/8] & \
478 (1 << ((x) & (sizeof(keybits[0])*8-1))))
480 void omapsdl_input_init(void)
482 long keybits[KEY_CNT / sizeof(long) / 8];
485 // the kernel might support and return less keys then we know about,
486 // so make sure the buffer is clear.
487 memset(keybits, 0, sizeof(keybits));
491 int support = 0, count = 0;
495 snprintf(name, sizeof(name), "/dev/input/event%d", i);
496 fd = open(name, O_RDONLY|O_NONBLOCK);
499 continue; /* maybe we can access next one */
503 /* check supported events */
504 ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support);
506 printf("in_evdev: ioctl failed on %s\n", name);
510 if (!(support & (1 << EV_KEY)))
513 ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
515 printf("in_evdev: ioctl failed on %s\n", name);
519 /* check for interesting keys */
520 for (u = 0; u < KEY_CNT; u++) {
521 if (KEYBITS_BIT(keybits, u)) {
522 if (u != KEY_POWER && u != KEY_SLEEP && u != BTN_TOUCH)
530 osdl_evdev_devs[osdl_evdev_dev_count++] = fd;
531 ioctl(fd, EVIOCGNAME(sizeof(name)), name);
532 printf("in_evdev: found \"%s\" with %d events (type %08x)\n",
533 name, count, support);
540 printf("found %d evdev devices.\n", osdl_evdev_dev_count);
543 int omapsdl_input_get_events(int timeout_ms,
544 int (*cb)(void *cb_arg, int sdl_kc, int is_pressed), void *cb_arg)
546 struct timeval tv, *timeout = NULL;
547 struct input_event ev;
551 if (timeout_ms >= 0) {
552 tv.tv_sec = timeout_ms / 1000;
553 tv.tv_usec = (timeout_ms % 1000) * 1000;
558 for (i = 0; i < osdl_evdev_dev_count; i++) {
559 if (osdl_evdev_devs[i] > fdmax)
560 fdmax = osdl_evdev_devs[i];
561 FD_SET(osdl_evdev_devs[i], &fdset);
568 ret = select(fdmax + 1, &fdset, NULL, NULL, timeout);
571 perror("in_evdev: select failed");
575 return -1; /* timeout */
577 for (i = 0; i < osdl_evdev_dev_count; i++) {
578 if (!FD_ISSET(osdl_evdev_devs[i], &fdset))
581 fd = osdl_evdev_devs[i];
583 ret = read(fd, &ev, sizeof(ev));
584 if (ret < (int)sizeof(ev)) {
585 if (errno != EAGAIN) {
586 perror("in_evdev: read failed");
592 if (ev.type != EV_KEY)
593 continue; /* not key event */
594 if ((unsigned int)ev.value > 1)
595 continue; /* not key up/down */
596 if ((unsigned int)ev.code >= ARRAY_SIZE(osdl_evdev_map))
597 continue; /* keycode from future */
598 sdl_kc = osdl_evdev_map[ev.code];
600 continue; /* not mapped */
601 ret = cb(cb_arg, sdl_kc, ev.value);
612 static unsigned char g_keystate[SDLK_LAST];
619 static int do_key_cb(void *cb_arg, int sdl_kc, int is_pressed)
621 struct key_event *ev = cb_arg;
623 ev->is_pressed = is_pressed;
628 static int do_event(SDL_Event *event, int timeout)
633 ret = omapsdl_input_get_events(timeout, do_key_cb, &ev);
637 g_keystate[ev.sdl_kc] = ev.is_pressed;
640 return 1; // FIXME: ..but the event is lost
642 memset(event, 0, sizeof(event->key));
643 event->type = ev.is_pressed ? SDL_KEYDOWN : SDL_KEYUP;
644 // event->key.which =
645 event->key.state = ev.is_pressed ? SDL_PRESSED : SDL_RELEASED;
646 event->key.keysym.sym = ev.sdl_kc;
647 // event->key.keysym.mod
653 SDL_WaitEvent(SDL_Event *event)
657 return do_event(event, -1);
661 SDL_PollEvent(SDL_Event *event)
665 return do_event(event, 0);
668 DECLSPEC Uint8 * SDLCALL
669 SDL_GetKeyState(int *numkeys)
671 trace("%p", numkeys);
674 *numkeys = ARRAY_SIZE(g_keystate);
678 DECLSPEC char * SDLCALL
679 SDL_GetKeyName(SDLKey key)
683 if ((unsigned int)key < ARRAY_SIZE(sdl_keynames))
684 return (char *)sdl_keynames[key];
690 SDL_EnableUNICODE(int enable)
701 SDL_EnableKeyRepeat(int delay, int interval)
703 trace("%d, %d", delay, interval);
710 DECLSPEC void SDLCALL
711 SDL_GetKeyRepeat(int *delay, int *interval)
713 trace("%p, %p", delay, interval);
721 DECLSPEC SDLMod SDLCALL
722 SDL_GetModState(void)
724 static const short syms[] = { SDLK_LSHIFT, SDLK_RSHIFT, SDLK_LCTRL, SDLK_RCTRL, SDLK_LALT,
725 SDLK_RALT, SDLK_LMETA, SDLK_RMETA, SDLK_NUMLOCK, SDLK_CAPSLOCK, SDLK_MODE };
726 static const short mods[] = { KMOD_LSHIFT, KMOD_RSHIFT, KMOD_LCTRL, KMOD_RCTRL, KMOD_LALT,
727 KMOD_RALT, KMOD_LMETA, KMOD_RMETA, KMOD_NUM, KMOD_CAPS, KMOD_MODE };
728 SDLMod ret = KMOD_NONE;
733 for (i = 0; i < ARRAY_SIZE(syms); i++)
734 if (g_keystate[syms[i]])
742 SDL_NumJoysticks(void)
748 DECLSPEC SDL_Joystick * SDLCALL
749 SDL_JoystickOpen(int device_index)
751 trace("%d", device_index);