Merge pull request #3014 from bfg1981/master
[vuplus_xbmc] / xbmc / input / linux / LinuxInputDevices.cpp
1 /*
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
5  *      All rights reserved.
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>.
11  *
12  *      Copyright (C) 2005-2013 Team XBMC
13  *      http://xbmc.org
14  *
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)
18  *  any later version.
19  *
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.
24  *
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/>.
28  *
29  */
30 #include "system.h"
31 #if defined(HAS_LINUX_EVENTS)
32
33 #include <linux/version.h>
34
35 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
36 typedef unsigned long kernel_ulong_t;
37 #define BITS_PER_LONG    (sizeof(long)*8)
38 #endif
39
40 #include <linux/input.h>
41
42 #ifndef EV_CNT
43 #define EV_CNT (EV_MAX+1)
44 #define KEY_CNT (KEY_MAX+1)
45 #define REL_CNT (REL_MAX+1)
46 #define ABS_CNT (ABS_MAX+1)
47 #define LED_CNT (LED_MAX+1)
48 #endif
49
50 /* compat defines for older kernel like 2.4.x */
51 #ifndef EV_SYN
52 #define EV_SYN                  0x00
53 #define SYN_REPORT              0
54 #define SYN_CONFIG              1
55 #define ABS_TOOL_WIDTH          0x1c
56 #define BTN_TOOL_DOUBLETAP      0x14d
57 #define BTN_TOOL_TRIPLETAP      0x14e
58 #endif
59
60 #ifndef EVIOCGLED
61 #define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len)
62 #endif
63
64 #ifndef EVIOCGRAB
65 #define EVIOCGRAB _IOW('E', 0x90, int)
66 #endif
67
68 #ifdef STANDALONE
69 #define XBMC_BUTTON_LEFT    1
70 #define XBMC_BUTTON_MIDDLE  2
71 #define XBMC_BUTTON_RIGHT 3
72 #define XBMC_BUTTON_WHEELUP 4
73 #define XBMC_BUTTON_WHEELDOWN 5
74 #endif
75
76 #include <linux/keyboard.h>
77 #include <linux/kd.h>
78
79 #include <string.h>
80 #include <unistd.h>
81 #include <errno.h>
82 #include <fcntl.h>
83
84 #include <sys/types.h>
85 #include <sys/stat.h>
86 #include <sys/ioctl.h>
87 #include <stdlib.h>
88 #include <stdio.h>
89
90 #include "guilib/GraphicContext.h"
91 #include "input/XBMC_keysym.h"
92 #include "LinuxInputDevices.h"
93 #include "input/MouseStat.h"
94 #include "utils/log.h"
95
96 #ifndef BITS_PER_LONG
97 #define BITS_PER_LONG        (sizeof(long) * 8)
98 #endif
99 #define NBITS(x)             ((((x)-1)/BITS_PER_LONG)+1)
100 #define OFF(x)               ((x)%BITS_PER_LONG)
101 #define BIT(x)               (1UL<<OFF(x))
102 #define LONG(x)              ((x)/BITS_PER_LONG)
103 #undef test_bit
104 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
105
106 #define MAX_LINUX_INPUT_DEVICES 16
107
108 typedef struct {
109   unsigned short Key;
110   XBMCKey xbmcKey;
111 } KeyMap;
112
113 static const
114 KeyMap keyMap[] = {
115   { KEY_ESC           , XBMCK_ESCAPE      },
116   { KEY_1             , XBMCK_1           },
117   { KEY_2             , XBMCK_2           },
118   { KEY_3             , XBMCK_3           },
119   { KEY_4             , XBMCK_4           },
120   { KEY_5             , XBMCK_5           },
121   { KEY_6             , XBMCK_6           },
122   { KEY_7             , XBMCK_7           },
123   { KEY_8             , XBMCK_8           },
124   { KEY_9             , XBMCK_9           },
125   { KEY_0             , XBMCK_0           },
126   { KEY_MINUS         , XBMCK_MINUS       },
127   { KEY_EQUAL         , XBMCK_EQUALS      },
128   { KEY_BACKSPACE     , XBMCK_BACKSPACE   },
129   { KEY_TAB           , XBMCK_TAB         },
130   { KEY_Q             , XBMCK_q           },
131   { KEY_W             , XBMCK_w           },
132   { KEY_E             , XBMCK_e           },
133   { KEY_R             , XBMCK_r           },
134   { KEY_T             , XBMCK_t           },
135   { KEY_Y             , XBMCK_y           },
136   { KEY_U             , XBMCK_u           },
137   { KEY_I             , XBMCK_i           },
138   { KEY_O             , XBMCK_o           },
139   { KEY_P             , XBMCK_p           },
140   { KEY_LEFTBRACE     , XBMCK_LEFTBRACKET },
141   { KEY_RIGHTBRACE    , XBMCK_RIGHTBRACKET},
142   { KEY_ENTER         , XBMCK_RETURN      },
143   { KEY_LEFTCTRL      , XBMCK_LCTRL       },
144   { KEY_A             , XBMCK_a           },
145   { KEY_S             , XBMCK_s           },
146   { KEY_D             , XBMCK_d           },
147   { KEY_F             , XBMCK_f           },
148   { KEY_G             , XBMCK_g           },
149   { KEY_H             , XBMCK_h           },
150   { KEY_J             , XBMCK_j           },
151   { KEY_K             , XBMCK_k           },
152   { KEY_L             , XBMCK_l           },
153   { KEY_SEMICOLON     , XBMCK_SEMICOLON   },
154   { KEY_APOSTROPHE    , XBMCK_QUOTE       },
155   { KEY_GRAVE         , XBMCK_BACKQUOTE   },
156   { KEY_LEFTSHIFT     , XBMCK_LSHIFT      },
157   { KEY_BACKSLASH     , XBMCK_BACKSLASH   },
158   { KEY_Z             , XBMCK_z           },
159   { KEY_X             , XBMCK_x           },
160   { KEY_C             , XBMCK_c           },
161   { KEY_V             , XBMCK_v           },
162   { KEY_B             , XBMCK_b           },
163   { KEY_N             , XBMCK_n           },
164   { KEY_M             , XBMCK_m           },
165   { KEY_COMMA         , XBMCK_COMMA       },
166   { KEY_DOT           , XBMCK_PERIOD      },
167   { KEY_SLASH         , XBMCK_SLASH       },
168   { KEY_RIGHTSHIFT    , XBMCK_RSHIFT      },
169   { KEY_KPASTERISK    , XBMCK_KP_MULTIPLY },
170   { KEY_LEFTALT       , XBMCK_LALT        },
171   { KEY_SPACE         , XBMCK_SPACE       },
172   { KEY_CAPSLOCK      , XBMCK_CAPSLOCK    },
173   { KEY_F1            , XBMCK_F1          },
174   { KEY_F2            , XBMCK_F2          },
175   { KEY_F3            , XBMCK_F3          },
176   { KEY_F4            , XBMCK_F4          },
177   { KEY_F5            , XBMCK_F5          },
178   { KEY_F6            , XBMCK_F6          },
179   { KEY_F7            , XBMCK_F7          },
180   { KEY_F8            , XBMCK_F8          },
181   { KEY_F9            , XBMCK_F9          },
182   { KEY_F10           , XBMCK_F10         },
183   { KEY_NUMLOCK       , XBMCK_NUMLOCK     },
184   { KEY_SCROLLLOCK    , XBMCK_SCROLLOCK   },
185   { KEY_KP7           , XBMCK_KP7         },
186   { KEY_KP8           , XBMCK_KP8         },
187   { KEY_KP9           , XBMCK_KP9         },
188   { KEY_KPMINUS       , XBMCK_KP_MINUS    },
189   { KEY_KP4           , XBMCK_KP4         },
190   { KEY_KP5           , XBMCK_KP5         },
191   { KEY_KP6           , XBMCK_KP6         },
192   { KEY_KPPLUS        , XBMCK_KP_PLUS     },
193   { KEY_KP1           , XBMCK_KP1         },
194   { KEY_KP2           , XBMCK_KP2         },
195   { KEY_KP3           , XBMCK_KP3         },
196   { KEY_KP0           , XBMCK_KP0         },
197   { KEY_KPDOT         , XBMCK_KP_PERIOD   },
198   { 84                , XBMCK_BACKSLASH   },
199   { 85                , XBMCK_F13         },
200   { 86                , XBMCK_LESS        },
201   { KEY_F11           , XBMCK_F11         },
202   { KEY_F12           , XBMCK_F12         },
203   { 89                , XBMCK_F14         },
204   { 90                , XBMCK_F15         },
205   { KEY_KPENTER       , XBMCK_KP_ENTER    },
206   { KEY_RIGHTCTRL     , XBMCK_RCTRL       },
207   { KEY_KPSLASH       , XBMCK_KP_DIVIDE   },
208   { KEY_SYSRQ         , XBMCK_PRINT       },
209   { KEY_RIGHTALT      , XBMCK_MODE        },
210   { KEY_HOME          , XBMCK_HOME        },
211   { KEY_UP            , XBMCK_UP          },
212   { KEY_PAGEUP        , XBMCK_PAGEUP      },
213   { KEY_LEFT          , XBMCK_LEFT        },
214   { KEY_RIGHT         , XBMCK_RIGHT       },
215   { KEY_END           , XBMCK_END         },
216   { KEY_DOWN          , XBMCK_DOWN        },
217   { KEY_PAGEDOWN      , XBMCK_PAGEDOWN    },
218   { KEY_INSERT        , XBMCK_INSERT      },
219   { KEY_DELETE        , XBMCK_DELETE      },
220   { KEY_MUTE          , XBMCK_VOLUME_MUTE },
221   { KEY_VOLUMEDOWN    , XBMCK_VOLUME_DOWN },
222   { KEY_VOLUMEUP      , XBMCK_VOLUME_UP   },
223   { KEY_POWER         , XBMCK_POWER       },
224   { KEY_KPEQUAL       , XBMCK_KP_EQUALS   },
225   { KEY_PAUSE         , XBMCK_PAUSE       },
226   { KEY_LEFTMETA      , XBMCK_LMETA       },
227   { KEY_RIGHTMETA     , XBMCK_RMETA       },
228   { KEY_COMPOSE       , XBMCK_LSUPER      },
229   { KEY_STOP          , XBMCK_MEDIA_STOP  },
230   { KEY_HELP          , XBMCK_HELP        },
231   { KEY_CLOSECD       , XBMCK_EJECT       },
232   { KEY_EJECTCD       , XBMCK_EJECT       },
233   { KEY_EJECTCLOSECD  , XBMCK_EJECT       },
234   { KEY_NEXTSONG      , XBMCK_MEDIA_NEXT_TRACK},
235   { KEY_PLAYPAUSE     , XBMCK_MEDIA_PLAY_PAUSE},
236   { KEY_PREVIOUSSONG  , XBMCK_MEDIA_PREV_TRACK},
237   { KEY_STOPCD        , XBMCK_MEDIA_STOP  },
238   { KEY_RECORD        , XBMCK_RECORD      },
239   { KEY_REWIND        , XBMCK_REWIND      },
240   { KEY_PHONE         , XBMCK_PHONE       },
241   { KEY_REFRESH       , XBMCK_SHUFFLE     },
242   { KEY_SCROLLUP      , XBMCK_PAGEUP      },
243   { KEY_SCROLLDOWN    , XBMCK_PAGEDOWN    },
244   { KEY_PLAY          , XBMCK_PLAY        },
245   { KEY_FASTFORWARD   , XBMCK_FASTFORWARD },
246   { KEY_PRINT         , XBMCK_PRINT       },
247   { KEY_QUESTION      , XBMCK_HELP        },
248   // The Little Black Box Remote Additions
249   { 384               , XBMCK_LEFT        }, // Red
250   { 378               , XBMCK_RIGHT       }, // Green
251   { 381               , XBMCK_UP          }, // Yellow
252   { 366               , XBMCK_DOWN        }, // Blue
253 };
254
255 typedef enum
256 {
257   LI_DEVICE_NONE     = 0,
258   LI_DEVICE_MOUSE    = 1,
259   LI_DEVICE_JOYSTICK = 2,
260   LI_DEVICE_KEYBOARD = 4,
261   LI_DEVICE_REMOTE   = 8
262 } LinuxInputDeviceType;
263
264 typedef enum
265 {
266   LI_CAPS_KEYS    = 1,
267   LI_CAPS_BUTTONS = 2,
268   LI_CAPS_AXES    = 4,
269 } LinuxInputCapsType;
270
271 static char remoteStatus = 0xFF; // paired, battery OK
272
273 CLinuxInputDevice::CLinuxInputDevice(const std::string fileName, int index)
274 {
275   m_fd = -1;
276   m_vt_fd = -1;
277   m_hasLeds = false;
278   m_fileName = fileName;
279   m_ledState[0] = false;
280   m_ledState[1] = false;
281   m_ledState[2] = false;
282   m_mouseX = 0;
283   m_mouseY = 0;
284   m_deviceIndex = index;
285   m_keyMods = XBMCKMOD_NONE;
286   m_lastKeyMods = XBMCKMOD_NONE;
287   strcpy(m_deviceName, "");
288   m_deviceType = 0;
289   m_devicePreferredId = 0;
290   m_deviceCaps = 0;
291   m_deviceMinKeyCode = 0;
292   m_deviceMaxKeyCode = 0;
293   m_deviceMaxAxis = 0;
294   m_bUnplugged = false;
295
296   Open();
297 }
298
299 CLinuxInputDevice::~CLinuxInputDevice()
300 {
301   Close();
302 }
303
304 /*
305  * Translates a Linux input keycode into an XBMC keycode.
306  */
307 XBMCKey CLinuxInputDevice::TranslateKey(unsigned short code)
308 {
309   for (size_t index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
310   {
311     if (code == keyMap[index].Key)
312       return keyMap[index].xbmcKey;
313   }
314
315   return XBMCK_UNKNOWN;
316 }
317
318 int CLinuxInputDevice::KeyboardGetSymbol(unsigned short value)
319 {
320   unsigned char type = KTYP(value);
321   unsigned char index = KVAL(value);
322
323   switch (type)
324   {
325   case KT_FN:
326     if (index < 15)
327       return XBMCK_F1 + index;
328     break;
329   case KT_LETTER:
330   case KT_LATIN:
331     switch (index)
332     {
333     case 0x1c:
334       return XBMCK_PRINT;
335     case 0x7f:
336       return XBMCK_BACKSPACE;
337     case 0xa4:
338       return XBMCK_EURO; /* euro currency sign */
339     default:
340       return index;
341     }
342     break;
343
344 /*
345   case KT_DEAD:
346     switch (value)
347     {
348     case K_DGRAVE:
349       return DIKS_DEAD_GRAVE;
350
351     case K_DACUTE:
352       return DIKS_DEAD_ACUTE;
353
354     case K_DCIRCM:
355       return DIKS_DEAD_CIRCUMFLEX;
356
357     case K_DTILDE:
358       return DIKS_DEAD_TILDE;
359
360     case K_DDIERE:
361       return DIKS_DEAD_DIAERESIS;
362
363     case K_DCEDIL:
364       return DIKS_DEAD_CEDILLA;
365
366     default:
367       break;
368     }
369     break;
370
371   case KT_PAD:
372     if (index <= 9 && level != DIKSI_BASE)
373       return (DFBInputDeviceKeySymbol) (DIKS_0 + index);
374     break;
375 */
376   }
377
378   return XBMCK_UNKNOWN;
379 }
380
381 unsigned short CLinuxInputDevice::KeyboardReadValue(unsigned char table, unsigned char index)
382 {
383   struct kbentry entry;
384
385   entry.kb_table = table;
386   entry.kb_index = index;
387   entry.kb_value = 0;
388
389   if (ioctl(m_vt_fd, KDGKBENT, &entry))
390   {
391     CLog::Log(LOGWARNING, "CLinuxInputDevice::KeyboardReadValue: KDGKBENT (table: %d, index: %d) "
392         "failed!\n", table, index);
393     return 0;
394   }
395
396   return entry.kb_value;
397 }
398
399 XBMCMod CLinuxInputDevice::UpdateModifiers(XBMC_Event& devt)
400 {
401   XBMCMod modifier = XBMCKMOD_NONE;
402   switch (devt.key.keysym.sym)
403   {
404     case XBMCK_LSHIFT: modifier = XBMCKMOD_LSHIFT; break;
405     case XBMCK_RSHIFT: modifier = XBMCKMOD_RSHIFT; break;
406     case XBMCK_LCTRL: modifier = XBMCKMOD_LCTRL; break;
407     case XBMCK_RCTRL: modifier = XBMCKMOD_RCTRL; break;
408     case XBMCK_LALT: modifier = XBMCKMOD_LALT; break;
409     case XBMCK_RALT: modifier = XBMCKMOD_RALT; break;
410     case XBMCK_LMETA: modifier = XBMCKMOD_LMETA; break;
411     case XBMCK_RMETA: modifier = XBMCKMOD_RMETA; break;
412     default: break;
413   }
414
415   if (devt.key.type == XBMC_KEYDOWN)
416   {
417     m_keyMods |= modifier;
418   }
419   else
420   {
421     m_keyMods &= ~modifier;
422   }
423
424   if (devt.key.type == XBMC_KEYDOWN)
425   {
426     modifier = XBMCKMOD_NONE;
427     switch (devt.key.keysym.sym)
428     {
429       case XBMCK_NUMLOCK: modifier = XBMCKMOD_NUM; break;
430       case XBMCK_CAPSLOCK: modifier = XBMCKMOD_CAPS; break;
431       default: break;
432     }
433
434     if (m_keyMods & modifier)
435     {
436       m_keyMods &= ~modifier;
437     }
438     else
439     {
440       m_keyMods |= modifier;
441     }
442   }
443
444   return (XBMCMod) m_keyMods;
445 }
446
447 /*
448  * Translates key and button events.
449  */
450 bool CLinuxInputDevice::KeyEvent(const struct input_event& levt, XBMC_Event& devt)
451 {
452   int code = levt.code;
453
454   /* map touchscreen and smartpad events to button mouse */
455   if (code == BTN_TOUCH || code == BTN_TOOL_FINGER)
456     code = BTN_MOUSE;
457
458   if ((code >= BTN_MOUSE && code < BTN_JOYSTICK) || code == BTN_TOUCH)
459   {
460     /* ignore repeat events for buttons */
461     if (levt.value == 2)
462       return false;
463
464     devt.type = levt.value ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP;
465     devt.button.state = levt.value ? XBMC_PRESSED : XBMC_RELEASED;
466     devt.button.type = devt.type;
467     devt.button.x = m_mouseX;
468     devt.button.y = m_mouseY;
469
470     switch (levt.code)
471     {
472       case BTN_RIGHT:
473         devt.button.button = XBMC_BUTTON_RIGHT;
474         break;
475
476       case BTN_LEFT:
477         devt.button.button = XBMC_BUTTON_LEFT;
478         break;
479
480       case BTN_MIDDLE:
481         devt.button.button = XBMC_BUTTON_RIGHT;
482         break;
483
484       case BTN_FORWARD:
485         devt.button.button = XBMC_BUTTON_WHEELDOWN;
486         break;
487
488       case BTN_BACK:
489         devt.button.button = XBMC_BUTTON_WHEELUP;
490         break;
491
492       case BTN_TOUCH:
493         devt.button.button = XBMC_BUTTON_LEFT;
494         break;
495
496       case BTN_TOOL_DOUBLETAP:
497         devt.button.button = XBMC_BUTTON_RIGHT;
498         break;
499
500       default:
501         CLog::Log(LOGWARNING, "CLinuxInputDevice::KeyEvent: Unknown mouse button code: %d\n", levt.code);
502         return false;
503     }
504   }
505   else
506   {
507     XBMCKey key = TranslateKey(code);
508
509     if (key == XBMCK_UNKNOWN)
510     {
511       CLog::Log(LOGDEBUG, "CLinuxInputDevice::KeyEvent: TranslateKey returned XBMCK_UNKNOWN from code(%d)", code);
512       return false;
513     }
514
515     devt.type = levt.value ? XBMC_KEYDOWN : XBMC_KEYUP;
516     devt.key.type = devt.type;
517     // warning, key.keysym.scancode is unsigned char so 0 - 255 only
518     devt.key.keysym.scancode = code;
519     devt.key.keysym.sym = key;
520     devt.key.keysym.mod = UpdateModifiers(devt);
521     devt.key.keysym.unicode = 0;
522
523     KeymapEntry entry;
524     entry.code = code;
525     if (GetKeymapEntry(entry))
526     {
527       int keyMapValue;
528       if (devt.key.keysym.mod & (XBMCKMOD_SHIFT | XBMCKMOD_CAPS)) keyMapValue = entry.shift;
529       else if (devt.key.keysym.mod & XBMCKMOD_ALT) keyMapValue = entry.alt;
530       else if (devt.key.keysym.mod & XBMCKMOD_META) keyMapValue = entry.altShift;
531       else keyMapValue = entry.base;
532
533       if (keyMapValue != XBMCK_UNKNOWN)
534       {
535         devt.key.keysym.sym = (XBMCKey) keyMapValue;
536         if (keyMapValue > 0 && keyMapValue < 127)
537         {
538           devt.key.keysym.unicode = devt.key.keysym.sym;
539         }
540       }
541     }
542   }
543
544   return true;
545 }
546
547 /*
548  * Translates relative axis events.
549  */
550 bool CLinuxInputDevice::RelEvent(const struct input_event& levt, XBMC_Event& devt)
551 {
552   switch (levt.code)
553   {
554   case REL_X:
555     m_mouseX += levt.value;
556     devt.motion.xrel = levt.value;
557     devt.motion.yrel = 0;
558     break;
559
560   case REL_Y:
561     m_mouseY += levt.value;
562     devt.motion.xrel = 0;
563     devt.motion.yrel = levt.value;
564     break;
565
566   case REL_Z:
567   case REL_WHEEL:
568   default:
569     CLog::Log(LOGWARNING, "CLinuxInputDevice::RelEvent: Unknown rel event code: %d\n", levt.code);
570     return false;
571   }
572
573   // limit the mouse to the screen width
574   m_mouseX = std::min(g_graphicsContext.GetWidth(), m_mouseX);
575   m_mouseX = std::max(0, m_mouseX);
576
577   // limit the mouse to the screen height
578   m_mouseY = std::min(g_graphicsContext.GetHeight(), m_mouseY);
579   m_mouseY = std::max(0, m_mouseY);
580
581
582   devt.type = XBMC_MOUSEMOTION;
583   devt.motion.type = XBMC_MOUSEMOTION;
584   devt.motion.x = m_mouseX;
585   devt.motion.y = m_mouseY;
586   devt.motion.state = 0;
587   devt.motion.which = m_deviceIndex;
588
589
590   return true;
591 }
592
593 /*
594  * Translates absolute axis events.
595  */
596 bool CLinuxInputDevice::AbsEvent(const struct input_event& levt, XBMC_Event& devt)
597 {
598   switch (levt.code)
599   {
600   case ABS_X:
601     m_mouseX = levt.value;
602     break;
603
604   case ABS_Y:
605     m_mouseY = levt.value;
606     break;
607   
608   case ABS_MISC:
609     remoteStatus = levt.value & 0xFF;
610     break;
611
612   case ABS_Z:
613   default:
614     return false;
615   }
616
617   devt.type = XBMC_MOUSEMOTION;
618   devt.motion.type = XBMC_MOUSEMOTION;
619   devt.motion.x = m_mouseX;
620   devt.motion.y = m_mouseY;
621   devt.motion.state = 0;
622   devt.motion.xrel = 0;
623   devt.motion.yrel = 0;
624   devt.motion.which = m_deviceIndex;
625
626   return true;
627 }
628
629 /*
630  * Translates a Linux input event into a DirectFB input event.
631  */
632 bool CLinuxInputDevice::TranslateEvent(const struct input_event& levt,
633     XBMC_Event& devt)
634 {
635   switch (levt.type)
636   {
637   case EV_KEY:
638     return KeyEvent(levt, devt);
639
640   case EV_REL:
641     if (m_bSkipNonKeyEvents)
642     {
643       CLog::Log(LOGINFO, "read a relative event which will be ignored (device name %s) (file name %s)", m_deviceName, m_fileName.c_str());
644       return false;
645     }
646
647     return RelEvent(levt, devt);
648
649   case EV_ABS:
650     if (m_bSkipNonKeyEvents)
651     {
652       CLog::Log(LOGINFO, "read an absolute event which will be ignored (device name %s) (file name %s)", m_deviceName, m_fileName.c_str());
653       return false;
654     }
655
656     return AbsEvent(levt, devt);
657
658   default:
659     ;
660   }
661
662   return false;
663 }
664
665 void CLinuxInputDevice::SetLed(int led, int state)
666 {
667   struct input_event levt;
668
669   levt.type = EV_LED;
670   levt.code = led;
671   levt.value = !!state;
672
673   write(m_fd, &levt, sizeof(levt));
674 }
675
676 /*
677  * Input thread reading from device.
678  * Generates events on incoming data.
679  */
680 XBMC_Event CLinuxInputDevice::ReadEvent()
681 {
682   int readlen;
683   struct input_event levt;
684
685   XBMC_Event devt;
686
687   while (1)
688   {
689     bzero(&levt, sizeof(levt));
690
691     bzero(&devt, sizeof(devt));
692     devt.type = XBMC_NOEVENT;
693
694     if(m_devicePreferredId == LI_DEVICE_NONE)
695       return devt;
696
697     readlen = read(m_fd, &levt, sizeof(levt));
698
699     if (readlen <= 0)
700     {
701       if (errno == ENODEV)
702       {
703         CLog::Log(LOGINFO,"input device was unplugged %s",m_deviceName);
704         m_bUnplugged = true;
705       }
706
707       break;
708     }
709
710     //printf("read event readlen = %d device name %s m_fileName %s\n", readlen, m_deviceName, m_fileName.c_str());
711
712     // sanity check if we realy read the event
713     if(readlen != sizeof(levt))
714     {
715       printf("CLinuxInputDevice: read error : %s\n", strerror(errno));
716       break;
717     }
718
719     if (!TranslateEvent(levt, devt))
720       continue;
721
722     /* Flush previous event with DIEF_FOLLOW? */
723     if (devt.type != XBMC_NOEVENT)
724     {
725       //printf("new event! type = %d\n", devt.type);
726       //printf("key: %d %d %d %c\n", devt.key.keysym.scancode, devt.key.keysym.sym, devt.key.keysym.mod, devt.key.keysym.unicode);
727
728       if (m_hasLeds && (m_keyMods != m_lastKeyMods))
729       {
730         SetLed(LED_NUML, m_keyMods & XBMCKMOD_NUM);
731         SetLed(LED_CAPSL, m_keyMods & XBMCKMOD_CAPS);
732         m_lastKeyMods = m_keyMods;
733       }
734
735       break;
736     }
737   }
738
739   return devt;
740 }
741
742 void CLinuxInputDevice::SetupKeyboardAutoRepeat(int fd)
743 {
744   bool enable = true;
745
746 #if defined(HAS_AMLPLAYER)
747   // ignore the native aml driver named 'key_input',
748   //  it is the dedicated power key handler (am_key_input)
749   if (strncmp(m_deviceName, "key_input", strlen("key_input")) == 0)
750     return;
751   // ignore the native aml driver named 'aml_keypad',
752   //  it is the dedicated IR remote handler (amremote)
753   else if (strncmp(m_deviceName, "aml_keypad", strlen("aml_keypad")) == 0)
754     return;
755
756   // turn off any keyboard autorepeat, there is a kernel bug
757   // where if the cpu is max'ed then key up is missed and
758   // we get a flood of EV_REP that never stop until next
759   // key down/up. Very nasty when seeking during video playback.
760   enable = false;
761 #endif
762
763   if (enable)
764   {
765     int kbdrep[2] = { 400, 80 };
766     ioctl(fd, EVIOCSREP, kbdrep);
767   }
768   else
769   {
770     struct input_event event;
771     memset(&event, 0, sizeof(event));
772
773     gettimeofday(&event.time, NULL);
774     event.type  = EV_REP;
775     event.code  = REP_DELAY;
776     event.value = 0;
777     write(fd, &event, sizeof(event));
778
779     gettimeofday(&event.time, NULL);
780     event.type  = EV_REP;
781     event.code  = REP_PERIOD;
782     event.value = 0;
783     write(fd, &event, sizeof(event));
784
785     CLog::Log(LOGINFO, "CLinuxInputDevice: auto key repeat disabled on device '%s'\n", m_deviceName);
786   }
787 }
788
789 /*
790  * Fill device information.
791  * Queries the input device and tries to classify it.
792  */
793 void CLinuxInputDevice::GetInfo(int fd)
794 {
795   unsigned int num_keys = 0;
796   unsigned int num_ext_keys = 0;
797   unsigned int num_buttons = 0;
798   unsigned int num_rels = 0;
799   unsigned int num_abs = 0;
800
801   unsigned long evbit[NBITS(EV_CNT)];
802   unsigned long keybit[NBITS(KEY_CNT)];
803
804   /* get device name */
805   bzero(m_deviceName, sizeof(m_deviceName));
806   ioctl(fd, EVIOCGNAME(sizeof(m_deviceName)-1), m_deviceName);
807
808   if (strncmp(m_deviceName, "D-Link Boxee D-Link Boxee Receiver", strlen("D-Link Boxee D-Link Boxee Receiver")) == 0)
809   {
810     m_bSkipNonKeyEvents = true;
811   }
812   else
813   {
814     m_bSkipNonKeyEvents = false;
815   }
816   CLog::Log(LOGINFO, "opened device '%s' (file name %s), m_bSkipNonKeyEvents %d\n", m_deviceName, m_fileName.c_str(), m_bSkipNonKeyEvents);
817
818   /* get event type bits */
819   ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit);
820
821   if (test_bit( EV_KEY, evbit ))
822   {
823     int i;
824
825     /* get keyboard bits */
826     ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit);
827
828     /**  count typical keyboard keys only */
829     for (i = KEY_Q; i <= KEY_M; i++)
830       if (test_bit( i, keybit ))
831         num_keys++;
832
833     for (i = KEY_OK; i < KEY_CNT; i++)
834       if (test_bit( i, keybit ))
835         num_ext_keys++;
836
837     for (i = BTN_MOUSE; i < BTN_JOYSTICK; i++)
838       if (test_bit( i, keybit ))
839         num_buttons++;
840   }
841
842 #ifndef HAS_INTELCE
843   unsigned long relbit[NBITS(REL_CNT)];
844   unsigned long absbit[NBITS(ABS_CNT)];
845
846   if (test_bit( EV_REL, evbit ))
847   {
848     int i;
849
850     /* get bits for relative axes */
851     ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit);
852
853     for (i = 0; i < REL_CNT; i++)
854       if (test_bit( i, relbit ))
855         num_rels++;
856   }
857
858   if (test_bit( EV_ABS, evbit ))
859   {
860     int i;
861
862     /* get bits for absolute axes */
863     ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit);
864
865     for (i = 0; i < ABS_PRESSURE; i++)
866       if (test_bit( i, absbit ))
867         num_abs++;
868   }
869
870   /* Mouse, Touchscreen or Smartpad ? */
871   if ((test_bit( EV_KEY, evbit ) && (test_bit( BTN_TOUCH, keybit )
872       || test_bit( BTN_TOOL_FINGER, keybit ))) || ((num_rels >= 2
873       && num_buttons) || (num_abs == 2 && (num_buttons == 1))))
874     m_deviceType |= LI_DEVICE_MOUSE;
875   else if (num_abs && num_buttons) /* Or a Joystick? */
876     m_deviceType |= LI_DEVICE_JOYSTICK;
877 #endif
878
879   /* A Keyboard, do we have at least some letters? */
880   if (num_keys > 20)
881   {
882     m_deviceType |= LI_DEVICE_KEYBOARD;
883     m_deviceCaps |= LI_CAPS_KEYS;
884
885     m_deviceMinKeyCode = 0;
886     m_deviceMaxKeyCode = 127;
887   }
888
889   /* A Remote Control? */
890   if (num_ext_keys)
891   {
892     m_deviceType |= LI_DEVICE_REMOTE;
893     m_deviceCaps |= LI_CAPS_KEYS;
894   }
895
896   /* Buttons */
897   if (num_buttons)
898   {
899     m_deviceCaps |= LI_CAPS_BUTTONS;
900     m_deviceMaxKeyCode = num_buttons - 1;
901   }
902
903   /* Axes */
904   if (num_rels || num_abs)
905   {
906     m_deviceCaps |= LI_CAPS_AXES;
907     m_deviceMaxAxis = std::max(num_rels, num_abs) - 1;
908   }
909
910   /* Decide which primary input device to be. */
911   if (m_deviceType & LI_DEVICE_KEYBOARD)
912     m_devicePreferredId = LI_DEVICE_KEYBOARD;
913   else if (m_deviceType & LI_DEVICE_REMOTE)
914     m_devicePreferredId = LI_DEVICE_REMOTE;
915   else if (m_deviceType & LI_DEVICE_JOYSTICK)
916     m_devicePreferredId = LI_DEVICE_JOYSTICK;
917   else if (m_deviceType & LI_DEVICE_MOUSE)
918     m_devicePreferredId = LI_DEVICE_MOUSE;
919   else
920     m_devicePreferredId = LI_DEVICE_NONE;
921
922   //printf("type: %d\n", m_deviceType);
923   //printf("caps: %d\n", m_deviceCaps);
924   //printf("pref: %d\n", m_devicePreferredId);
925 }
926
927 char* CLinuxInputDevice::GetDeviceName()
928 {
929   return m_deviceName;
930 }
931
932 bool CLinuxInputDevice::IsUnplugged()
933 {
934   return m_bUnplugged;
935 }
936
937 bool CLinuxInputDevices::CheckDevice(const char *device)
938 {
939   int fd;
940
941   /* Check if we are able to open the device */
942   fd = open(device, O_RDWR);
943   if (fd < 0)
944     return false;
945
946   if (ioctl(fd, EVIOCGRAB, 1) && errno != EINVAL)
947   {
948     close(fd);
949     return false;
950   }
951
952   ioctl(fd, EVIOCGRAB, 0);
953
954   close(fd);
955
956   return true;
957 }
958
959 /* exported symbols */
960
961 /*
962  * Return the number of available devices.
963  * Called once during initialization of DirectFB.
964  */
965 void CLinuxInputDevices::InitAvailable()
966 {
967   CSingleLock lock(m_devicesListLock);
968
969   /* Close any devices that may have been initialized previously */
970   for (size_t i = 0; i < m_devices.size(); i++)
971   {
972     delete m_devices[i];
973   }
974   m_devices.clear();
975
976   int deviceId = 0;
977
978   /* No devices specified. Try to guess some. */
979   for (int i = 0; i < MAX_LINUX_INPUT_DEVICES; i++)
980   {
981     char buf[32];
982
983     snprintf(buf, 32, "/dev/input/event%d", i);
984     if (CheckDevice(buf))
985     {
986       CLog::Log(LOGINFO, "Found input device %s", buf);
987       m_devices.push_back(new CLinuxInputDevice(buf, deviceId));
988       ++deviceId;
989     }
990   }
991 }
992
993 /*
994  * Check for hot plugged devices.
995  */
996 void CLinuxInputDevices::CheckHotplugged()
997 {
998   CSingleLock lock(m_devicesListLock);
999
1000   int deviceId = m_devices.size();
1001
1002   /* No devices specified. Try to guess some. */
1003   for (int i = 0; i < MAX_LINUX_INPUT_DEVICES; i++)
1004   {
1005     char buf[32];
1006     bool ispresent = false;
1007
1008     snprintf(buf, 32, "/dev/input/event%d", i);
1009
1010     for (size_t j = 0; j < m_devices.size(); j++)
1011     {
1012       if (strcmp(m_devices[j]->GetDeviceName(),buf) == 0)
1013       {
1014         ispresent = true;
1015         break;
1016       }
1017     }
1018
1019     if (!ispresent && CheckDevice(buf))
1020     {
1021       CLog::Log(LOGINFO, "Found input device %s", buf);
1022       m_devices.push_back(new CLinuxInputDevice(buf, deviceId));
1023       ++deviceId;
1024     }
1025   }
1026 }
1027
1028 /*
1029  * Open the device, fill out information about it,
1030  * allocate and fill private data, start input thread.
1031  */
1032 bool CLinuxInputDevice::Open()
1033 {
1034   int fd, ret;
1035   unsigned long ledbit[NBITS(LED_CNT)];
1036
1037   /* open device */
1038   fd = open(m_fileName.c_str(), O_RDWR | O_NONBLOCK);
1039   if (fd < 0)
1040   {
1041     CLog::Log(LOGERROR, "CLinuxInputDevice: could not open device: %s\n", m_fileName.c_str());
1042     return false;
1043   }
1044
1045   /* grab device */
1046   ret = ioctl(fd, EVIOCGRAB, 1);
1047   if (ret && errno != EINVAL)
1048   {
1049     CLog::Log(LOGERROR, "CLinuxInputDevice: could not grab device: %s\n", m_fileName.c_str());
1050     close(fd);
1051     return false;
1052   }
1053
1054   // Set the socket to non-blocking
1055   int opts = 0;
1056   if ((opts = fcntl(fd, F_GETFL)) < 0)
1057   {
1058     CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_GETFL) failed: %s", __FUNCTION__ , strerror(errno));
1059     close(fd);
1060     return false;
1061   }
1062
1063   opts = (opts | O_NONBLOCK);
1064   if (fcntl(fd, F_SETFL, opts) < 0)
1065   {
1066     CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_SETFL) failed: %s", __FUNCTION__, strerror(errno));
1067     close(fd);
1068     return false;
1069   }
1070
1071   /* fill device info structure */
1072   GetInfo(fd);
1073
1074   if (m_deviceType & LI_DEVICE_KEYBOARD)
1075     SetupKeyboardAutoRepeat(fd);
1076
1077   m_fd = fd;
1078   m_vt_fd = -1;
1079
1080   if (m_deviceMinKeyCode >= 0 && m_deviceMaxKeyCode >= m_deviceMinKeyCode)
1081   {
1082     if (m_vt_fd < 0)
1083       m_vt_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
1084  
1085     if (m_vt_fd < 0)
1086       m_vt_fd = open("/dev/tty1", O_RDWR | O_NOCTTY);
1087
1088     if (m_vt_fd < 0)
1089       CLog::Log(LOGWARNING, "no keymap support (requires /dev/tty0 - CONFIG_VT)");
1090   }
1091
1092   /* check if the device has LEDs */
1093   ret = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit);
1094   if (ret < 0)
1095           CLog::Log(LOGWARNING, "DirectFB/linux_input: could not get LED bits" );
1096   else
1097     m_hasLeds = test_bit( LED_SCROLLL, ledbit ) || test_bit( LED_NUML, ledbit )
1098         || test_bit( LED_CAPSL, ledbit );
1099
1100   if (m_hasLeds)
1101   {
1102     /* get LED state */
1103     ret = ioctl(fd, EVIOCGLED(sizeof(m_ledState)), m_ledState);
1104     if (ret < 0)
1105     {
1106       CLog::Log(LOGERROR, "DirectFB/linux_input: could not get LED state");
1107       goto driver_open_device_error;
1108     }
1109
1110     /* turn off LEDs */
1111     SetLed(LED_SCROLLL, 0);
1112     SetLed(LED_NUML, 0);
1113     SetLed(LED_CAPSL, 0);
1114   }
1115
1116   return true;
1117
1118 driver_open_device_error:
1119
1120   ioctl(fd, EVIOCGRAB, 0);
1121   if (m_vt_fd >= 0)
1122   {
1123     close(m_vt_fd);
1124     m_vt_fd = -1;
1125   }
1126   close(fd);
1127   m_fd = -1;
1128
1129   return false;
1130 }
1131
1132 /*
1133  * Fetch one entry from the kernel keymap.
1134  */
1135 bool CLinuxInputDevice::GetKeymapEntry(KeymapEntry& entry)
1136 {
1137   int code = entry.code;
1138   unsigned short value;
1139   //DFBInputDeviceKeyIdentifier identifier;
1140
1141   if (m_vt_fd < 0)
1142     return false;
1143
1144   // to support '+'  and '/' with Boxee's remote control we do something ugly like this for now
1145   if (KVAL(code) == 98)
1146   {
1147     code = K(KTYP(code),53);
1148   }
1149
1150   /* fetch the base level */
1151   value = KeyboardGetSymbol(KeyboardReadValue(K_NORMTAB, code));
1152   //printf("base=%d typ=%d code %d\n", KVAL(value), KTYP(value), code);
1153
1154   /* write base level symbol to entry */
1155   entry.base = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_BASE);
1156
1157   /* fetch the shifted base level */
1158   value = KeyboardGetSymbol(KeyboardReadValue(K_SHIFTTAB, entry.code));
1159   //printf("shift=%d\n", value);
1160
1161   /* write shifted base level symbol to entry */
1162   entry.shift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_SHIFT);
1163
1164   // to support '+'  and '/' with Boxee's remote control we could do ugly something like this for now
1165   if (KVAL(code) == 78)
1166   {
1167     //code = K(KTYP(code),13);
1168     //entry.code = K(KTYP(code),13);
1169     entry.base = K(KTYP(code),43);
1170   }
1171
1172   /* fetch the alternative level */
1173   value = KeyboardGetSymbol(KeyboardReadValue(K_ALTTAB, entry.code));
1174   //printf("alt=%d\n", value);
1175
1176   /* write alternative level symbol to entry */
1177   entry.alt = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT);
1178
1179   /* fetch the shifted alternative level */
1180   value = KeyboardGetSymbol(KeyboardReadValue(K_ALTSHIFTTAB, entry.code));
1181   //printf("altshift=%d\n", value);
1182
1183   /* write shifted alternative level symbol to entry */
1184   entry.altShift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT_SHIFT);
1185
1186   return true;
1187 }
1188
1189 /*
1190  * End thread, close device and free private data.
1191  */
1192 void CLinuxInputDevice::Close()
1193 {
1194   /* release device */
1195   ioctl(m_fd, EVIOCGRAB, 0);
1196
1197   if (m_vt_fd >= 0)
1198     close(m_vt_fd);
1199
1200   /* close file */
1201   close(m_fd);
1202 }
1203
1204 XBMC_Event CLinuxInputDevices::ReadEvent()
1205 {
1206   if (m_bReInitialize)
1207   {
1208     InitAvailable();
1209     m_bReInitialize = false;
1210   }
1211   else
1212   {
1213     time_t now;
1214     time(&now);
1215
1216     if ((now - m_lastHotplugCheck) >= 10)
1217     {
1218       CheckHotplugged();
1219       m_lastHotplugCheck = now;
1220     }
1221   }
1222
1223   CSingleLock lock(m_devicesListLock);
1224
1225   XBMC_Event event;
1226   event.type = XBMC_NOEVENT;
1227
1228   for (size_t i = 0; i < m_devices.size(); i++)
1229   {
1230     event = m_devices[i]->ReadEvent();
1231     if (event.type != XBMC_NOEVENT)
1232     {
1233       break;
1234     }
1235
1236     if (m_devices[i]->IsUnplugged())
1237     {
1238       m_bReInitialize = true;
1239       break;
1240     }
1241   }
1242
1243   return event;
1244 }
1245
1246 /*
1247    - 0x7F -> if not paired, battery OK
1248    - 0xFF -> if paired, battery OK
1249    - 0x00 -> if not paired, battery low
1250    - 0x80 -> if paired, battery low
1251 */
1252 bool CLinuxInputDevices::IsRemoteLowBattery()
1253 {
1254   bool bLowBattery = !(remoteStatus & 0xF);
1255   return bLowBattery;
1256 }
1257
1258 bool CLinuxInputDevices::IsRemoteNotPaired()
1259 {
1260   bool bRemoteNotPaired = !(remoteStatus & 0x70) || !(remoteStatus & 0x80);
1261   return bRemoteNotPaired;
1262 }
1263
1264 /*
1265 int main()
1266 {
1267   CLinuxInputDevices devices;
1268   devices.InitAvailable();
1269   while (1)
1270   {
1271     XBMC_Event event = devices.ReadEvent();
1272     if (event.type != XBMC_NOEVENT)
1273     {
1274       printf("%d\n", event.type);
1275     }
1276     usleep(1000);
1277   }
1278
1279 }
1280 */
1281 #endif