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