506cffffa0a0781e6bc208300b8cd23cb7a7fa49
[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 #ifdef TARGET_DVBBOX // oskwon
258   { 352               , XBMCK_RETURN      }, // Ok
259   { 412               , XBMCK_ESCAPE      }, // <
260 #endif /*TARGET_DVBBOX*/
261 };
262
263
264 typedef enum
265 {
266   LI_DEVICE_NONE     = 0,
267   LI_DEVICE_MOUSE    = 1,
268   LI_DEVICE_JOYSTICK = 2,
269   LI_DEVICE_KEYBOARD = 4,
270   LI_DEVICE_REMOTE   = 8
271 } LinuxInputDeviceType;
272
273 typedef enum
274 {
275   LI_CAPS_KEYS    = 1,
276   LI_CAPS_BUTTONS = 2,
277   LI_CAPS_AXES    = 4,
278 } LinuxInputCapsType;
279
280 static char remoteStatus = 0xFF; // paired, battery OK
281
282 CLinuxInputDevice::CLinuxInputDevice(const std::string fileName, int index)
283 {
284   m_fd = -1;
285   m_vt_fd = -1;
286   m_hasLeds = false;
287   m_fileName = fileName;
288   m_ledState[0] = false;
289   m_ledState[1] = false;
290   m_ledState[2] = false;
291   m_mouseX = 0;
292   m_mouseY = 0;
293   m_deviceIndex = index;
294   m_keyMods = XBMCKMOD_NONE;
295   m_lastKeyMods = XBMCKMOD_NONE;
296   strcpy(m_deviceName, "");
297   m_deviceType = 0;
298   m_devicePreferredId = 0;
299   m_deviceCaps = 0;
300   m_deviceMinKeyCode = 0;
301   m_deviceMaxKeyCode = 0;
302   m_deviceMaxAxis = 0;
303   m_bUnplugged = false;
304
305   Open();
306 }
307
308 CLinuxInputDevice::~CLinuxInputDevice()
309 {
310   Close();
311 }
312
313 /*
314  * Translates a Linux input keycode into an XBMC keycode.
315  */
316 XBMCKey CLinuxInputDevice::TranslateKey(unsigned short code)
317 {
318   for (size_t index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
319   {
320     if (code == keyMap[index].Key)
321       return keyMap[index].xbmcKey;
322   }
323
324   return XBMCK_UNKNOWN;
325 }
326
327 int CLinuxInputDevice::KeyboardGetSymbol(unsigned short value)
328 {
329   unsigned char type = KTYP(value);
330   unsigned char index = KVAL(value);
331
332   switch (type)
333   {
334   case KT_FN:
335     if (index < 15)
336       return XBMCK_F1 + index;
337     break;
338   case KT_LETTER:
339   case KT_LATIN:
340     switch (index)
341     {
342     case 0x1c:
343       return XBMCK_PRINT;
344     case 0x7f:
345       return XBMCK_BACKSPACE;
346     case 0xa4:
347       return XBMCK_EURO; /* euro currency sign */
348     default:
349       return index;
350     }
351     break;
352
353 /*
354   case KT_DEAD:
355     switch (value)
356     {
357     case K_DGRAVE:
358       return DIKS_DEAD_GRAVE;
359
360     case K_DACUTE:
361       return DIKS_DEAD_ACUTE;
362
363     case K_DCIRCM:
364       return DIKS_DEAD_CIRCUMFLEX;
365
366     case K_DTILDE:
367       return DIKS_DEAD_TILDE;
368
369     case K_DDIERE:
370       return DIKS_DEAD_DIAERESIS;
371
372     case K_DCEDIL:
373       return DIKS_DEAD_CEDILLA;
374
375     default:
376       break;
377     }
378     break;
379
380   case KT_PAD:
381     if (index <= 9 && level != DIKSI_BASE)
382       return (DFBInputDeviceKeySymbol) (DIKS_0 + index);
383     break;
384 */
385   }
386
387   return XBMCK_UNKNOWN;
388 }
389
390 unsigned short CLinuxInputDevice::KeyboardReadValue(unsigned char table, unsigned char index)
391 {
392   struct kbentry entry;
393
394   entry.kb_table = table;
395   entry.kb_index = index;
396   entry.kb_value = 0;
397
398   if (ioctl(m_vt_fd, KDGKBENT, &entry))
399   {
400     CLog::Log(LOGWARNING, "CLinuxInputDevice::KeyboardReadValue: KDGKBENT (table: %d, index: %d) "
401         "failed!\n", table, index);
402     return 0;
403   }
404
405   return entry.kb_value;
406 }
407
408 XBMCMod CLinuxInputDevice::UpdateModifiers(XBMC_Event& devt)
409 {
410   XBMCMod modifier = XBMCKMOD_NONE;
411   switch (devt.key.keysym.sym)
412   {
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;
421     default: break;
422   }
423
424   if (devt.key.type == XBMC_KEYDOWN)
425   {
426     m_keyMods |= modifier;
427   }
428   else
429   {
430     m_keyMods &= ~modifier;
431   }
432
433   if (devt.key.type == XBMC_KEYDOWN)
434   {
435     modifier = XBMCKMOD_NONE;
436     switch (devt.key.keysym.sym)
437     {
438       case XBMCK_NUMLOCK: modifier = XBMCKMOD_NUM; break;
439       case XBMCK_CAPSLOCK: modifier = XBMCKMOD_CAPS; break;
440       default: break;
441     }
442
443     if (m_keyMods & modifier)
444     {
445       m_keyMods &= ~modifier;
446     }
447     else
448     {
449       m_keyMods |= modifier;
450     }
451   }
452
453   return (XBMCMod) m_keyMods;
454 }
455
456 /*
457  * Translates key and button events.
458  */
459 bool CLinuxInputDevice::KeyEvent(const struct input_event& levt, XBMC_Event& devt)
460 {
461   int code = levt.code;
462
463   /* map touchscreen and smartpad events to button mouse */
464   if (code == BTN_TOUCH || code == BTN_TOOL_FINGER)
465     code = BTN_MOUSE;
466
467   if ((code >= BTN_MOUSE && code < BTN_JOYSTICK) || code == BTN_TOUCH)
468   {
469     /* ignore repeat events for buttons */
470     if (levt.value == 2)
471       return false;
472
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;
478
479     switch (levt.code)
480     {
481       case BTN_RIGHT:
482         devt.button.button = XBMC_BUTTON_RIGHT;
483         break;
484
485       case BTN_LEFT:
486         devt.button.button = XBMC_BUTTON_LEFT;
487         break;
488
489       case BTN_MIDDLE:
490         devt.button.button = XBMC_BUTTON_RIGHT;
491         break;
492
493       case BTN_FORWARD:
494         devt.button.button = XBMC_BUTTON_WHEELDOWN;
495         break;
496
497       case BTN_BACK:
498         devt.button.button = XBMC_BUTTON_WHEELUP;
499         break;
500
501       case BTN_TOUCH:
502         devt.button.button = XBMC_BUTTON_LEFT;
503         break;
504
505       case BTN_TOOL_DOUBLETAP:
506         devt.button.button = XBMC_BUTTON_RIGHT;
507         break;
508
509       default:
510         CLog::Log(LOGWARNING, "CLinuxInputDevice::KeyEvent: Unknown mouse button code: %d\n", levt.code);
511         return false;
512     }
513   }
514   else
515   {
516     XBMCKey key = TranslateKey(code);
517
518     if (key == XBMCK_UNKNOWN)
519     {
520       CLog::Log(LOGDEBUG, "CLinuxInputDevice::KeyEvent: TranslateKey returned XBMCK_UNKNOWN from code(%d)", code);
521       return false;
522     }
523
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;
531
532     KeymapEntry entry;
533     entry.code = code;
534     if (GetKeymapEntry(entry))
535     {
536       int keyMapValue;
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;
541
542       if (keyMapValue != XBMCK_UNKNOWN)
543       {
544         devt.key.keysym.sym = (XBMCKey) keyMapValue;
545         if (keyMapValue > 0 && keyMapValue < 127)
546         {
547           devt.key.keysym.unicode = devt.key.keysym.sym;
548         }
549       }
550     }
551   }
552
553   return true;
554 }
555
556 /*
557  * Translates relative axis events.
558  */
559 bool CLinuxInputDevice::RelEvent(const struct input_event& levt, XBMC_Event& devt)
560 {
561   switch (levt.code)
562   {
563   case REL_X:
564     m_mouseX += levt.value;
565     devt.motion.xrel = levt.value;
566     devt.motion.yrel = 0;
567     break;
568
569   case REL_Y:
570     m_mouseY += levt.value;
571     devt.motion.xrel = 0;
572     devt.motion.yrel = levt.value;
573     break;
574
575   case REL_Z:
576   case REL_WHEEL:
577   default:
578     CLog::Log(LOGWARNING, "CLinuxInputDevice::RelEvent: Unknown rel event code: %d\n", levt.code);
579     return false;
580   }
581
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);
585
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);
589
590
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;
597
598
599   return true;
600 }
601
602 /*
603  * Translates absolute axis events.
604  */
605 bool CLinuxInputDevice::AbsEvent(const struct input_event& levt, XBMC_Event& devt)
606 {
607   switch (levt.code)
608   {
609   case ABS_X:
610     m_mouseX = levt.value;
611     break;
612
613   case ABS_Y:
614     m_mouseY = levt.value;
615     break;
616   
617   case ABS_MISC:
618     remoteStatus = levt.value & 0xFF;
619     break;
620
621   case ABS_Z:
622   default:
623     return false;
624   }
625
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;
634
635   return true;
636 }
637
638 /*
639  * Translates a Linux input event into a DirectFB input event.
640  */
641 bool CLinuxInputDevice::TranslateEvent(const struct input_event& levt,
642     XBMC_Event& devt)
643 {
644   switch (levt.type)
645   {
646   case EV_KEY:
647     return KeyEvent(levt, devt);
648
649   case EV_REL:
650     if (m_bSkipNonKeyEvents)
651     {
652       CLog::Log(LOGINFO, "read a relative event which will be ignored (device name %s) (file name %s)", m_deviceName, m_fileName.c_str());
653       return false;
654     }
655
656     return RelEvent(levt, devt);
657
658   case EV_ABS:
659     if (m_bSkipNonKeyEvents)
660     {
661       CLog::Log(LOGINFO, "read an absolute event which will be ignored (device name %s) (file name %s)", m_deviceName, m_fileName.c_str());
662       return false;
663     }
664
665     return AbsEvent(levt, devt);
666
667   default:
668     ;
669   }
670
671   return false;
672 }
673
674 void CLinuxInputDevice::SetLed(int led, int state)
675 {
676   struct input_event levt;
677
678   levt.type = EV_LED;
679   levt.code = led;
680   levt.value = !!state;
681
682   write(m_fd, &levt, sizeof(levt));
683 }
684
685 /*
686  * Input thread reading from device.
687  * Generates events on incoming data.
688  */
689 XBMC_Event CLinuxInputDevice::ReadEvent()
690 {
691   int readlen;
692   struct input_event levt;
693
694   XBMC_Event devt;
695
696   while (1)
697   {
698     bzero(&levt, sizeof(levt));
699
700     bzero(&devt, sizeof(devt));
701     devt.type = XBMC_NOEVENT;
702
703     if(m_devicePreferredId == LI_DEVICE_NONE)
704       return devt;
705
706     readlen = read(m_fd, &levt, sizeof(levt));
707
708     if (readlen <= 0)
709     {
710       if (errno == ENODEV)
711       {
712         CLog::Log(LOGINFO,"input device was unplugged %s",m_deviceName);
713         m_bUnplugged = true;
714       }
715
716       break;
717     }
718
719 #ifdef TARGET_DVBBOX // oskwon
720     if (access("/tmp/playing.lock", F_OK) == 0) {
721         break;
722     }
723 #endif /*TARGET_DVBBOX*/
724
725     //printf("read event readlen = %d device name %s m_fileName %s\n", readlen, m_deviceName, m_fileName.c_str());
726
727     // sanity check if we realy read the event
728     if(readlen != sizeof(levt))
729     {
730       printf("CLinuxInputDevice: read error : %s\n", strerror(errno));
731       break;
732     }
733
734     if (!TranslateEvent(levt, devt))
735       continue;
736
737     /* Flush previous event with DIEF_FOLLOW? */
738     if (devt.type != XBMC_NOEVENT)
739     {
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);
742
743       if (m_hasLeds && (m_keyMods != m_lastKeyMods))
744       {
745         SetLed(LED_NUML, m_keyMods & XBMCKMOD_NUM);
746         SetLed(LED_CAPSL, m_keyMods & XBMCKMOD_CAPS);
747         m_lastKeyMods = m_keyMods;
748       }
749
750       break;
751     }
752   }
753
754   return devt;
755 }
756
757 void CLinuxInputDevice::SetupKeyboardAutoRepeat(int fd)
758 {
759   bool enable = true;
760
761 #if defined(HAS_LIBAMCODEC)
762   if (aml_present())
763   {
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)
767       return;
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)
771       return;
772
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.
777     enable = false;
778   }
779 #endif
780
781   if (enable)
782   {
783     int kbdrep[2] = { 400, 80 };
784     ioctl(fd, EVIOCSREP, kbdrep);
785   }
786   else
787   {
788     struct input_event event;
789     memset(&event, 0, sizeof(event));
790
791     gettimeofday(&event.time, NULL);
792     event.type  = EV_REP;
793     event.code  = REP_DELAY;
794     event.value = 0;
795     write(fd, &event, sizeof(event));
796
797     gettimeofday(&event.time, NULL);
798     event.type  = EV_REP;
799     event.code  = REP_PERIOD;
800     event.value = 0;
801     write(fd, &event, sizeof(event));
802
803     CLog::Log(LOGINFO, "CLinuxInputDevice: auto key repeat disabled on device '%s'\n", m_deviceName);
804   }
805 }
806
807 /*
808  * Fill device information.
809  * Queries the input device and tries to classify it.
810  */
811 void CLinuxInputDevice::GetInfo(int fd)
812 {
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;
818
819   unsigned long evbit[NBITS(EV_CNT)];
820   unsigned long keybit[NBITS(KEY_CNT)];
821
822   /* get device name */
823   bzero(m_deviceName, sizeof(m_deviceName));
824   ioctl(fd, EVIOCGNAME(sizeof(m_deviceName)-1), m_deviceName);
825
826   if (strncmp(m_deviceName, "D-Link Boxee D-Link Boxee Receiver", strlen("D-Link Boxee D-Link Boxee Receiver")) == 0)
827   {
828     m_bSkipNonKeyEvents = true;
829   }
830   else
831   {
832     m_bSkipNonKeyEvents = false;
833   }
834   CLog::Log(LOGINFO, "opened device '%s' (file name %s), m_bSkipNonKeyEvents %d\n", m_deviceName, m_fileName.c_str(), m_bSkipNonKeyEvents);
835
836   /* get event type bits */
837   ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit);
838
839   if (test_bit( EV_KEY, evbit ))
840   {
841     int i;
842
843     /* get keyboard bits */
844     ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit);
845
846     /**  count typical keyboard keys only */
847     for (i = KEY_Q; i <= KEY_M; i++)
848       if (test_bit( i, keybit ))
849         num_keys++;
850
851     for (i = KEY_OK; i < KEY_CNT; i++)
852       if (test_bit( i, keybit ))
853         num_ext_keys++;
854
855     for (i = BTN_MOUSE; i < BTN_JOYSTICK; i++)
856       if (test_bit( i, keybit ))
857         num_buttons++;
858   }
859
860 #ifndef HAS_INTELCE
861   unsigned long relbit[NBITS(REL_CNT)];
862   unsigned long absbit[NBITS(ABS_CNT)];
863
864   if (test_bit( EV_REL, evbit ))
865   {
866     int i;
867
868     /* get bits for relative axes */
869     ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit);
870
871     for (i = 0; i < REL_CNT; i++)
872       if (test_bit( i, relbit ))
873         num_rels++;
874   }
875
876   if (test_bit( EV_ABS, evbit ))
877   {
878     int i;
879
880     /* get bits for absolute axes */
881     ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit);
882
883     for (i = 0; i < ABS_PRESSURE; i++)
884       if (test_bit( i, absbit ))
885         num_abs++;
886   }
887
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;
895 #endif
896
897   /* A Keyboard, do we have at least some letters? */
898   if (num_keys > 20)
899   {
900     m_deviceType |= LI_DEVICE_KEYBOARD;
901     m_deviceCaps |= LI_CAPS_KEYS;
902
903     m_deviceMinKeyCode = 0;
904     m_deviceMaxKeyCode = 127;
905   }
906
907   /* A Remote Control? */
908   if (num_ext_keys)
909   {
910     m_deviceType |= LI_DEVICE_REMOTE;
911     m_deviceCaps |= LI_CAPS_KEYS;
912   }
913
914   /* Buttons */
915   if (num_buttons)
916   {
917     m_deviceCaps |= LI_CAPS_BUTTONS;
918     m_deviceMaxKeyCode = num_buttons - 1;
919   }
920
921   /* Axes */
922   if (num_rels || num_abs)
923   {
924     m_deviceCaps |= LI_CAPS_AXES;
925     m_deviceMaxAxis = std::max(num_rels, num_abs) - 1;
926   }
927
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;
937   else
938     m_devicePreferredId = LI_DEVICE_NONE;
939
940   //printf("type: %d\n", m_deviceType);
941   //printf("caps: %d\n", m_deviceCaps);
942   //printf("pref: %d\n", m_devicePreferredId);
943 }
944
945 const std::string& CLinuxInputDevice::GetFileName()
946 {
947   return m_fileName;
948 }
949
950 bool CLinuxInputDevice::IsUnplugged()
951 {
952   return m_bUnplugged;
953 }
954
955 bool CLinuxInputDevices::CheckDevice(const char *device)
956 {
957   int fd;
958
959   // Does the device exists?
960   struct stat buffer;
961   if (stat(device, &buffer) != 0)
962     return false;
963
964   /* Check if we are able to open the device */
965   fd = open(device, O_RDWR);
966   if (fd < 0)
967     return false;
968
969 #ifndef TARGET_DVBBOX // oskwon
970   if (ioctl(fd, EVIOCGRAB, 1) && errno != EINVAL)
971   {
972     close(fd);
973     return false;
974   }
975
976   ioctl(fd, EVIOCGRAB, 0);
977 #endif /*TARGET_DVBBOX*/
978
979   close(fd);
980
981   return true;
982 }
983
984 /* exported symbols */
985
986 /*
987  * Return the number of available devices.
988  * Called once during initialization of DirectFB.
989  */
990 void CLinuxInputDevices::InitAvailable()
991 {
992   CSingleLock lock(m_devicesListLock);
993
994   /* Close any devices that may have been initialized previously */
995   for (size_t i = 0; i < m_devices.size(); i++)
996   {
997     delete m_devices[i];
998   }
999   m_devices.clear();
1000
1001   int deviceId = 0;
1002
1003   /* No devices specified. Try to guess some. */
1004   for (int i = 0; i < MAX_LINUX_INPUT_DEVICES; i++)
1005   {
1006     char buf[32];
1007
1008     snprintf(buf, 32, "/dev/input/event%d", i);
1009     if (CheckDevice(buf))
1010     {
1011       CLog::Log(LOGINFO, "Found input device %s", buf);
1012       m_devices.push_back(new CLinuxInputDevice(buf, deviceId));
1013       ++deviceId;
1014     }
1015   }
1016 }
1017
1018 /*
1019  * Check for hot plugged devices.
1020  */
1021 void CLinuxInputDevices::CheckHotplugged()
1022 {
1023   CSingleLock lock(m_devicesListLock);
1024
1025   int deviceId = m_devices.size();
1026
1027   /* No devices specified. Try to guess some. */
1028   for (int i = 0; i < MAX_LINUX_INPUT_DEVICES; i++)
1029   {
1030     char buf[32];
1031     bool ispresent = false;
1032
1033     snprintf(buf, 32, "/dev/input/event%d", i);
1034
1035     for (size_t j = 0; j < m_devices.size(); j++)
1036     {
1037       if (m_devices[j]->GetFileName().compare(buf) == 0)
1038       {
1039         ispresent = true;
1040         break;
1041       }
1042     }
1043
1044     if (!ispresent && CheckDevice(buf))
1045     {
1046       CLog::Log(LOGINFO, "Found input device %s", buf);
1047       m_devices.push_back(new CLinuxInputDevice(buf, deviceId));
1048       ++deviceId;
1049     }
1050   }
1051 }
1052
1053 /*
1054  * Open the device, fill out information about it,
1055  * allocate and fill private data, start input thread.
1056  */
1057 bool CLinuxInputDevice::Open()
1058 {
1059   int fd, ret;
1060   unsigned long ledbit[NBITS(LED_CNT)];
1061
1062   /* open device */
1063   fd = open(m_fileName.c_str(), O_RDWR | O_NONBLOCK);
1064   if (fd < 0)
1065   {
1066     CLog::Log(LOGERROR, "CLinuxInputDevice: could not open device: %s\n", m_fileName.c_str());
1067     return false;
1068   }
1069
1070 #ifndef TARGET_DVBBOX // oskwon
1071   /* grab device */
1072   ret = ioctl(fd, EVIOCGRAB, 1);
1073   if (ret && errno != EINVAL)
1074   {
1075     CLog::Log(LOGERROR, "CLinuxInputDevice: could not grab device: %s\n", m_fileName.c_str());
1076     close(fd);
1077     return false;
1078   }
1079 #endif /*TARGET_DVBBOX*/
1080
1081   // Set the socket to non-blocking
1082   int opts = 0;
1083   if ((opts = fcntl(fd, F_GETFL)) < 0)
1084   {
1085     CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_GETFL) failed: %s", __FUNCTION__ , strerror(errno));
1086     close(fd);
1087     return false;
1088   }
1089
1090   opts = (opts | O_NONBLOCK);
1091   if (fcntl(fd, F_SETFL, opts) < 0)
1092   {
1093     CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_SETFL) failed: %s", __FUNCTION__, strerror(errno));
1094     close(fd);
1095     return false;
1096   }
1097
1098   /* fill device info structure */
1099   GetInfo(fd);
1100
1101   if (m_deviceType & LI_DEVICE_KEYBOARD)
1102     SetupKeyboardAutoRepeat(fd);
1103
1104   m_fd = fd;
1105   m_vt_fd = -1;
1106
1107   if (m_deviceMinKeyCode >= 0 && m_deviceMaxKeyCode >= m_deviceMinKeyCode)
1108   {
1109     if (m_vt_fd < 0)
1110       m_vt_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
1111  
1112     if (m_vt_fd < 0)
1113       m_vt_fd = open("/dev/tty1", O_RDWR | O_NOCTTY);
1114
1115     if (m_vt_fd < 0)
1116       CLog::Log(LOGWARNING, "no keymap support (requires /dev/tty0 - CONFIG_VT)");
1117   }
1118
1119   /* check if the device has LEDs */
1120   ret = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit);
1121   if (ret < 0)
1122           CLog::Log(LOGWARNING, "DirectFB/linux_input: could not get LED bits" );
1123   else
1124     m_hasLeds = test_bit( LED_SCROLLL, ledbit ) || test_bit( LED_NUML, ledbit )
1125         || test_bit( LED_CAPSL, ledbit );
1126
1127   if (m_hasLeds)
1128   {
1129     /* get LED state */
1130     ret = ioctl(fd, EVIOCGLED(sizeof(m_ledState)), m_ledState);
1131     if (ret < 0)
1132     {
1133       CLog::Log(LOGERROR, "DirectFB/linux_input: could not get LED state");
1134       goto driver_open_device_error;
1135     }
1136
1137     /* turn off LEDs */
1138     SetLed(LED_SCROLLL, 0);
1139     SetLed(LED_NUML, 0);
1140     SetLed(LED_CAPSL, 0);
1141   }
1142
1143   return true;
1144
1145 driver_open_device_error:
1146 #ifndef TARGET_DVBBOX // oskwon
1147   ioctl(fd, EVIOCGRAB, 0);
1148 #endif /*TARGET_DVBBOX*/
1149   if (m_vt_fd >= 0)
1150   {
1151     close(m_vt_fd);
1152     m_vt_fd = -1;
1153   }
1154   close(fd);
1155   m_fd = -1;
1156
1157   return false;
1158 }
1159
1160 /*
1161  * Fetch one entry from the kernel keymap.
1162  */
1163 bool CLinuxInputDevice::GetKeymapEntry(KeymapEntry& entry)
1164 {
1165   int code = entry.code;
1166   unsigned short value;
1167   //DFBInputDeviceKeyIdentifier identifier;
1168
1169   if (m_vt_fd < 0)
1170     return false;
1171
1172   // to support '+'  and '/' with Boxee's remote control we do something ugly like this for now
1173   if (KVAL(code) == 98)
1174   {
1175     code = K(KTYP(code),53);
1176   }
1177
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);
1181
1182   /* write base level symbol to entry */
1183   entry.base = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_BASE);
1184
1185   /* fetch the shifted base level */
1186   value = KeyboardGetSymbol(KeyboardReadValue(K_SHIFTTAB, entry.code));
1187   //printf("shift=%d\n", value);
1188
1189   /* write shifted base level symbol to entry */
1190   entry.shift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_SHIFT);
1191
1192   // to support '+'  and '/' with Boxee's remote control we could do ugly something like this for now
1193   if (KVAL(code) == 78)
1194   {
1195     //code = K(KTYP(code),13);
1196     //entry.code = K(KTYP(code),13);
1197     entry.base = K(KTYP(code),43);
1198   }
1199
1200   /* fetch the alternative level */
1201   value = KeyboardGetSymbol(KeyboardReadValue(K_ALTTAB, entry.code));
1202   //printf("alt=%d\n", value);
1203
1204   /* write alternative level symbol to entry */
1205   entry.alt = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT);
1206
1207   /* fetch the shifted alternative level */
1208   value = KeyboardGetSymbol(KeyboardReadValue(K_ALTSHIFTTAB, entry.code));
1209   //printf("altshift=%d\n", value);
1210
1211   /* write shifted alternative level symbol to entry */
1212   entry.altShift = value; //KeyboardGetSymbol(code, value, LI_KEYLEVEL_ALT_SHIFT);
1213
1214   return true;
1215 }
1216
1217 /*
1218  * End thread, close device and free private data.
1219  */
1220 void CLinuxInputDevice::Close()
1221 {
1222 #ifndef TARGET_DVBBOX // oskwon
1223   /* release device */
1224   ioctl(m_fd, EVIOCGRAB, 0);
1225 #endif /*TARGET_DVBBOX*/
1226   if (m_vt_fd >= 0)
1227     close(m_vt_fd);
1228
1229   /* close file */
1230   close(m_fd);
1231 }
1232
1233 XBMC_Event CLinuxInputDevices::ReadEvent()
1234 {
1235   if (m_bReInitialize)
1236   {
1237     InitAvailable();
1238     m_bReInitialize = false;
1239   }
1240   else
1241   {
1242     time_t now;
1243     time(&now);
1244
1245     if ((now - m_lastHotplugCheck) >= 10)
1246     {
1247       CheckHotplugged();
1248       m_lastHotplugCheck = now;
1249     }
1250   }
1251
1252   CSingleLock lock(m_devicesListLock);
1253
1254   XBMC_Event event;
1255   event.type = XBMC_NOEVENT;
1256
1257   for (size_t i = 0; i < m_devices.size(); i++)
1258   {
1259     event = m_devices[i]->ReadEvent();
1260     if (event.type != XBMC_NOEVENT)
1261     {
1262       break;
1263     }
1264
1265     if (m_devices[i]->IsUnplugged())
1266     {
1267       m_bReInitialize = true;
1268       break;
1269     }
1270   }
1271
1272   return event;
1273 }
1274
1275 /*
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
1280 */
1281 bool CLinuxInputDevices::IsRemoteLowBattery()
1282 {
1283   bool bLowBattery = !(remoteStatus & 0xF);
1284   return bLowBattery;
1285 }
1286
1287 bool CLinuxInputDevices::IsRemoteNotPaired()
1288 {
1289   bool bRemoteNotPaired = !(remoteStatus & 0x70) || !(remoteStatus & 0x80);
1290   return bRemoteNotPaired;
1291 }
1292
1293 /*
1294 int main()
1295 {
1296   CLinuxInputDevices devices;
1297   devices.InitAvailable();
1298   while (1)
1299   {
1300     XBMC_Event event = devices.ReadEvent();
1301     if (event.type != XBMC_NOEVENT)
1302     {
1303       printf("%d\n", event.type);
1304     }
1305     usleep(1000);
1306   }
1307
1308 }
1309 */
1310 #endif