2 * Portions copied from DirectFB:
3 * Copyright (C) 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
4 * Copyright (C) 2000-2004 Convergence (integrated media) GmbH
6 * Written by Denis Oliver Kropp <dok@directfb.org>,
7 * Andreas Hundt <andi@fischlustig.de>,
8 * Sven Neumann <neo@directfb.org>,
9 * Ville Syrj������l������ <syrjala@sci.fi> and
10 * Claudio Ciccani <klan@users.sf.net>.
12 * Copyright (C) 2005-2013 Team XBMC
15 * This Program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2, or (at your option)
20 * This Program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with XBMC; see the file COPYING. If not, see
27 * <http://www.gnu.org/licenses/>.
31 #if defined(HAS_LINUX_EVENTS)
33 #if defined(HAS_LIBAMCODEC)
34 #include "utils/AMLUtils.h"
37 #include <linux/version.h>
39 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
40 typedef unsigned long kernel_ulong_t;
41 #define BITS_PER_LONG (sizeof(long)*8)
44 #include <linux/input.h>
47 #define EV_CNT (EV_MAX+1)
48 #define KEY_CNT (KEY_MAX+1)
49 #define REL_CNT (REL_MAX+1)
50 #define ABS_CNT (ABS_MAX+1)
51 #define LED_CNT (LED_MAX+1)
54 /* compat defines for older kernel like 2.4.x */
59 #define ABS_TOOL_WIDTH 0x1c
60 #define BTN_TOOL_DOUBLETAP 0x14d
61 #define BTN_TOOL_TRIPLETAP 0x14e
65 #define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len)
69 #define EVIOCGRAB _IOW('E', 0x90, int)
73 #define XBMC_BUTTON_LEFT 1
74 #define XBMC_BUTTON_MIDDLE 2
75 #define XBMC_BUTTON_RIGHT 3
76 #define XBMC_BUTTON_WHEELUP 4
77 #define XBMC_BUTTON_WHEELDOWN 5
80 #include <linux/keyboard.h>
88 #include <sys/types.h>
90 #include <sys/ioctl.h>
94 #include "guilib/GraphicContext.h"
95 #include "input/XBMC_keysym.h"
96 #include "LinuxInputDevices.h"
97 #include "input/MouseStat.h"
98 #include "utils/log.h"
100 #ifndef BITS_PER_LONG
101 #define BITS_PER_LONG (sizeof(long) * 8)
103 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
104 #define OFF(x) ((x)%BITS_PER_LONG)
105 #define BIT(x) (1UL<<OFF(x))
106 #define LONG(x) ((x)/BITS_PER_LONG)
108 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
110 #define MAX_LINUX_INPUT_DEVICES 16
119 { KEY_ESC , XBMCK_ESCAPE },
130 { KEY_MINUS , XBMCK_MINUS },
131 { KEY_EQUAL , XBMCK_EQUALS },
132 { KEY_BACKSPACE , XBMCK_BACKSPACE },
133 { KEY_TAB , XBMCK_TAB },
144 { KEY_LEFTBRACE , XBMCK_LEFTBRACKET },
145 { KEY_RIGHTBRACE , XBMCK_RIGHTBRACKET},
146 { KEY_ENTER , XBMCK_RETURN },
147 { KEY_LEFTCTRL , XBMCK_LCTRL },
157 { KEY_SEMICOLON , XBMCK_SEMICOLON },
158 { KEY_APOSTROPHE , XBMCK_QUOTE },
159 { KEY_GRAVE , XBMCK_BACKQUOTE },
160 { KEY_LEFTSHIFT , XBMCK_LSHIFT },
161 { KEY_BACKSLASH , XBMCK_BACKSLASH },
169 { KEY_COMMA , XBMCK_COMMA },
170 { KEY_DOT , XBMCK_PERIOD },
171 { KEY_SLASH , XBMCK_SLASH },
172 { KEY_RIGHTSHIFT , XBMCK_RSHIFT },
173 { KEY_KPASTERISK , XBMCK_KP_MULTIPLY },
174 { KEY_LEFTALT , XBMCK_LALT },
175 { KEY_SPACE , XBMCK_SPACE },
176 { KEY_CAPSLOCK , XBMCK_CAPSLOCK },
177 { KEY_F1 , XBMCK_F1 },
178 { KEY_F2 , XBMCK_F2 },
179 { KEY_F3 , XBMCK_F3 },
180 { KEY_F4 , XBMCK_F4 },
181 { KEY_F5 , XBMCK_F5 },
182 { KEY_F6 , XBMCK_F6 },
183 { KEY_F7 , XBMCK_F7 },
184 { KEY_F8 , XBMCK_F8 },
185 { KEY_F9 , XBMCK_F9 },
186 { KEY_F10 , XBMCK_F10 },
187 { KEY_NUMLOCK , XBMCK_NUMLOCK },
188 { KEY_SCROLLLOCK , XBMCK_SCROLLOCK },
189 { KEY_KP7 , XBMCK_KP7 },
190 { KEY_KP8 , XBMCK_KP8 },
191 { KEY_KP9 , XBMCK_KP9 },
192 { KEY_KPMINUS , XBMCK_KP_MINUS },
193 { KEY_KP4 , XBMCK_KP4 },
194 { KEY_KP5 , XBMCK_KP5 },
195 { KEY_KP6 , XBMCK_KP6 },
196 { KEY_KPPLUS , XBMCK_KP_PLUS },
197 { KEY_KP1 , XBMCK_KP1 },
198 { KEY_KP2 , XBMCK_KP2 },
199 { KEY_KP3 , XBMCK_KP3 },
200 { KEY_KP0 , XBMCK_KP0 },
201 { KEY_KPDOT , XBMCK_KP_PERIOD },
202 { 84 , XBMCK_BACKSLASH },
205 { KEY_F11 , XBMCK_F11 },
206 { KEY_F12 , XBMCK_F12 },
209 { KEY_KPENTER , XBMCK_KP_ENTER },
210 { KEY_RIGHTCTRL , XBMCK_RCTRL },
211 { KEY_KPSLASH , XBMCK_KP_DIVIDE },
212 { KEY_SYSRQ , XBMCK_PRINT },
213 { KEY_RIGHTALT , XBMCK_MODE },
214 { KEY_HOME , XBMCK_HOME },
215 { KEY_UP , XBMCK_UP },
216 { KEY_PAGEUP , XBMCK_PAGEUP },
217 { KEY_LEFT , XBMCK_LEFT },
218 { KEY_RIGHT , XBMCK_RIGHT },
219 { KEY_END , XBMCK_END },
220 { KEY_DOWN , XBMCK_DOWN },
221 { KEY_PAGEDOWN , XBMCK_PAGEDOWN },
222 { KEY_INSERT , XBMCK_INSERT },
223 { KEY_DELETE , XBMCK_DELETE },
224 { KEY_MUTE , XBMCK_VOLUME_MUTE },
225 { KEY_VOLUMEDOWN , XBMCK_VOLUME_DOWN },
226 { KEY_VOLUMEUP , XBMCK_VOLUME_UP },
227 { KEY_POWER , XBMCK_POWER },
228 { KEY_KPEQUAL , XBMCK_KP_EQUALS },
229 { KEY_PAUSE , XBMCK_PAUSE },
230 { KEY_LEFTMETA , XBMCK_LMETA },
231 { KEY_RIGHTMETA , XBMCK_RMETA },
232 { KEY_COMPOSE , XBMCK_LSUPER },
233 { KEY_STOP , XBMCK_MEDIA_STOP },
234 { KEY_HELP , XBMCK_HELP },
235 { KEY_CLOSECD , XBMCK_EJECT },
236 { KEY_EJECTCD , XBMCK_EJECT },
237 { KEY_EJECTCLOSECD , XBMCK_EJECT },
238 { KEY_NEXTSONG , XBMCK_MEDIA_NEXT_TRACK},
239 { KEY_PLAYPAUSE , XBMCK_MEDIA_PLAY_PAUSE},
240 { KEY_PREVIOUSSONG , XBMCK_MEDIA_PREV_TRACK},
241 { KEY_STOPCD , XBMCK_MEDIA_STOP },
242 { KEY_RECORD , XBMCK_RECORD },
243 { KEY_REWIND , XBMCK_REWIND },
244 { KEY_PHONE , XBMCK_PHONE },
245 { KEY_REFRESH , XBMCK_SHUFFLE },
246 { KEY_SCROLLUP , XBMCK_PAGEUP },
247 { KEY_SCROLLDOWN , XBMCK_PAGEDOWN },
248 { KEY_PLAY , XBMCK_PLAY },
249 { KEY_FASTFORWARD , XBMCK_FASTFORWARD },
250 { KEY_PRINT , XBMCK_PRINT },
251 { KEY_QUESTION , XBMCK_HELP },
252 // The Little Black Box Remote Additions
253 { 384 , XBMCK_LEFT }, // Red
254 { 378 , XBMCK_RIGHT }, // Green
255 { 381 , XBMCK_UP }, // Yellow
256 { 366 , XBMCK_DOWN }, // Blue
257 #ifdef TARGET_DVBBOX // oskwon
258 { 352 , XBMCK_RETURN }, // Ok
259 { 412 , XBMCK_ESCAPE }, // <
260 #endif /*TARGET_DVBBOX*/
268 LI_DEVICE_JOYSTICK = 2,
269 LI_DEVICE_KEYBOARD = 4,
271 } LinuxInputDeviceType;
278 } LinuxInputCapsType;
280 static char remoteStatus = 0xFF; // paired, battery OK
282 CLinuxInputDevice::CLinuxInputDevice(const std::string fileName, int index)
287 m_fileName = fileName;
288 m_ledState[0] = false;
289 m_ledState[1] = false;
290 m_ledState[2] = false;
293 m_deviceIndex = index;
294 m_keyMods = XBMCKMOD_NONE;
295 m_lastKeyMods = XBMCKMOD_NONE;
296 strcpy(m_deviceName, "");
298 m_devicePreferredId = 0;
300 m_deviceMinKeyCode = 0;
301 m_deviceMaxKeyCode = 0;
303 m_bUnplugged = false;
308 CLinuxInputDevice::~CLinuxInputDevice()
314 * Translates a Linux input keycode into an XBMC keycode.
316 XBMCKey CLinuxInputDevice::TranslateKey(unsigned short code)
318 for (size_t index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
320 if (code == keyMap[index].Key)
321 return keyMap[index].xbmcKey;
324 return XBMCK_UNKNOWN;
327 int CLinuxInputDevice::KeyboardGetSymbol(unsigned short value)
329 unsigned char type = KTYP(value);
330 unsigned char index = KVAL(value);
336 return XBMCK_F1 + index;
345 return XBMCK_BACKSPACE;
347 return XBMCK_EURO; /* euro currency sign */
358 return DIKS_DEAD_GRAVE;
361 return DIKS_DEAD_ACUTE;
364 return DIKS_DEAD_CIRCUMFLEX;
367 return DIKS_DEAD_TILDE;
370 return DIKS_DEAD_DIAERESIS;
373 return DIKS_DEAD_CEDILLA;
381 if (index <= 9 && level != DIKSI_BASE)
382 return (DFBInputDeviceKeySymbol) (DIKS_0 + index);
387 return XBMCK_UNKNOWN;
390 unsigned short CLinuxInputDevice::KeyboardReadValue(unsigned char table, unsigned char index)
392 struct kbentry entry;
394 entry.kb_table = table;
395 entry.kb_index = index;
398 if (ioctl(m_vt_fd, KDGKBENT, &entry))
400 CLog::Log(LOGWARNING, "CLinuxInputDevice::KeyboardReadValue: KDGKBENT (table: %d, index: %d) "
401 "failed!\n", table, index);
405 return entry.kb_value;
408 XBMCMod CLinuxInputDevice::UpdateModifiers(XBMC_Event& devt)
410 XBMCMod modifier = XBMCKMOD_NONE;
411 switch (devt.key.keysym.sym)
413 case XBMCK_LSHIFT: modifier = XBMCKMOD_LSHIFT; break;
414 case XBMCK_RSHIFT: modifier = XBMCKMOD_RSHIFT; break;
415 case XBMCK_LCTRL: modifier = XBMCKMOD_LCTRL; break;
416 case XBMCK_RCTRL: modifier = XBMCKMOD_RCTRL; break;
417 case XBMCK_LALT: modifier = XBMCKMOD_LALT; break;
418 case XBMCK_RALT: modifier = XBMCKMOD_RALT; break;
419 case XBMCK_LMETA: modifier = XBMCKMOD_LMETA; break;
420 case XBMCK_RMETA: modifier = XBMCKMOD_RMETA; break;
424 if (devt.key.type == XBMC_KEYDOWN)
426 m_keyMods |= modifier;
430 m_keyMods &= ~modifier;
433 if (devt.key.type == XBMC_KEYDOWN)
435 modifier = XBMCKMOD_NONE;
436 switch (devt.key.keysym.sym)
438 case XBMCK_NUMLOCK: modifier = XBMCKMOD_NUM; break;
439 case XBMCK_CAPSLOCK: modifier = XBMCKMOD_CAPS; break;
443 if (m_keyMods & modifier)
445 m_keyMods &= ~modifier;
449 m_keyMods |= modifier;
453 return (XBMCMod) m_keyMods;
457 * Translates key and button events.
459 bool CLinuxInputDevice::KeyEvent(const struct input_event& levt, XBMC_Event& devt)
461 int code = levt.code;
463 /* map touchscreen and smartpad events to button mouse */
464 if (code == BTN_TOUCH || code == BTN_TOOL_FINGER)
467 if ((code >= BTN_MOUSE && code < BTN_JOYSTICK) || code == BTN_TOUCH)
469 /* ignore repeat events for buttons */
473 devt.type = levt.value ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP;
474 devt.button.state = levt.value ? XBMC_PRESSED : XBMC_RELEASED;
475 devt.button.type = devt.type;
476 devt.button.x = m_mouseX;
477 devt.button.y = m_mouseY;
482 devt.button.button = XBMC_BUTTON_RIGHT;
486 devt.button.button = XBMC_BUTTON_LEFT;
490 devt.button.button = XBMC_BUTTON_RIGHT;
494 devt.button.button = XBMC_BUTTON_WHEELDOWN;
498 devt.button.button = XBMC_BUTTON_WHEELUP;
502 devt.button.button = XBMC_BUTTON_LEFT;
505 case BTN_TOOL_DOUBLETAP:
506 devt.button.button = XBMC_BUTTON_RIGHT;
510 CLog::Log(LOGWARNING, "CLinuxInputDevice::KeyEvent: Unknown mouse button code: %d\n", levt.code);
516 XBMCKey key = TranslateKey(code);
518 if (key == XBMCK_UNKNOWN)
520 CLog::Log(LOGDEBUG, "CLinuxInputDevice::KeyEvent: TranslateKey returned XBMCK_UNKNOWN from code(%d)", code);
524 devt.type = levt.value ? XBMC_KEYDOWN : XBMC_KEYUP;
525 devt.key.type = devt.type;
526 // warning, key.keysym.scancode is unsigned char so 0 - 255 only
527 devt.key.keysym.scancode = code;
528 devt.key.keysym.sym = key;
529 devt.key.keysym.mod = UpdateModifiers(devt);
530 devt.key.keysym.unicode = 0;
534 if (GetKeymapEntry(entry))
537 if (devt.key.keysym.mod & (XBMCKMOD_SHIFT | XBMCKMOD_CAPS)) keyMapValue = entry.shift;
538 else if (devt.key.keysym.mod & XBMCKMOD_ALT) keyMapValue = entry.alt;
539 else if (devt.key.keysym.mod & XBMCKMOD_META) keyMapValue = entry.altShift;
540 else keyMapValue = entry.base;
542 if (keyMapValue != XBMCK_UNKNOWN)
544 devt.key.keysym.sym = (XBMCKey) keyMapValue;
545 if (keyMapValue > 0 && keyMapValue < 127)
547 devt.key.keysym.unicode = devt.key.keysym.sym;
557 * Translates relative axis events.
559 bool CLinuxInputDevice::RelEvent(const struct input_event& levt, XBMC_Event& devt)
564 m_mouseX += levt.value;
565 devt.motion.xrel = levt.value;
566 devt.motion.yrel = 0;
570 m_mouseY += levt.value;
571 devt.motion.xrel = 0;
572 devt.motion.yrel = levt.value;
578 CLog::Log(LOGWARNING, "CLinuxInputDevice::RelEvent: Unknown rel event code: %d\n", levt.code);
582 // limit the mouse to the screen width
583 m_mouseX = std::min(g_graphicsContext.GetWidth(), m_mouseX);
584 m_mouseX = std::max(0, m_mouseX);
586 // limit the mouse to the screen height
587 m_mouseY = std::min(g_graphicsContext.GetHeight(), m_mouseY);
588 m_mouseY = std::max(0, m_mouseY);
591 devt.type = XBMC_MOUSEMOTION;
592 devt.motion.type = XBMC_MOUSEMOTION;
593 devt.motion.x = m_mouseX;
594 devt.motion.y = m_mouseY;
595 devt.motion.state = 0;
596 devt.motion.which = m_deviceIndex;
603 * Translates absolute axis events.
605 bool CLinuxInputDevice::AbsEvent(const struct input_event& levt, XBMC_Event& devt)
610 m_mouseX = levt.value;
614 m_mouseY = levt.value;
618 remoteStatus = levt.value & 0xFF;
626 devt.type = XBMC_MOUSEMOTION;
627 devt.motion.type = XBMC_MOUSEMOTION;
628 devt.motion.x = m_mouseX;
629 devt.motion.y = m_mouseY;
630 devt.motion.state = 0;
631 devt.motion.xrel = 0;
632 devt.motion.yrel = 0;
633 devt.motion.which = m_deviceIndex;
639 * Translates a Linux input event into a DirectFB input event.
641 bool CLinuxInputDevice::TranslateEvent(const struct input_event& levt,
647 return KeyEvent(levt, devt);
650 if (m_bSkipNonKeyEvents)
652 CLog::Log(LOGINFO, "read a relative event which will be ignored (device name %s) (file name %s)", m_deviceName, m_fileName.c_str());
656 return RelEvent(levt, devt);
659 if (m_bSkipNonKeyEvents)
661 CLog::Log(LOGINFO, "read an absolute event which will be ignored (device name %s) (file name %s)", m_deviceName, m_fileName.c_str());
665 return AbsEvent(levt, devt);
674 void CLinuxInputDevice::SetLed(int led, int state)
676 struct input_event levt;
680 levt.value = !!state;
682 write(m_fd, &levt, sizeof(levt));
686 * Input thread reading from device.
687 * Generates events on incoming data.
689 XBMC_Event CLinuxInputDevice::ReadEvent()
692 struct input_event levt;
698 bzero(&levt, sizeof(levt));
700 bzero(&devt, sizeof(devt));
701 devt.type = XBMC_NOEVENT;
703 if(m_devicePreferredId == LI_DEVICE_NONE)
706 readlen = read(m_fd, &levt, sizeof(levt));
712 CLog::Log(LOGINFO,"input device was unplugged %s",m_deviceName);
719 #ifdef TARGET_DVBBOX // oskwon
720 if (access("/tmp/playing.lock", F_OK) == 0) {
723 #endif /*TARGET_DVBBOX*/
725 //printf("read event readlen = %d device name %s m_fileName %s\n", readlen, m_deviceName, m_fileName.c_str());
727 // sanity check if we realy read the event
728 if(readlen != sizeof(levt))
730 printf("CLinuxInputDevice: read error : %s\n", strerror(errno));
734 if (!TranslateEvent(levt, devt))
737 /* Flush previous event with DIEF_FOLLOW? */
738 if (devt.type != XBMC_NOEVENT)
740 //printf("new event! type = %d\n", devt.type);
741 //printf("key: %d %d %d %c\n", devt.key.keysym.scancode, devt.key.keysym.sym, devt.key.keysym.mod, devt.key.keysym.unicode);
743 if (m_hasLeds && (m_keyMods != m_lastKeyMods))
745 SetLed(LED_NUML, m_keyMods & XBMCKMOD_NUM);
746 SetLed(LED_CAPSL, m_keyMods & XBMCKMOD_CAPS);
747 m_lastKeyMods = m_keyMods;
757 void CLinuxInputDevice::SetupKeyboardAutoRepeat(int fd)
761 #if defined(HAS_LIBAMCODEC)
764 // ignore the native aml driver named 'key_input',
765 // it is the dedicated power key handler (am_key_input)
766 if (strncmp(m_deviceName, "key_input", strlen("key_input")) == 0)
768 // ignore the native aml driver named 'aml_keypad',
769 // it is the dedicated IR remote handler (amremote)
770 else if (strncmp(m_deviceName, "aml_keypad", strlen("aml_keypad")) == 0)
773 // turn off any keyboard autorepeat, there is a kernel bug
774 // where if the cpu is max'ed then key up is missed and
775 // we get a flood of EV_REP that never stop until next
776 // key down/up. Very nasty when seeking during video playback.
783 int kbdrep[2] = { 400, 80 };
784 ioctl(fd, EVIOCSREP, kbdrep);
788 struct input_event event;
789 memset(&event, 0, sizeof(event));
791 gettimeofday(&event.time, NULL);
793 event.code = REP_DELAY;
795 write(fd, &event, sizeof(event));
797 gettimeofday(&event.time, NULL);
799 event.code = REP_PERIOD;
801 write(fd, &event, sizeof(event));
803 CLog::Log(LOGINFO, "CLinuxInputDevice: auto key repeat disabled on device '%s'\n", m_deviceName);
808 * Fill device information.
809 * Queries the input device and tries to classify it.
811 void CLinuxInputDevice::GetInfo(int fd)
813 unsigned int num_keys = 0;
814 unsigned int num_ext_keys = 0;
815 unsigned int num_buttons = 0;
816 unsigned int num_rels = 0;
817 unsigned int num_abs = 0;
819 unsigned long evbit[NBITS(EV_CNT)];
820 unsigned long keybit[NBITS(KEY_CNT)];
822 /* get device name */
823 bzero(m_deviceName, sizeof(m_deviceName));
824 ioctl(fd, EVIOCGNAME(sizeof(m_deviceName)-1), m_deviceName);
826 if (strncmp(m_deviceName, "D-Link Boxee D-Link Boxee Receiver", strlen("D-Link Boxee D-Link Boxee Receiver")) == 0)
828 m_bSkipNonKeyEvents = true;
832 m_bSkipNonKeyEvents = false;
834 CLog::Log(LOGINFO, "opened device '%s' (file name %s), m_bSkipNonKeyEvents %d\n", m_deviceName, m_fileName.c_str(), m_bSkipNonKeyEvents);
836 /* get event type bits */
837 ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit);
839 if (test_bit( EV_KEY, evbit ))
843 /* get keyboard bits */
844 ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit);
846 /** count typical keyboard keys only */
847 for (i = KEY_Q; i <= KEY_M; i++)
848 if (test_bit( i, keybit ))
851 for (i = KEY_OK; i < KEY_CNT; i++)
852 if (test_bit( i, keybit ))
855 for (i = BTN_MOUSE; i < BTN_JOYSTICK; i++)
856 if (test_bit( i, keybit ))
861 unsigned long relbit[NBITS(REL_CNT)];
862 unsigned long absbit[NBITS(ABS_CNT)];
864 if (test_bit( EV_REL, evbit ))
868 /* get bits for relative axes */
869 ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit);
871 for (i = 0; i < REL_CNT; i++)
872 if (test_bit( i, relbit ))
876 if (test_bit( EV_ABS, evbit ))
880 /* get bits for absolute axes */
881 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit);
883 for (i = 0; i < ABS_PRESSURE; i++)
884 if (test_bit( i, absbit ))
888 /* Mouse, Touchscreen or Smartpad ? */
889 if ((test_bit( EV_KEY, evbit ) && (test_bit( BTN_TOUCH, keybit )
890 || test_bit( BTN_TOOL_FINGER, keybit ))) || ((num_rels >= 2
891 && num_buttons) || (num_abs == 2 && (num_buttons == 1))))
892 m_deviceType |= LI_DEVICE_MOUSE;
893 else if (num_abs && num_buttons) /* Or a Joystick? */
894 m_deviceType |= LI_DEVICE_JOYSTICK;
897 /* A Keyboard, do we have at least some letters? */
900 m_deviceType |= LI_DEVICE_KEYBOARD;
901 m_deviceCaps |= LI_CAPS_KEYS;
903 m_deviceMinKeyCode = 0;
904 m_deviceMaxKeyCode = 127;
907 /* A Remote Control? */
910 m_deviceType |= LI_DEVICE_REMOTE;
911 m_deviceCaps |= LI_CAPS_KEYS;
917 m_deviceCaps |= LI_CAPS_BUTTONS;
918 m_deviceMaxKeyCode = num_buttons - 1;
922 if (num_rels || num_abs)
924 m_deviceCaps |= LI_CAPS_AXES;
925 m_deviceMaxAxis = std::max(num_rels, num_abs) - 1;
928 /* Decide which primary input device to be. */
929 if (m_deviceType & LI_DEVICE_KEYBOARD)
930 m_devicePreferredId = LI_DEVICE_KEYBOARD;
931 else if (m_deviceType & LI_DEVICE_REMOTE)
932 m_devicePreferredId = LI_DEVICE_REMOTE;
933 else if (m_deviceType & LI_DEVICE_JOYSTICK)
934 m_devicePreferredId = LI_DEVICE_JOYSTICK;
935 else if (m_deviceType & LI_DEVICE_MOUSE)
936 m_devicePreferredId = LI_DEVICE_MOUSE;
938 m_devicePreferredId = LI_DEVICE_NONE;
940 //printf("type: %d\n", m_deviceType);
941 //printf("caps: %d\n", m_deviceCaps);
942 //printf("pref: %d\n", m_devicePreferredId);
945 const std::string& CLinuxInputDevice::GetFileName()
950 bool CLinuxInputDevice::IsUnplugged()
955 bool CLinuxInputDevices::CheckDevice(const char *device)
959 // Does the device exists?
961 if (stat(device, &buffer) != 0)
964 /* Check if we are able to open the device */
965 fd = open(device, O_RDWR);
969 #ifndef TARGET_DVBBOX // oskwon
970 if (ioctl(fd, EVIOCGRAB, 1) && errno != EINVAL)
976 ioctl(fd, EVIOCGRAB, 0);
977 #endif /*TARGET_DVBBOX*/
984 /* exported symbols */
987 * Return the number of available devices.
988 * Called once during initialization of DirectFB.
990 void CLinuxInputDevices::InitAvailable()
992 CSingleLock lock(m_devicesListLock);
994 /* Close any devices that may have been initialized previously */
995 for (size_t i = 0; i < m_devices.size(); i++)
1003 /* No devices specified. Try to guess some. */
1004 for (int i = 0; i < MAX_LINUX_INPUT_DEVICES; i++)
1008 snprintf(buf, 32, "/dev/input/event%d", i);
1009 if (CheckDevice(buf))
1011 CLog::Log(LOGINFO, "Found input device %s", buf);
1012 m_devices.push_back(new CLinuxInputDevice(buf, deviceId));
1019 * Check for hot plugged devices.
1021 void CLinuxInputDevices::CheckHotplugged()
1023 CSingleLock lock(m_devicesListLock);
1025 int deviceId = m_devices.size();
1027 /* No devices specified. Try to guess some. */
1028 for (int i = 0; i < MAX_LINUX_INPUT_DEVICES; i++)
1031 bool ispresent = false;
1033 snprintf(buf, 32, "/dev/input/event%d", i);
1035 for (size_t j = 0; j < m_devices.size(); j++)
1037 if (m_devices[j]->GetFileName().compare(buf) == 0)
1044 if (!ispresent && CheckDevice(buf))
1046 CLog::Log(LOGINFO, "Found input device %s", buf);
1047 m_devices.push_back(new CLinuxInputDevice(buf, deviceId));
1054 * Open the device, fill out information about it,
1055 * allocate and fill private data, start input thread.
1057 bool CLinuxInputDevice::Open()
1060 unsigned long ledbit[NBITS(LED_CNT)];
1063 fd = open(m_fileName.c_str(), O_RDWR | O_NONBLOCK);
1066 CLog::Log(LOGERROR, "CLinuxInputDevice: could not open device: %s\n", m_fileName.c_str());
1070 #ifndef TARGET_DVBBOX // oskwon
1072 ret = ioctl(fd, EVIOCGRAB, 1);
1073 if (ret && errno != EINVAL)
1075 CLog::Log(LOGERROR, "CLinuxInputDevice: could not grab device: %s\n", m_fileName.c_str());
1079 #endif /*TARGET_DVBBOX*/
1081 // Set the socket to non-blocking
1083 if ((opts = fcntl(fd, F_GETFL)) < 0)
1085 CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_GETFL) failed: %s", __FUNCTION__ , strerror(errno));
1090 opts = (opts | O_NONBLOCK);
1091 if (fcntl(fd, F_SETFL, opts) < 0)
1093 CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_SETFL) failed: %s", __FUNCTION__, strerror(errno));
1098 /* fill device info structure */
1101 if (m_deviceType & LI_DEVICE_KEYBOARD)
1102 SetupKeyboardAutoRepeat(fd);
1107 if (m_deviceMinKeyCode >= 0 && m_deviceMaxKeyCode >= m_deviceMinKeyCode)
1110 m_vt_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
1113 m_vt_fd = open("/dev/tty1", O_RDWR | O_NOCTTY);
1116 CLog::Log(LOGWARNING, "no keymap support (requires /dev/tty0 - CONFIG_VT)");
1119 /* check if the device has LEDs */
1120 ret = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit);
1122 CLog::Log(LOGWARNING, "DirectFB/linux_input: could not get LED bits" );
1124 m_hasLeds = test_bit( LED_SCROLLL, ledbit ) || test_bit( LED_NUML, ledbit )
1125 || test_bit( LED_CAPSL, ledbit );
1130 ret = ioctl(fd, EVIOCGLED(sizeof(m_ledState)), m_ledState);
1133 CLog::Log(LOGERROR, "DirectFB/linux_input: could not get LED state");
1134 goto driver_open_device_error;
1138 SetLed(LED_SCROLLL, 0);
1139 SetLed(LED_NUML, 0);
1140 SetLed(LED_CAPSL, 0);
1145 driver_open_device_error:
1146 #ifndef TARGET_DVBBOX // oskwon
1147 ioctl(fd, EVIOCGRAB, 0);
1148 #endif /*TARGET_DVBBOX*/
1161 * Fetch one entry from the kernel keymap.
1163 bool CLinuxInputDevice::GetKeymapEntry(KeymapEntry& entry)
1165 int code = entry.code;
1166 unsigned short value;
1167 //DFBInputDeviceKeyIdentifier identifier;
1172 // to support '+' and '/' with Boxee's remote control we do something ugly like this for now
1173 if (KVAL(code) == 98)
1175 code = K(KTYP(code),53);
1178 /* fetch the base level */
1179 value = KeyboardGetSymbol(KeyboardReadValue(K_NORMTAB, code));
1180 //printf("base=%d typ=%d code %d\n", KVAL(value), KTYP(value), code);
1182 /* write base level symbol to entry */
1183 entry.base = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_BASE);
1185 /* fetch the shifted base level */
1186 value = KeyboardGetSymbol(KeyboardReadValue(K_SHIFTTAB, entry.code));
1187 //printf("shift=%d\n", value);
1189 /* write shifted base level symbol to entry */
1190 entry.shift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_SHIFT);
1192 // to support '+' and '/' with Boxee's remote control we could do ugly something like this for now
1193 if (KVAL(code) == 78)
1195 //code = K(KTYP(code),13);
1196 //entry.code = K(KTYP(code),13);
1197 entry.base = K(KTYP(code),43);
1200 /* fetch the alternative level */
1201 value = KeyboardGetSymbol(KeyboardReadValue(K_ALTTAB, entry.code));
1202 //printf("alt=%d\n", value);
1204 /* write alternative level symbol to entry */
1205 entry.alt = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT);
1207 /* fetch the shifted alternative level */
1208 value = KeyboardGetSymbol(KeyboardReadValue(K_ALTSHIFTTAB, entry.code));
1209 //printf("altshift=%d\n", value);
1211 /* write shifted alternative level symbol to entry */
1212 entry.altShift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT_SHIFT);
1218 * End thread, close device and free private data.
1220 void CLinuxInputDevice::Close()
1222 #ifndef TARGET_DVBBOX // oskwon
1223 /* release device */
1224 ioctl(m_fd, EVIOCGRAB, 0);
1225 #endif /*TARGET_DVBBOX*/
1233 XBMC_Event CLinuxInputDevices::ReadEvent()
1235 if (m_bReInitialize)
1238 m_bReInitialize = false;
1245 if ((now - m_lastHotplugCheck) >= 10)
1248 m_lastHotplugCheck = now;
1252 CSingleLock lock(m_devicesListLock);
1255 event.type = XBMC_NOEVENT;
1257 for (size_t i = 0; i < m_devices.size(); i++)
1259 event = m_devices[i]->ReadEvent();
1260 if (event.type != XBMC_NOEVENT)
1265 if (m_devices[i]->IsUnplugged())
1267 m_bReInitialize = true;
1276 - 0x7F -> if not paired, battery OK
1277 - 0xFF -> if paired, battery OK
1278 - 0x00 -> if not paired, battery low
1279 - 0x80 -> if paired, battery low
1281 bool CLinuxInputDevices::IsRemoteLowBattery()
1283 bool bLowBattery = !(remoteStatus & 0xF);
1287 bool CLinuxInputDevices::IsRemoteNotPaired()
1289 bool bRemoteNotPaired = !(remoteStatus & 0x70) || !(remoteStatus & 0x80);
1290 return bRemoteNotPaired;
1296 CLinuxInputDevices devices;
1297 devices.InitAvailable();
1300 XBMC_Event event = devices.ReadEvent();
1301 if (event.type != XBMC_NOEVENT)
1303 printf("%d\n", event.type);