37#include <linux/input.h>
46#ifndef input_event_sec
47#define input_event_sec time.tv_sec
48#define input_event_usec time.tv_usec
56 return (
unsigned long)
type << 16 | (
unsigned long)
code;
71 { { EV_SYN, SYN_REPORT },
"syn-report" },
72 { { EV_SYN, SYN_CONFIG },
"syn-config" },
75 { { EV_KEY, BTN_0 },
"button-0" },
76 { { EV_KEY, BTN_1 },
"button-1" },
77 { { EV_KEY, BTN_2 },
"button-2" },
78 { { EV_KEY, BTN_3 },
"button-3" },
79 { { EV_KEY, BTN_4 },
"button-4" },
80 { { EV_KEY, BTN_5 },
"button-5" },
81 { { EV_KEY, BTN_6 },
"button-6" },
82 { { EV_KEY, BTN_7 },
"button-7" },
83 { { EV_KEY, BTN_8 },
"button-8" },
84 { { EV_KEY, BTN_9 },
"button-9" },
87 { { EV_KEY, BTN_LEFT },
"button-left" },
88 { { EV_KEY, BTN_RIGHT },
"button-right" },
89 { { EV_KEY, BTN_MIDDLE },
"button-middle" },
90 { { EV_KEY, BTN_SIDE },
"button-side" },
91 { { EV_KEY, BTN_EXTRA },
"button-extra" },
92 { { EV_KEY, BTN_FORWARD },
"button-forward" },
93 { { EV_KEY, BTN_BACK },
"button-back" },
94 { { EV_KEY, BTN_TASK },
"button-task" },
97 { { EV_KEY, BTN_TRIGGER },
"button-trigger" },
98 { { EV_KEY, BTN_THUMB },
"button-thumb" },
99 { { EV_KEY, BTN_THUMB2 },
"button-thumb2" },
100 { { EV_KEY, BTN_TOP },
"button-top" },
101 { { EV_KEY, BTN_TOP2 },
"button-top2" },
102 { { EV_KEY, BTN_PINKIE },
"button-pinkie" },
103 { { EV_KEY, BTN_BASE },
"button-base" },
104 { { EV_KEY, BTN_BASE2 },
"button-base2" },
105 { { EV_KEY, BTN_BASE3 },
"button-base3" },
106 { { EV_KEY, BTN_BASE4 },
"button-base4" },
107 { { EV_KEY, BTN_BASE5 },
"button-base5" },
108 { { EV_KEY, BTN_BASE6 },
"button-base6" },
109 { { EV_KEY, BTN_DEAD },
"button-dead" },
112 { { EV_KEY, BTN_A },
"button-a" },
113 { { EV_KEY, BTN_B },
"button-b" },
114 { { EV_KEY, BTN_C },
"button-c" },
115 { { EV_KEY, BTN_X },
"button-x" },
116 { { EV_KEY, BTN_Y },
"button-y" },
117 { { EV_KEY, BTN_Z },
"button-z" },
118 { { EV_KEY, BTN_TL },
"button-tl" },
119 { { EV_KEY, BTN_TR },
"button-tr" },
120 { { EV_KEY, BTN_TL2 },
"button-tl2" },
121 { { EV_KEY, BTN_TR2 },
"button-tr2" },
122 { { EV_KEY, BTN_SELECT },
"button-select" },
123 { { EV_KEY, BTN_START },
"button-start" },
124 { { EV_KEY, BTN_MODE },
"button-mode" },
125 { { EV_KEY, BTN_THUMBL },
"button-thumbl" },
126 { { EV_KEY, BTN_THUMBR },
"button-thumbr" },
129 { { EV_KEY, BTN_TOOL_PEN },
"button-pen" },
130 { { EV_KEY, BTN_TOOL_RUBBER },
"button-rubber" },
131 { { EV_KEY, BTN_TOOL_BRUSH },
"button-brush" },
132 { { EV_KEY, BTN_TOOL_PENCIL },
"button-pencil" },
133 { { EV_KEY, BTN_TOOL_AIRBRUSH },
"button-airbrush" },
134 { { EV_KEY, BTN_TOOL_FINGER },
"button-finger" },
135 { { EV_KEY, BTN_TOOL_MOUSE },
"button-mouse" },
136 { { EV_KEY, BTN_TOOL_LENS },
"button-lens" },
137 { { EV_KEY, BTN_TOUCH },
"button-touch" },
138 { { EV_KEY, BTN_STYLUS },
"button-stylus" },
139 { { EV_KEY, BTN_STYLUS2 },
"button-stylus2" },
140 { { EV_KEY, BTN_TOOL_DOUBLETAP },
"button-doubletap" },
141 { { EV_KEY, BTN_TOOL_TRIPLETAP },
"button-trippletap" },
143 { { EV_KEY, BTN_WHEEL },
"button-wheel" },
144 { { EV_KEY, BTN_GEAR_DOWN },
"button-gear-down" },
145 { { EV_KEY, BTN_GEAR_UP },
"button-gear-up" },
147 { { EV_REL, REL_X },
"rel-x-translate" },
148 { { EV_REL, REL_Y},
"rel-y-translate" },
149 { { EV_REL, REL_Z},
"rel-z-translate" },
150 { { EV_REL, REL_RX},
"rel-x-rotate" },
151 { { EV_REL, REL_RY},
"rel-y-rotate" },
152 { { EV_REL, REL_RZ},
"rel-z-rotate" },
153 { { EV_REL, REL_HWHEEL},
"rel-hwheel" },
154 { { EV_REL, REL_DIAL},
"rel-dial" },
155 { { EV_REL, REL_WHEEL},
"rel-wheel" },
156 { { EV_REL, REL_MISC},
"rel-misc" },
158 { { EV_ABS, ABS_X },
"abs-x-translate" },
159 { { EV_ABS, ABS_Y },
"abs-y-translate" },
160 { { EV_ABS, ABS_Z },
"abs-z-translate" },
161 { { EV_ABS, ABS_RX },
"abs-x-rotate" },
162 { { EV_ABS, ABS_RY },
"abs-y-rotate" },
163 { { EV_ABS, ABS_RZ },
"abs-z-rotate" },
164 { { EV_ABS, ABS_THROTTLE },
"abs-throttle" },
165 { { EV_ABS, ABS_RUDDER },
"abs-rudder" },
166 { { EV_ABS, ABS_WHEEL },
"abs-wheel" },
167 { { EV_ABS, ABS_GAS },
"abs-gas" },
168 { { EV_ABS, ABS_BRAKE },
"abs-brake" },
169 { { EV_ABS, ABS_HAT0X },
"abs-hat0-x" },
170 { { EV_ABS, ABS_HAT0Y },
"abs-hat0-y" },
171 { { EV_ABS, ABS_HAT1X },
"abs-hat1-x" },
172 { { EV_ABS, ABS_HAT1Y },
"abs-hat1-y" },
173 { { EV_ABS, ABS_HAT2X },
"abs-hat2-x" },
174 { { EV_ABS, ABS_HAT2Y },
"abs-hat2-y" },
175 { { EV_ABS, ABS_HAT3X },
"abs-hat3-x" },
176 { { EV_ABS, ABS_HAT3Y },
"abs-hat3-y" },
177 { { EV_ABS, ABS_PRESSURE },
"abs-pressure" },
178 { { EV_ABS, ABS_DISTANCE },
"abs-distance" },
179 { { EV_ABS, ABS_TILT_X },
"abs-tilt-x" },
180 { { EV_ABS, ABS_TILT_Y },
"abs-tilt-y" },
181 { { EV_ABS, ABS_TOOL_WIDTH },
"abs-toold-width" },
182 { { EV_ABS, ABS_VOLUME },
"abs-volume" },
183 { { EV_ABS, ABS_MISC },
"abs-misc" },
185 { { EV_MSC, MSC_SERIAL },
"misc-serial" },
186 { { EV_MSC, MSC_PULSELED },
"misc-pulseled" },
187 { { EV_MSC, MSC_GESTURE },
"misc-gesture" },
188 { { EV_MSC, MSC_RAW },
"misc-raw" },
189 { { EV_MSC, MSC_SCAN },
"misc-scan" },
192 { { EV_SW, SW_LID },
"switch-lid" },
193 { { EV_SW, SW_TABLET_MODE },
"switch-tablet-mode" },
194 { { EV_SW, SW_HEADPHONE_INSERT },
"switch-headphone-insert" },
196 { { EV_SW, SW_RFKILL_ALL },
"switch-rfkill" },
198#ifdef SW_MICROPHONE_INSERT
199 { { EV_SW, SW_MICROPHONE_INSERT },
"switch-microphone-insert" },
202 { { EV_SW, SW_DOCK },
"switch-dock" },
205 { { EV_LED, LED_NUML},
"led-numlock" },
206 { { EV_LED, LED_CAPSL},
"led-capslock" },
207 { { EV_LED, LED_SCROLLL},
"led-scrolllock" },
208 { { EV_LED, LED_COMPOSE},
"led-compose" },
209 { { EV_LED, LED_KANA},
"led-kana" },
210 { { EV_LED, LED_SLEEP},
"led-sleep" },
211 { { EV_LED, LED_SUSPEND},
"led-suspend" },
212 { { EV_LED, LED_MUTE},
"led-mute" },
213 { { EV_LED, LED_MISC},
"led-misc" },
214 { { EV_LED, LED_MAIL},
"led-mail" },
215 { { EV_LED, LED_CHARGING},
"led-charging" }
224 { EV_KEY,
"button" },
234 { EV_FF_STATUS,
"ff-status" }
259 return std::string(s1).compare( s2 ) < 0;
280 SG_LOG(SG_INPUT, SG_DEBUG,
"FGLinuxInputDevice " << aName <<
" (s/n: " << aSerial <<
") " << aDevname);
297static inline bool bitSet(
unsigned char * buf,
unsigned bit )
299 return (buf[bit/
sizeof(
unsigned char)/8] >> (bit%(
sizeof(
unsigned char)*8))) & 1;
304 if( fd != -1 )
return true;
305 if( (fd = ::open( devfile.c_str(), O_RDWR )) == -1 ) {
306 SG_LOG( SG_INPUT, SG_ALERT,
"Cannot open '" << devfile
307 <<
"'. errno=" << errno
308 <<
": " << strerror(errno)
314 if(
GetGrab() && ioctl( fd, EVIOCGRAB, 2 ) == -1 ) {
315 SG_LOG( SG_INPUT, SG_WARN,
"Can't grab " << devfile <<
" for exclusive access" );
319 unsigned char buf[ABS_CNT/
sizeof(
unsigned char)/8];
321 if( ioctl( fd, EVIOCGBIT(EV_ABS,ABS_MAX), buf ) == -1 ) {
322 SG_LOG( SG_INPUT, SG_WARN,
"Can't get abs-axes for " << devfile );
324 for(
unsigned i = 0;
i < ABS_MAX;
i++ ) {
326 struct input_absinfo ai;
327 if( ioctl(fd, EVIOCGABS(
i), &ai) == -1 ) {
328 SG_LOG( SG_INPUT, SG_WARN,
"Can't get abs-axes maximums for " << devfile );
343 struct input_event event;
346 event.value = ai.value;
355 unsigned char mask[KEY_CNT/
sizeof(
unsigned char)/8];
356 unsigned char flag[KEY_CNT/
sizeof(
unsigned char)/8];
357 memset(mask,0,
sizeof(mask));
358 memset(flag,0,
sizeof(flag));
359 if( ioctl( fd, EVIOCGKEY(
sizeof(flag)), flag ) == -1 ||
360 ioctl( fd, EVIOCGBIT(EV_KEY,
sizeof(mask)), mask ) == -1 ) {
361 SG_LOG( SG_INPUT, SG_WARN,
"Can't get keys for " << devfile );
363 for(
unsigned i = 0;
i < KEY_MAX;
i++ ) {
365 struct input_event event;
376 unsigned char buf[SW_CNT/
sizeof(
unsigned char)/8];
377 if( ioctl( fd, EVIOCGSW(
sizeof(buf)), buf ) == -1 ) {
378 SG_LOG( SG_INPUT, SG_WARN,
"Can't get switches for " << devfile );
380 for(
unsigned i = 0;
i < SW_MAX;
i++ ) {
382 struct input_event event;
398 if( absinfo.count(event.code) > 0 ) {
399 const struct input_absinfo & ai = absinfo[(
unsigned int)event.code];
400 if( ai.maximum == ai.minimum )
402 return ((
double)event.value-(
double)ai.minimum)/((double)ai.maximum-(double)ai.minimum);
404 return (
double)
event.value;
411 if(
GetGrab() && ioctl( fd, EVIOCGRAB, 0 ) != 0 ) {
412 SG_LOG( SG_INPUT, SG_WARN,
"Can't ungrab " << devfile );
422 SG_LOG( SG_INPUT, SG_DEBUG,
"Can't send unknown event " << eventName );
432 evt.type=typeCode.
type;
433 evt.code = typeCode.
code;
434 evt.value = (long)value;
435 evt.input_event_sec = 0;
436 evt.input_event_usec = 0;
437 size_t bytes_written = write(fd, &evt,
sizeof(evt));
440 if( bytes_written ==
sizeof(evt) )
441 SG_LOG(SG_INPUT, SG_DEBUG,
"Written event " << eventName <<
" as type=" << evt.type
442 <<
", code=" << evt.code <<
" value=" << evt.value);
444 SG_LOG(SG_INPUT, SG_WARN,
"Failed to write event: written = " << bytes_written);
452 typeCode.
type = linuxEventData.
type;
453 typeCode.
code = linuxEventData.
code;
458 sprintf(
ugly_buffer,
"unknown-%u-%u", (
unsigned)linuxEventData.
type, (
unsigned)linuxEventData.
code );
470 this->devfile =
name;
485 struct udev * udev = udev_new();
488 struct udev_enumerate *enumerate = udev_enumerate_new(udev);
489 udev_enumerate_add_match_subsystem(enumerate,
"input");
490 udev_enumerate_scan_devices(enumerate);
492 struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
493 struct udev_list_entry *dev_list_entry;
495 udev_list_entry_foreach(dev_list_entry, devices) {
496 const char * syspath = udev_list_entry_get_name(dev_list_entry);
497 struct udev_device *dev = udev_device_new_from_syspath(udev, syspath);
498 const char * devFile = udev_device_get_devnode(dev);
501 std::string sysname = udev_device_get_sysname(dev);
502 std::string devpath = syspath;
503 devpath.erase(devpath.length() - sysname.length());
505 struct udev_device * parent_dev = udev_device_get_parent( dev );
506 if ( parent_dev != NULL ) {
507 const char *
name = udev_device_get_sysattr_value(parent_dev,
"name");
508 if(
name && devFile ) {
509 const char * serial = udev_device_get_sysattr_value(parent_dev,
"serial");
510 SG_LOG(SG_INPUT,SG_DEBUG,
"FGLinuxEventInput: path=" << devpath <<
": " <<
511 " name=" << (
name?
name:
"<null>") <<
", devFile=" << (devFile?devFile:
"<null>") );
513 std::string serialString = serial ? serial : std::string{};
518 udev_device_unref(dev);
521 udev_enumerate_unref(enumerate);
532 std::map<int,FGLinuxInputDevice*> devicesByFd;
533 std::map<int,FGInputDevice*>::const_iterator it;
539 fds[
i].events = POLLIN;
547 while( maxpolls-- > 0 && ::poll( fds,
i, 0 ) > 0 ) {
548 for(
unsigned i = 0;
i <
sizeof(fds)/
sizeof(fds[0]);
i++ ) {
549 if( fds[
i].revents & POLLIN ) {
552 struct input_event event;
554 if( read( fds[
i].fd, &event,
sizeof(event) ) !=
sizeof(event) )
559 if( event.type == EV_ABS )
560 eventData.
value = devicesByFd[fds[
i].fd]->Normalize( event );
563 devicesByFd[fds[
i].fd]->HandleEvent( eventData );
bool operator<(const TypeCode &other) const
unsigned long hashCode() const
bool operator()(const char *s1, const char *s2) const