]> git.mxchange.org Git - flightgear.git/blob - src/Input/FGLinuxEventInput.cxx
Use new SGBucket API in tile-manager
[flightgear.git] / src / Input / FGLinuxEventInput.cxx
1 // FGEventInput.cxx -- handle event driven input devices for the Linux O/S
2 //
3 // Written by Torsten Dreyer, started July 2009.
4 //
5 // Copyright (C) 2009 Torsten Dreyer, Torsten (at) t3r _dot_ de
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #include <cstring>
26 #include <cstdio>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include "FGLinuxEventInput.hxx"
30
31 extern "C" {
32     #include <libudev.h>
33 }
34
35 #include <poll.h>
36 #include <linux/input.h>
37 #include <fcntl.h>
38
39 #include <string.h>
40
41 struct TypeCode {
42   unsigned type;
43   unsigned code;
44
45   inline unsigned long hashCode() const {
46     return (unsigned long)type << 16 | (unsigned long)code;
47   }
48
49   bool operator < ( const TypeCode & other) const {
50     return hashCode() < other.hashCode();
51   }
52 };
53
54 // event to name translation table
55 // events are from include <linux/input.h>
56
57 static struct EventTypes {
58   struct TypeCode typeCode;
59   const char * name;
60 } EVENT_TYPES[] = {
61   { { EV_SYN, SYN_REPORT },     "syn-report" },
62   { { EV_SYN, SYN_CONFIG },     "syn-config" },
63
64   // misc
65   { { EV_KEY, BTN_0 }, "button-0" },
66   { { EV_KEY, BTN_1 }, "button-1" },
67   { { EV_KEY, BTN_2 }, "button-2" },
68   { { EV_KEY, BTN_3 }, "button-3" },
69   { { EV_KEY, BTN_4 }, "button-4" },
70   { { EV_KEY, BTN_5 }, "button-5" },
71   { { EV_KEY, BTN_6 }, "button-6" },
72   { { EV_KEY, BTN_7 }, "button-7" },
73   { { EV_KEY, BTN_8 }, "button-8" },
74   { { EV_KEY, BTN_9 }, "button-9" },
75
76   // mouse
77   { { EV_KEY, BTN_LEFT },    "button-left" },
78   { { EV_KEY, BTN_RIGHT },   "button-right" },
79   { { EV_KEY, BTN_MIDDLE },  "button-middle" },
80   { { EV_KEY, BTN_SIDE },    "button-side" },
81   { { EV_KEY, BTN_EXTRA },   "button-extra" },
82   { { EV_KEY, BTN_FORWARD }, "button-forward" },
83   { { EV_KEY, BTN_BACK },    "button-back" },
84   { { EV_KEY, BTN_TASK },    "button-task" },
85
86   // joystick
87   { { EV_KEY, BTN_TRIGGER }, "button-trigger" },
88   { { EV_KEY, BTN_THUMB },   "button-thumb" },
89   { { EV_KEY, BTN_THUMB2 },  "button-thumb2" },
90   { { EV_KEY, BTN_TOP },     "button-top" },
91   { { EV_KEY, BTN_TOP2 },    "button-top2" },
92   { { EV_KEY, BTN_PINKIE },  "button-pinkie" },
93   { { EV_KEY, BTN_BASE },    "button-base" },
94   { { EV_KEY, BTN_BASE2 },   "button-base2" },
95   { { EV_KEY, BTN_BASE3 },   "button-base3" },
96   { { EV_KEY, BTN_BASE4 },   "button-base4" },
97   { { EV_KEY, BTN_BASE5 },   "button-base5" },
98   { { EV_KEY, BTN_BASE6 },   "button-base6" },
99   { { EV_KEY, BTN_DEAD },    "button-dead" },
100
101   // gamepad
102   { { EV_KEY, BTN_A },      "button-a" },
103   { { EV_KEY, BTN_B },      "button-b" },
104   { { EV_KEY, BTN_C },      "button-c" },
105   { { EV_KEY, BTN_X },      "button-x" },
106   { { EV_KEY, BTN_Y },      "button-y" },
107   { { EV_KEY, BTN_Z },      "button-z" },
108   { { EV_KEY, BTN_TL },     "button-tl" },
109   { { EV_KEY, BTN_TR },     "button-tr" },
110   { { EV_KEY, BTN_TL2 },    "button-tl2" },
111   { { EV_KEY, BTN_TR2 },    "button-tr2" },
112   { { EV_KEY, BTN_SELECT }, "button-select" },
113   { { EV_KEY, BTN_START },  "button-start" },
114   { { EV_KEY, BTN_MODE },   "button-mode" },
115   { { EV_KEY, BTN_THUMBL }, "button-thumbl" },
116   { { EV_KEY, BTN_THUMBR }, "button-thumbr" },
117
118   // digitizer
119   { { EV_KEY, BTN_TOOL_PEN },       "button-pen" },
120   { { EV_KEY, BTN_TOOL_RUBBER },    "button-rubber" },
121   { { EV_KEY, BTN_TOOL_BRUSH },     "button-brush" },
122   { { EV_KEY, BTN_TOOL_PENCIL },    "button-pencil" },
123   { { EV_KEY, BTN_TOOL_AIRBRUSH },  "button-airbrush" },
124   { { EV_KEY, BTN_TOOL_FINGER },    "button-finger" },
125   { { EV_KEY, BTN_TOOL_MOUSE },     "button-mouse" },
126   { { EV_KEY, BTN_TOOL_LENS },      "button-lens" },
127   { { EV_KEY, BTN_TOUCH },          "button-touch" },
128   { { EV_KEY, BTN_STYLUS },         "button-stylus" },
129   { { EV_KEY, BTN_STYLUS2 },        "button-stylus2" },
130   { { EV_KEY, BTN_TOOL_DOUBLETAP }, "button-doubletap" },
131   { { EV_KEY, BTN_TOOL_TRIPLETAP }, "button-trippletap" },
132
133   { { EV_KEY, BTN_WHEEL },          "button-wheel" },
134   { { EV_KEY, BTN_GEAR_DOWN },      "button-gear-down" },
135   { { EV_KEY, BTN_GEAR_UP },        "button-gear-up" },
136
137   { { EV_REL, REL_X },     "rel-x-translate" },
138   { { EV_REL, REL_Y},      "rel-y-translate" },
139   { { EV_REL, REL_Z},      "rel-z-translate" },
140   { { EV_REL, REL_RX},     "rel-x-rotate" },
141   { { EV_REL, REL_RY},     "rel-y-rotate" },
142   { { EV_REL, REL_RZ},     "rel-z-rotate" },
143   { { EV_REL, REL_HWHEEL}, "rel-hwheel" },
144   { { EV_REL, REL_DIAL},   "rel-dial" },
145   { { EV_REL, REL_WHEEL},  "rel-wheel" },
146   { { EV_REL, REL_MISC},   "rel-misc" },
147
148   { { EV_ABS, ABS_X },          "abs-x-translate" },
149   { { EV_ABS, ABS_Y },          "abs-y-translate" },
150   { { EV_ABS, ABS_Z },          "abs-z-translate" },
151   { { EV_ABS, ABS_RX },         "abs-x-rotate" },
152   { { EV_ABS, ABS_RY },         "abs-y-rotate" },
153   { { EV_ABS, ABS_RZ },         "abs-z-rotate" },
154   { { EV_ABS, ABS_THROTTLE },   "abs-throttle" },
155   { { EV_ABS, ABS_RUDDER },     "abs-rudder" },
156   { { EV_ABS, ABS_WHEEL },      "abs-wheel" },
157   { { EV_ABS, ABS_GAS },        "abs-gas" },
158   { { EV_ABS, ABS_BRAKE },      "abs-brake" },
159   { { EV_ABS, ABS_HAT0X },      "abs-hat0-x" },
160   { { EV_ABS, ABS_HAT0Y },      "abs-hat0-y" },
161   { { EV_ABS, ABS_HAT1X },      "abs-hat1-x" },
162   { { EV_ABS, ABS_HAT1Y },      "abs-hat1-y" },
163   { { EV_ABS, ABS_HAT2X },      "abs-hat2-x" },
164   { { EV_ABS, ABS_HAT2Y },      "abs-hat2-y" },
165   { { EV_ABS, ABS_HAT3X },      "abs-hat3-x" },
166   { { EV_ABS, ABS_HAT3Y },      "abs-hat3-y" },
167   { { EV_ABS, ABS_PRESSURE },   "abs-pressure" },
168   { { EV_ABS, ABS_DISTANCE },   "abs-distance" },
169   { { EV_ABS, ABS_TILT_X },     "abs-tilt-x" },
170   { { EV_ABS, ABS_TILT_Y },     "abs-tilt-y" },
171   { { EV_ABS, ABS_TOOL_WIDTH }, "abs-toold-width" },
172   { { EV_ABS, ABS_VOLUME },     "abs-volume" },
173   { { EV_ABS, ABS_MISC },       "abs-misc" },
174
175   { { EV_MSC,  MSC_SERIAL },    "misc-serial" },
176   { { EV_MSC,  MSC_PULSELED },  "misc-pulseled" },
177   { { EV_MSC,  MSC_GESTURE },   "misc-gesture" },
178   { { EV_MSC,  MSC_RAW },       "misc-raw" },
179   { { EV_MSC,  MSC_SCAN },      "misc-scan" },
180
181   // switch
182   { { EV_SW, SW_LID },               "switch-lid" },
183   { { EV_SW, SW_TABLET_MODE },       "switch-tablet-mode" },
184   { { EV_SW, SW_HEADPHONE_INSERT },  "switch-headphone-insert" },
185 #ifdef SW_RFKILL_ALL 
186   { { EV_SW, SW_RFKILL_ALL },        "switch-rfkill" },
187 #endif
188 #ifdef SW_MICROPHONE_INSERT 
189   { { EV_SW, SW_MICROPHONE_INSERT }, "switch-microphone-insert" },
190 #endif
191 #ifdef SW_DOCK
192   { { EV_SW, SW_DOCK },              "switch-dock" },
193 #endif
194
195   { { EV_LED, LED_NUML},     "led-numlock" },
196   { { EV_LED, LED_CAPSL},    "led-capslock" },
197   { { EV_LED, LED_SCROLLL},  "led-scrolllock" },
198   { { EV_LED, LED_COMPOSE},  "led-compose" },
199   { { EV_LED, LED_KANA},     "led-kana" },
200   { { EV_LED, LED_SLEEP},    "led-sleep" },
201   { { EV_LED, LED_SUSPEND},  "led-suspend" },
202   { { EV_LED, LED_MUTE},     "led-mute" },
203   { { EV_LED, LED_MISC},     "led-misc" },
204   { { EV_LED, LED_MAIL},     "led-mail" },
205   { { EV_LED, LED_CHARGING}, "led-charging" }
206
207 };
208
209 static struct enbet {
210   unsigned type;
211   const char * name;
212 } EVENT_NAMES_BY_EVENT_TYPE[] = {
213   { EV_SYN, "syn" },
214   { EV_KEY, "button" },
215   { EV_REL, "rel" },
216   { EV_ABS, "abs" },
217   { EV_MSC, "msc" },
218   { EV_SW, "button" },
219   { EV_LED, "led" },
220   { EV_SND, "snd" },
221   { EV_REP, "rep" },
222   { EV_FF, "ff" },
223   { EV_PWR, "pwr" },
224   { EV_FF_STATUS, "ff-status" }
225 };
226
227
228 class EventNameByEventType : public std::map<unsigned,const char*> {
229 public:
230   EventNameByEventType() {
231     for( unsigned i = 0; i < sizeof(EVENT_NAMES_BY_EVENT_TYPE)/sizeof(EVENT_NAMES_BY_EVENT_TYPE[0]); i++ )
232       (*this)[EVENT_NAMES_BY_EVENT_TYPE[i].type] = EVENT_NAMES_BY_EVENT_TYPE[i].name;
233   }
234 };
235 static EventNameByEventType EVENT_NAME_BY_EVENT_TYPE;
236
237 class EventNameByType : public std::map<TypeCode,const char*> {
238 public:
239   EventNameByType() {
240     for( unsigned i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ )
241       (*this)[EVENT_TYPES[i].typeCode] = EVENT_TYPES[i].name;
242   }
243 };
244 static EventNameByType EVENT_NAME_BY_TYPE;
245
246
247 struct ltstr {
248   bool operator()(const char * s1, const char * s2 ) const {
249     return std::string(s1).compare( s2 ) < 0;
250   }
251 };
252
253 class EventTypeByName : public std::map<const char *,TypeCode,ltstr> {
254 public:
255   EventTypeByName() {
256     for( unsigned i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ )
257       (*this)[EVENT_TYPES[i].name] = EVENT_TYPES[i].typeCode;
258   }
259 };
260 static EventTypeByName EVENT_TYPE_BY_NAME;
261
262
263 FGLinuxInputDevice::FGLinuxInputDevice( std::string aName, std::string aDevname ) :
264   FGInputDevice(aName),
265   devname( aDevname ),
266   fd(-1)
267 {
268 }
269
270 FGLinuxInputDevice::~FGLinuxInputDevice()
271 {
272   try {
273     Close();
274   } 
275   catch(...) {
276   }
277 }
278
279 FGLinuxInputDevice::FGLinuxInputDevice() :
280   fd(-1)
281 {
282 }
283
284 static inline bool bitSet( unsigned char * buf, unsigned bit )
285 {
286   return (buf[bit/sizeof(unsigned char)/8] >> (bit%(sizeof(unsigned char)*8))) & 1;
287 }
288
289 void FGLinuxInputDevice::Open()
290 {
291   if( fd != -1 ) return;
292   if( (fd = ::open( devname.c_str(), O_RDWR )) == -1 ) { 
293     throw std::exception();
294   }
295
296   if( GetGrab() && ioctl( fd, EVIOCGRAB, 2 ) == -1 ) {
297     SG_LOG( SG_INPUT, SG_WARN, "Can't grab " << devname << " for exclusive access" );
298   }
299
300   {
301     unsigned char buf[ABS_CNT/sizeof(unsigned char)/8];
302     // get axes maximums
303     if( ioctl( fd, EVIOCGBIT(EV_ABS,ABS_MAX), buf ) == -1 ) {
304       SG_LOG( SG_INPUT, SG_WARN, "Can't get abs-axes for " << devname );
305     } else {
306       for( unsigned i = 0; i < ABS_MAX; i++ ) {
307         if( bitSet( buf, i ) ) {
308           struct input_absinfo ai;
309           if( ioctl(fd, EVIOCGABS(i), &ai) == -1 ) {
310             SG_LOG( SG_INPUT, SG_WARN, "Can't get abs-axes maximums for " << devname );
311             continue;
312           }
313           absinfo[i] = ai;
314 /*
315           SG_LOG( SG_INPUT, SG_INFO, "Axis #" << i <<
316             ": value=" << ai.value << 
317             ": minimum=" << ai.minimum << 
318             ": maximum=" << ai.maximum << 
319             ": fuzz=" << ai.fuzz << 
320             ": flat=" << ai.flat << 
321             ": resolution=" << ai.resolution );
322 */
323
324           // kick an initial event
325           struct input_event event;
326           event.type = EV_ABS;
327           event.code = i;
328           event.value = ai.value;
329           FGLinuxEventData eventData( event, 0, 0 );
330           eventData.value = Normalize( event );
331           HandleEvent(eventData);
332         }
333       }
334     }
335   }
336   {
337     unsigned char mask[KEY_CNT/sizeof(unsigned char)/8];
338     unsigned char flag[KEY_CNT/sizeof(unsigned char)/8];
339     memset(mask,0,sizeof(mask));
340     memset(flag,0,sizeof(flag));
341     if( ioctl( fd, EVIOCGKEY(sizeof(flag)), flag ) == -1 ||
342         ioctl( fd, EVIOCGBIT(EV_KEY, sizeof(mask)), mask ) == -1 ) {
343       SG_LOG( SG_INPUT, SG_WARN, "Can't get keys for " << devname );
344     } else {
345       for( unsigned i = 0; i < KEY_MAX; i++ ) {
346         if( bitSet( mask, i ) ) {
347           struct input_event event;
348           event.type = EV_KEY;
349           event.code = i;
350           event.value = bitSet(flag,i);
351           FGLinuxEventData eventData( event, 0, 0 );
352           HandleEvent(eventData);
353         }
354       }
355     }
356   }
357   {
358     unsigned char buf[SW_CNT/sizeof(unsigned char)/8];
359     if( ioctl( fd, EVIOCGSW(sizeof(buf)), buf ) == -1 ) {
360       SG_LOG( SG_INPUT, SG_WARN, "Can't get switches for " << devname );
361     } else {
362       for( unsigned i = 0; i < SW_MAX; i++ ) {
363         if( bitSet( buf, i ) ) {
364           struct input_event event;
365           event.type = EV_SW;
366           event.code = i;
367           event.value = 1;
368           FGLinuxEventData eventData( event, 0, 0 );
369           HandleEvent(eventData);
370         }
371       }
372     }
373   }
374 }
375
376 double FGLinuxInputDevice::Normalize( struct input_event & event ) 
377 {
378   if( absinfo.count(event.code) > 0 ) {
379      const struct input_absinfo & ai = absinfo[(unsigned int)event.code];
380      if( ai.maximum == ai.minimum )
381        return 0.0;
382      return ((double)event.value-(double)ai.minimum)/((double)ai.maximum-(double)ai.minimum);
383   } else {
384     return (double)event.value;
385   }
386 }
387
388 void FGLinuxInputDevice::Close()
389 {
390   if( fd != -1 ) {
391     if( GetGrab() && ioctl( fd, EVIOCGRAB, 0 ) != 0 ) {
392       SG_LOG( SG_INPUT, SG_WARN, "Can't ungrab " << devname );
393     }
394     ::close(fd);
395   }
396   fd = -1;
397 }
398
399 void FGLinuxInputDevice::Send( const char * eventName, double value )
400 {
401   if( EVENT_TYPE_BY_NAME.count( eventName ) <= 0 ) {
402     SG_LOG( SG_INPUT, SG_ALERT, "Can't send unknown event " << eventName );
403     return;
404   }
405
406   TypeCode & typeCode = EVENT_TYPE_BY_NAME[ eventName ];
407
408   if( fd == -1 )
409     return;
410
411   input_event evt;
412   evt.type=typeCode.type;
413   evt.code = typeCode.code;
414   evt.value = (long)value;
415   evt.time.tv_sec = 0;
416   evt.time.tv_usec = 0;
417   size_t bytes_written = write(fd, &evt, sizeof(evt));
418
419   if( bytes_written == sizeof(evt) )
420     SG_LOG( SG_INPUT,
421             SG_DEBUG,
422             "Written event " << eventName << " as type=" << evt.type
423                         << ", code=" << evt.code
424                         << " value=" << evt.value );
425   else
426     SG_LOG( SG_INPUT,
427             SG_WARN,
428             "Failed to write event: written = " << bytes_written );
429 }
430
431 static char ugly_buffer[128];
432 const char * FGLinuxInputDevice::TranslateEventName( FGEventData & eventData ) 
433 {
434   FGLinuxEventData & linuxEventData = (FGLinuxEventData&)eventData;
435   TypeCode typeCode;
436   typeCode.type = linuxEventData.type;
437   typeCode.code = linuxEventData.code;
438   if( EVENT_NAME_BY_TYPE.count(typeCode) == 0 ) {
439     // event not known in translation tables
440     if( EVENT_NAME_BY_EVENT_TYPE.count(linuxEventData.type) == 0 ) {
441       // event type not known in translation tables
442       sprintf( ugly_buffer, "unknown-%u-%u", (unsigned)linuxEventData.type, (unsigned)linuxEventData.code );
443       return ugly_buffer;
444     }
445     sprintf( ugly_buffer, "%s-%u", EVENT_NAME_BY_EVENT_TYPE[linuxEventData.type], (unsigned)linuxEventData.code );
446     return ugly_buffer;
447   }
448
449   return EVENT_NAME_BY_TYPE[typeCode];
450 }
451
452 void FGLinuxInputDevice::SetDevname( const std::string & name )
453 {
454   this->devname = name; 
455 }
456
457 FGLinuxEventInput::FGLinuxEventInput()
458 {
459 }
460
461 FGLinuxEventInput::~FGLinuxEventInput()
462 {
463 }
464
465 void FGLinuxEventInput::postinit()
466 {
467   FGEventInput::postinit();
468
469   struct udev * udev = udev_new();
470
471   struct udev_enumerate *enumerate = udev_enumerate_new(udev);
472   udev_enumerate_add_match_subsystem(enumerate, "input");
473   udev_enumerate_scan_devices(enumerate);
474   struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
475   struct udev_list_entry *dev_list_entry;
476
477   udev_list_entry_foreach(dev_list_entry, devices) {
478     const char * path = udev_list_entry_get_name(dev_list_entry);
479     struct udev_device *dev = udev_device_new_from_syspath(udev, path);
480     const char * node = udev_device_get_devnode(dev);
481  
482     dev = udev_device_get_parent( dev );
483     const char * name = udev_device_get_sysattr_value(dev,"name");
484
485     SG_LOG(SG_INPUT,SG_DEBUG, "name=" << (name?name:"<null>") << ", node=" << (node?node:"<null>"));
486     if( name && node )
487       AddDevice( new FGLinuxInputDevice(name, node) );
488
489     udev_device_unref(dev);
490   }
491
492   udev_unref(udev);
493
494 }
495
496 void FGLinuxEventInput::update( double dt )
497 {
498   FGEventInput::update( dt );
499   // index the input devices by the associated fd and prepare
500   // the pollfd array by filling in the file descriptor
501   struct pollfd fds[input_devices.size()];
502   std::map<int,FGLinuxInputDevice*> devicesByFd;
503   std::map<int,FGInputDevice*>::const_iterator it;
504   int i;
505   for( i=0, it = input_devices.begin(); it != input_devices.end(); ++it, i++ ) {
506     FGInputDevice* p = (*it).second;
507     int fd = ((FGLinuxInputDevice*)p)->GetFd();
508     fds[i].fd = fd;
509     fds[i].events = POLLIN;
510     devicesByFd[fd] = (FGLinuxInputDevice*)p;
511   }
512
513   int modifiers = fgGetKeyModifiers();
514   // poll all devices until no more events are in the queue
515   // do no more than maxpolls in a single loop to prevent locking
516   int maxpolls = 100;
517   while( maxpolls-- > 0 && ::poll( fds, i, 0 ) > 0 ) {
518     for( unsigned i = 0; i < sizeof(fds)/sizeof(fds[0]); i++ ) {
519       if( fds[i].revents & POLLIN ) {
520
521         // if this device reports data ready, it should be a input_event struct
522         struct input_event event;
523
524         if( read( fds[i].fd, &event, sizeof(event) ) != sizeof(event) )
525           continue;
526
527         FGLinuxEventData eventData( event, dt, modifiers );
528
529         if( event.type == EV_ABS )
530           eventData.value = devicesByFd[fds[i].fd]->Normalize( event );
531
532         // let the FGInputDevice handle the data
533         devicesByFd[fds[i].fd]->HandleEvent( eventData );
534       }
535     }
536   }
537 }
538