2 // Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "gnashconfig.h"
24 #include "InputDevice.h"
26 #include <sys/types.h>
30 #include <linux/input.h>
35 static const char *INPUT_DEVICE
= "/dev/input/event0";
37 // The debug log used by all the gnash libraries.
38 static LogFile
& dbglogfile
= LogFile::getDefaultInstance();
40 EventDevice::EventDevice()
48 // GNASH_REPORT_FUNCTION;
50 memset(&_device_info
, 0, sizeof(struct input_id
));
56 // GNASH_REPORT_FUNCTION;
58 return init(INPUT_DEVICE
, DEFAULT_BUFFER_SIZE
);
62 EventDevice::init(const std::string
&filespec
, size_t /* size */)
64 // GNASH_REPORT_FUNCTION;
66 dbglogfile
.setVerbosity();
70 // Try to open mouse device, be error tolerant (FD is kept open all the time)
71 _fd
= open(filespec
.c_str(), O_RDONLY
| O_NONBLOCK
);
74 log_debug(_("Could not open %s: %s"), filespec
, strerror(errno
));
79 if (fcntl(_fd
, F_SETFL
, fcntl(_fd
, F_GETFL
) | O_NONBLOCK
) < 0) {
80 log_error(_("Could not set non-blocking mode for pointing device: %s"),
90 // Get the version number of the input event subsystem
92 if (ioctl(_fd
, EVIOCGVERSION
, &version
)) {
93 log_error(_("ioctl (EVIOCGVERSION)"));
96 log_debug(_("evdev driver version is %d.%d.%d"),
97 version
>> 16, (version
>> 8) & 0xff,
101 if(ioctl(_fd
, EVIOCGID
, &_device_info
)) {
102 log_error(_("ioctl (EVIOCGID): %s"), strerror(errno
));
105 char name
[256]= "Unknown";
106 if(ioctl(_fd
, EVIOCGNAME(sizeof(name
)), name
) < 0) {
107 log_error(_("ioctl (EVIOCGNAME): %s"), strerror(errno
));
109 log_debug(_("The device on %s says its name is %s"), filespec
, name
);
110 // /dev/mxc_ts is the Touchscreen driver used by the Freescale Babbage board
111 // For some reason it has an empty device info structure other than the name.
112 if (strstr(name
, "mxc_ts") != 0) {
113 _device_info
.bustype
= BUS_HOST
;
115 log_debug(_("vendor %04hx product %04hx version %04hx"),
116 _device_info
.vendor
, _device_info
.product
,
117 _device_info
.version
);
118 switch (_device_info
.bustype
) {
120 log_unimpl(_("is a PCI bus type"));
123 log_unimpl(_("is a PNP bus type"));
126 // FIXME: this probably needs a better way of checking what
127 // device things truly are.
128 log_debug(_("is on a Universal Serial Bus"));
129 // ID 0eef:0001 D-WAV Scientific Co., Ltd eGalax TouchScreen
130 if ((_device_info
.product
== 0) && (_device_info
.vendor
== 0)) {
131 _type
= InputDevice::UMOUSE
;
132 // ID 046d:c001 Logitech, Inc. N48/M-BB48 [FirstMouse Plus]
133 } else if ((_device_info
.product
== 0x0001) && (_device_info
.vendor
== 0x0eef)) {
134 _type
= InputDevice::TOUCHMOUSE
;
135 // ID 046d:c001 Logitech, Inc. N48/M-BB48 [FirstMouse Plus]
136 } else if ((_device_info
.product
== 0xc001) && (_device_info
.vendor
== 0x046d)) {
137 _type
= InputDevice::MOUSE
;
138 // ID 0001:0001 AT Translated Set 2 keyboard
139 } else if ((_device_info
.product
== 0x0001) && (_device_info
.vendor
== 0x0001)) {
140 _type
= InputDevice::MOUSE
;
141 // ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
142 } else if ((_device_info
.product
== 0x2303) && (_device_info
.vendor
== 0x067b)) {
143 _type
= InputDevice::SERIALUSB
;
144 // ID 0471:0815 Philips (or NXP) eHome Infrared Receiver
145 } else if ((_device_info
.product
== 0x0815) && (_device_info
.vendor
== 0x0471)) {
146 _type
= InputDevice::INFRARED
;
150 log_unimpl(_("is a HIL bus type"));
153 log_unimpl(_("is Bluetooth bus type "));
157 log_unimpl(_("is a Virtual bus type "));
161 log_unimpl(_("is an ISA bus type"));
164 // This is for keyboards and mice
165 log_debug(_("is an I8042 bus type"));
166 if (strstr(name
, "keyboard") != 0) {
167 _type
= InputDevice::KEYBOARD
;
169 if (strstr(name
, "Mouse") != 0) {
170 _type
= InputDevice::MOUSE
;
175 log_unimpl(_("is an XTKBD bus type"));
178 log_unimpl(_("is a serial port bus type"));
181 log_unimpl(_("is a gameport bus type"));
184 log_unimpl(_("is a parallel port bus type"));
187 log_unimpl(_("is an Amiga bus type"));
190 log_unimpl(_("is an AOB bus type"));
193 log_unimpl(_("is an i2C bus type "));
196 // log_debug("is Host bus type");
197 // ON the Babbage board, this is the evdev driver version 1.0.0
198 if (strstr(name
, "mxc_ts") != 0) {
199 log_debug(_("Babbage Touchscreen found!"));
200 _type
= InputDevice::TABLET
;
202 if (strstr(name
, "mxckpd") != 0) {
203 log_debug(_("Babbage Power Button found!"));
204 _type
= InputDevice::POWERBUTTON
;
208 log_unimpl(_("is a GSC bus type"));
212 log_unimpl(_("is an Atari bus type"));
216 log_error(_("Unknown bus type %d!"), _device_info
.bustype
);
219 log_debug(_("Event enabled for %s on fd #%d"), _filespec
, _fd
);
222 // FIXME: this has probably been replaced by the uinput device code
223 if (_type
== InputDevice::MOUSE
) {
224 // Get the existing absolute info
225 struct input_absinfo abs
;
226 memset(&abs
, 0, sizeof(struct input_absinfo
));
227 if (ioctl (_fd
, EVIOCGABS(ABS_X
), &abs
) < 0) {
228 log_error(_("ioctl (EVIOCGABS(ABS_X)): %s"), strerror(errno
));
230 #ifdef ABSINFO_RESOLUTION
234 abs
.maximum
= _screen_width
;
235 // Set the scale of the display so the absolute postions
236 // we get from the touchscreen driver are correct.
237 if (ioctl (_fd
, EVIOCSABS(ABS_X
), &abs
) < 0) {
238 log_error(_("ioctl (EVIOCSABS(ABS_X)): %s"), strerror(errno
));
240 if (ioctl(_fd
, EVIOCGABS(ABS_Y
), &abs
) < 0) {
241 log_error(_("ioctl (EVIOCGABS(ABS_Y)): %s"), strerror(errno
));
243 abs
.maximum
= _screen_height
;
244 if (ioctl (_fd
, EVIOCSABS(ABS_Y
), &abs
) < 0) {
245 log_error(_("ioctl (EVIOCSABS(ABS_Y)): %s"), strerror(errno
));
256 // GNASH_REPORT_FUNCTION;
258 bool activity
= false;
261 return false; // no device
264 // Try to read something from the device
265 boost::shared_array
<boost::uint8_t> buf
= readData(sizeof( struct input_event
));
266 // time,type,code,value
272 /// A typical touchscreen event is actually a series of events, one for each
273 /// piece of data. The sequence is terminated by the EV_SYN message. An
274 /// example from evtests looks like this:
275 /// Event: time 697585.633672, type 3 (Absolute), code 0 (X), value 127
276 /// Event: time 697585.633679, type 3 (Absolute), code 1 (Y), value 72
277 /// Event: time 697585.633681, type 3 (Absolute), code 24 (Pressure), value 41
278 /// Event: time 697585.633684, type 1 (Key), code 330 (Touch), value 1
279 /// Event: time 697585.633686, -------------- Report Sync ------------
281 /// Everytime we get the EV_SYN message we add this fully populated event to
282 /// queue of events. As the GUI polls for events, there may be multiple events
283 /// in the queue by the time the main event loop comes around to process the
287 const char *debug
[] = {
306 struct input_event
*ev
= reinterpret_cast<struct input_event
*>(buf
.get());
307 log_debug(_("Type is: %s(%hd), Code is: %hd, Val is: %d"), debug
[ev
->type
],
308 ev
->type
, ev
->type
, ev
->code
, ev
->value
);
314 boost::shared_ptr
<InputDevice::input_data_t
> _newdata(new InputDevice::input_data_t
);
316 std::copy(_input_data
.begin(), _input_data
.end(), _newdata
.begin());
318 _newdata
->pressed
= _input_data
.pressed
;
319 _newdata
->key
= _input_data
.key
;
320 _newdata
->modifier
= _input_data
.modifier
;
321 _newdata
->x
= _input_data
.x
;
322 _newdata
->y
= _input_data
.y
;
323 _newdata
->button
= _input_data
.button
;
324 _newdata
->position
= _input_data
.position
;
325 _newdata
->pressure
= _input_data
.pressure
;
326 _newdata
->volumne
= _input_data
.volumne
;
327 _newdata
->distance
= _input_data
.distance
;
328 _newdata
->rx
= _input_data
.rx
;
329 _newdata
->ry
= _input_data
.ry
;
330 _newdata
->rz
= _input_data
.rz
;
331 _newdata
->throttle
= _input_data
.throttle
;
332 _newdata
->rudder
= _input_data
.rudder
;
333 _newdata
->gas
= _input_data
.gas
;
334 _newdata
->brake
= _input_data
.brake
;
335 _newdata
->tiltX
= _input_data
.tiltX
;
336 _newdata
->tiltY
= _input_data
.tiltY
;
338 _data
.push(_newdata
);
345 // code == scan code of the key (KEY_xxxx defines in input.h)
346 // value == 0 key has been released
347 // value == 1 key has been pressed
348 // value == 2 repeated key reporting (while holding the key)
349 if (ev
->code
== KEY_LEFTSHIFT
) { // 42
350 keyb_lshift
= ev
->value
;
351 } else if (ev
->code
== KEY_RIGHTSHIFT
) { // 54
352 keyb_rshift
= ev
->value
;
353 } else if (ev
->code
== KEY_LEFTCTRL
) { // 29
354 keyb_lctrl
= ev
->value
;
355 } else if (ev
->code
== KEY_RIGHTCTRL
) { // 97
356 keyb_rctrl
= ev
->value
;
357 } else if (ev
->code
== KEY_LEFTALT
) { // 56
358 keyb_lalt
= ev
->value
;
359 } else if (ev
->code
== KEY_RIGHTALT
) { // 100
360 keyb_ralt
= ev
->value
;
361 } else if (ev
->code
== BTN_TOUCH
) { // 0x14a
362 // keyb_ralt = ev->value;
364 _input_data
.key
= scancode_to_gnash_key(ev
->code
,
365 keyb_lshift
|| keyb_rshift
);
367 _input_data
.modifier
= gnash::key::GNASH_MOD_NONE
;
369 if (keyb_lshift
|| keyb_rshift
) {
370 _input_data
.modifier
= _input_data
.modifier
| gnash::key::GNASH_MOD_SHIFT
;
373 if (keyb_lctrl
|| keyb_rctrl
) {
374 _input_data
.modifier
= _input_data
.modifier
| gnash::key::GNASH_MOD_CONTROL
;
377 if (keyb_lalt
|| keyb_ralt
) {
378 _input_data
.modifier
= _input_data
.modifier
| gnash::key::GNASH_MOD_ALT
;
388 log_debug(_("REL_X: %d"), ev
->value
);
389 _input_data
.x
= ev
->value
;
392 log_debug(_("REL_Y: %d"), ev
->value
);
393 _input_data
.y
= ev
->value
;
396 log_debug(_("REL_Z: %d"), ev
->value
);
397 _input_data
.z
= ev
->value
;
400 log_debug(_("REL_RX: %d"), ev
->value
);
401 _input_data
.rx
= ev
->value
;
404 log_debug(_("REL_RY: %d"), ev
->value
);
405 _input_data
.ry
= ev
->value
;
408 log_debug(_("REL_RZ: %d"), ev
->value
);
409 _input_data
.rz
= ev
->value
;
412 log_debug(_("REL_HWHEEL: %d"), ev
->value
);
414 log_debug(_("REL_DIAL: %d"), ev
->value
);
416 log_debug(_("REL_WHEEL: %d"), ev
->value
);
418 log_debug(_("REL_MISC: %d"), ev
->value
);
420 log_unimpl(_("Relative move event %d from Input Event Device"),
423 // Touchscreen or joystick
425 // Absolute coordinates come as multiple events, one for
431 // log_debug("ABS_X: %d", ev->value);
432 _input_data
.x
= ev
->value
;
436 // log_debug("ABS_X: %d ABS_Y: %d", _x, ev->value);
437 _input_data
.y
= ev
->value
;
440 // FIXME: Currently the Z axis is ignored
443 log_debug(_("ABS_Z: %d"), ev
->value
);
446 //log_debug("Pressure: %d", ev->value);
447 _input_data
.pressure
= ev
->value
;
450 log_debug(_("ABS_VOLUME: %d"), ev
->value
);
451 _input_data
.volumne
= ev
->value
;
454 log_debug(_("ABS_DISTANCE: %d"), ev
->value
);
455 _input_data
.distance
= ev
->value
;
458 log_debug(_("ABS_RX: %d"), ev
->value
);
459 _input_data
.rx
= ev
->value
;
462 log_debug(_("ABS_RY: %d"), ev
->value
);
463 _input_data
.ry
= ev
->value
;
466 log_debug(_("ABS_RZ: %d"), ev
->value
);
467 _input_data
.rz
= ev
->value
;
470 log_debug(_("ABS_THROTTLE: %d"), ev
->value
);
471 _input_data
.throttle
= ev
->value
;
474 log_debug(_("ABS_RUDDER: %d"), ev
->value
);
475 _input_data
.rudder
= ev
->value
;
478 log_debug(_("ABS_GAS: %d"), ev
->value
);
479 _input_data
.gas
= ev
->value
;
482 log_debug(_("ABS_BRAKE: %d"), ev
->value
);
483 _input_data
.brake
= ev
->value
;
486 log_debug(_("ABS_TILT_X: %d"), ev
->value
);
487 _input_data
.tiltX
= ev
->value
;
490 log_debug(_("ABS_TILT_Y: %d"), ev
->value
);
491 _input_data
.tiltY
= ev
->value
;
498 // EV_MSC is also used for the keyboard
505 log_unimpl(_("Misc event from Input Event Device"));
509 _input_data
.key
= scancode_to_gnash_key(ev
->value
,
510 keyb_lshift
|| keyb_rshift
);
511 _input_data
.modifier
= gnash::key::GNASH_MOD_NONE
;
513 if (keyb_lshift
|| keyb_rshift
) {
514 _input_data
.modifier
= _input_data
.modifier
| gnash::key::GNASH_MOD_SHIFT
;
517 if (keyb_lctrl
|| keyb_rctrl
) {
518 _input_data
.modifier
= _input_data
.modifier
| gnash::key::GNASH_MOD_CONTROL
;
521 if (keyb_lalt
|| keyb_ralt
) {
522 _input_data
.modifier
= _input_data
.modifier
| gnash::key::GNASH_MOD_ALT
;
529 log_unimpl(_("Misc event from Input Event Device"));
533 log_unimpl(_("LED event from Input Event Device"));
536 log_unimpl(_("Sound event from Input Event Device"));
539 log_unimpl(_("Key autorepeat event from Input Event Device"));
542 log_unimpl(_("Force Feedback event from Input Event Device"));
545 log_unimpl(_("Force Feedback status event from Input Event Device"));
548 log_unimpl(_("Power event from Input Event Device"));
556 EventDevice::scancode_to_gnash_key(int code
, bool shift
)
558 // NOTE: Scancodes are mostly keyboard oriented (ie. Q, W, E, R, T, ...)
559 // while Gnash codes are mostly ASCII-oriented (A, B, C, D, ...) so no
560 // direct conversion is possible.
562 // TODO: This is a very *incomplete* list and I also dislike this method
563 // very much because it depends on the keyboard layout (ie. pressing "Z"
564 // on a german keyboard will print "Y" instead). So we need some
568 case KEY_1
: return !shift
? gnash::key::_1
: gnash::key::EXCLAM
;
569 case KEY_2
: return !shift
? gnash::key::_2
: gnash::key::DOUBLE_QUOTE
;
570 case KEY_3
: return !shift
? gnash::key::_3
: gnash::key::HASH
;
571 case KEY_4
: return !shift
? gnash::key::_4
: gnash::key::DOLLAR
;
572 case KEY_5
: return !shift
? gnash::key::_5
: gnash::key::PERCENT
;
573 case KEY_6
: return !shift
? gnash::key::_6
: gnash::key::AMPERSAND
;
574 case KEY_7
: return !shift
? gnash::key::_7
: gnash::key::SINGLE_QUOTE
;
575 case KEY_8
: return !shift
? gnash::key::_8
: gnash::key::PAREN_LEFT
;
576 case KEY_9
: return !shift
? gnash::key::_9
: gnash::key::PAREN_RIGHT
;
577 case KEY_0
: return !shift
? gnash::key::_0
: gnash::key::ASTERISK
;
579 case KEY_A
: return shift
? gnash::key::A
: gnash::key::a
;
580 case KEY_B
: return shift
? gnash::key::B
: gnash::key::b
;
581 case KEY_C
: return shift
? gnash::key::C
: gnash::key::c
;
582 case KEY_D
: return shift
? gnash::key::D
: gnash::key::d
;
583 case KEY_E
: return shift
? gnash::key::E
: gnash::key::e
;
584 case KEY_F
: return shift
? gnash::key::F
: gnash::key::f
;
585 case KEY_G
: return shift
? gnash::key::G
: gnash::key::g
;
586 case KEY_H
: return shift
? gnash::key::H
: gnash::key::h
;
587 case KEY_I
: return shift
? gnash::key::I
: gnash::key::i
;
588 case KEY_J
: return shift
? gnash::key::J
: gnash::key::j
;
589 case KEY_K
: return shift
? gnash::key::K
: gnash::key::k
;
590 case KEY_L
: return shift
? gnash::key::L
: gnash::key::l
;
591 case KEY_M
: return shift
? gnash::key::M
: gnash::key::m
;
592 case KEY_N
: return shift
? gnash::key::N
: gnash::key::n
;
593 case KEY_O
: return shift
? gnash::key::O
: gnash::key::o
;
594 case KEY_P
: return shift
? gnash::key::P
: gnash::key::p
;
595 case KEY_Q
: return shift
? gnash::key::Q
: gnash::key::q
;
596 case KEY_R
: return shift
? gnash::key::R
: gnash::key::r
;
597 case KEY_S
: return shift
? gnash::key::S
: gnash::key::s
;
598 case KEY_T
: return shift
? gnash::key::T
: gnash::key::t
;
599 case KEY_U
: return shift
? gnash::key::U
: gnash::key::u
;
600 case KEY_V
: return shift
? gnash::key::V
: gnash::key::v
;
601 case KEY_W
: return shift
? gnash::key::W
: gnash::key::w
;
602 case KEY_X
: return shift
? gnash::key::X
: gnash::key::x
;
603 case KEY_Y
: return shift
? gnash::key::Y
: gnash::key::y
;
604 case KEY_Z
: return shift
? gnash::key::Z
: gnash::key::z
;
606 case KEY_F1
: return gnash::key::F1
;
607 case KEY_F2
: return gnash::key::F2
;
608 case KEY_F3
: return gnash::key::F3
;
609 case KEY_F4
: return gnash::key::F4
;
610 case KEY_F5
: return gnash::key::F5
;
611 case KEY_F6
: return gnash::key::F6
;
612 case KEY_F7
: return gnash::key::F7
;
613 case KEY_F8
: return gnash::key::F8
;
614 case KEY_F9
: return gnash::key::F9
;
615 case KEY_F10
: return gnash::key::F10
;
616 case KEY_F11
: return gnash::key::F11
;
617 case KEY_F12
: return gnash::key::F12
;
619 case KEY_KP0
: return gnash::key::KP_0
;
620 case KEY_KP1
: return gnash::key::KP_1
;
621 case KEY_KP2
: return gnash::key::KP_2
;
622 case KEY_KP3
: return gnash::key::KP_3
;
623 case KEY_KP4
: return gnash::key::KP_4
;
624 case KEY_KP5
: return gnash::key::KP_5
;
625 case KEY_KP6
: return gnash::key::KP_6
;
626 case KEY_KP7
: return gnash::key::KP_7
;
627 case KEY_KP8
: return gnash::key::KP_8
;
628 case KEY_KP9
: return gnash::key::KP_9
;
630 case KEY_KPMINUS
: return gnash::key::KP_SUBTRACT
;
631 case KEY_KPPLUS
: return gnash::key::KP_ADD
;
632 case KEY_KPDOT
: return gnash::key::KP_DECIMAL
;
633 case KEY_KPASTERISK
: return gnash::key::KP_MULTIPLY
;
634 case KEY_KPENTER
: return gnash::key::KP_ENTER
;
636 case KEY_ESC
: return gnash::key::ESCAPE
;
637 case KEY_MINUS
: return gnash::key::MINUS
;
638 case KEY_EQUAL
: return gnash::key::EQUALS
;
639 case KEY_BACKSPACE
: return gnash::key::BACKSPACE
;
640 case KEY_TAB
: return gnash::key::TAB
;
641 case KEY_LEFTBRACE
: return gnash::key::LEFT_BRACE
;
642 case KEY_RIGHTBRACE
: return gnash::key::RIGHT_BRACE
;
643 case KEY_ENTER
: return gnash::key::ENTER
;
644 case KEY_LEFTCTRL
: return gnash::key::CONTROL
;
645 case KEY_SEMICOLON
: return gnash::key::SEMICOLON
;
646 //case KEY_APOSTROPHE : return gnash::key::APOSTROPHE;
647 //case KEY_GRAVE : return gnash::key::GRAVE;
648 case KEY_LEFTSHIFT
: return gnash::key::SHIFT
;
649 case KEY_BACKSLASH
: return gnash::key::BACKSLASH
;
650 case KEY_COMMA
: return gnash::key::COMMA
;
651 case KEY_SLASH
: return gnash::key::SLASH
;
652 case KEY_RIGHTSHIFT
: return gnash::key::SHIFT
;
653 case KEY_LEFTALT
: return gnash::key::ALT
;
654 case KEY_SPACE
: return gnash::key::SPACE
;
655 case KEY_CAPSLOCK
: return gnash::key::CAPSLOCK
;
656 case KEY_NUMLOCK
: return gnash::key::NUM_LOCK
;
657 //case KEY_SCROLLLOCK : return gnash::key::SCROLLLOCK;
659 case KEY_UP
: return gnash::key::UP
;
660 case KEY_DOWN
: return gnash::key::DOWN
;
661 case KEY_LEFT
: return gnash::key::LEFT
;
662 case KEY_RIGHT
: return gnash::key::RIGHT
;
663 case KEY_PAGEUP
: return gnash::key::PGUP
;
664 case KEY_PAGEDOWN
: return gnash::key::PGDN
;
665 case KEY_INSERT
: return gnash::key::INSERT
;
666 case KEY_DELETE
: return gnash::key::DELETEKEY
;
667 case KEY_HOME
: return gnash::key::HOME
;
668 case KEY_END
: return gnash::key::END
;
671 return gnash::key::INVALID
;
674 // This looks in the input event devices
675 std::vector
<boost::shared_ptr
<InputDevice
> >
676 EventDevice::scanForDevices()
678 // GNASH_REPORT_FUNCTION;
683 std::vector
<boost::shared_ptr
<InputDevice
> > devices
;
685 // The default path for input event devices.
686 char *filespec
= strdup("/dev/input/eventX");
687 int len
= strlen(filespec
) - 1;
689 // Walk through all the input event devices for the ones that
690 // match the type we want. There can be multiple devices of the same
691 // type, so we return the ID of the event devices.
695 // First see if the file exists
696 if (stat(filespec
, &st
) == 0) {
697 // Then see if we can open it
698 if ((fd
= open(filespec
, O_RDWR
)) < 0) {
699 log_error(_("You don't have the proper permissions to open %s"),
701 // Try the next input event device file
703 filespec
[len
] = '0' + total
;
708 // No more device files to try, so we're done scanning
712 char name
[256] = "Unknown";
713 if(ioctl(fd
, EVIOCGNAME(sizeof(name
)), name
) < 0) {
714 log_error(_("ioctl (EVIOCGNAME): %s"), strerror(errno
));
716 log_debug(_("The device on %s says its name is %s"), filespec
, name
);
718 struct input_id device_info
;
719 if(ioctl(fd
, EVIOCGID
, &device_info
)) {
720 log_error(_("ioctl (EVIOCGID): %s"), strerror(errno
));
722 log_debug(_("vendor %04hx product %04hx version %04hx"),
723 device_info
.vendor
, device_info
.product
,
724 device_info
.version
);
726 boost::shared_ptr
<InputDevice
> dev
;
727 dev
= boost::shared_ptr
<InputDevice
>(new EventDevice());
728 // The Uinput device has no product, vendor, or version data.
729 if ((device_info
.vendor
+ device_info
.product
+ device_info
.version
) > 0) {
730 if (dev
->init(filespec
, DEFAULT_BUFFER_SIZE
)) {
732 // We don't care about power buttons, we mostly just want
733 // keyboards, mice, and touchscreens. Power buttons don't have
735 if (device_info
.vendor
!= 0) {
736 log_debug(_("Enabling USB device: %s"), name
);
737 devices
.push_back(dev
);
742 // setup the next device filespec to try
744 filespec
[len
] = '0' + total
;
757 // indent-tabs-mode: nil