don't use MSC_CNT in a case, it doesn't exist in Android, and will be covered by...
[gnash.git] / libdevice / events / EventDevice.cpp
blob5351dcf17912dc9c11b938f42f1eec31eb399148
1 //
2 // Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
3 //
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.
8 //
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
19 #ifdef HAVE_CONFIG_H
20 #include "gnashconfig.h"
21 #endif
23 #include "log.h"
24 #include "InputDevice.h"
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <linux/input.h>
31 #include <linux/kd.h>
33 namespace gnash {
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()
41 : keyb_lshift(false),
42 keyb_rshift(false),
43 keyb_lctrl(false),
44 keyb_rctrl(false),
45 keyb_lalt(false),
46 keyb_ralt(false)
48 // GNASH_REPORT_FUNCTION;
50 memset(&_device_info, 0, sizeof(struct input_id));
53 bool
54 EventDevice::init()
56 // GNASH_REPORT_FUNCTION;
58 return init(INPUT_DEVICE, DEFAULT_BUFFER_SIZE);
61 bool
62 EventDevice::init(const std::string &filespec, size_t /* size */)
64 // GNASH_REPORT_FUNCTION;
66 dbglogfile.setVerbosity();
68 _filespec = filespec;
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);
73 if (_fd < 0) {
74 log_debug(_("Could not open %s: %s"), filespec, strerror(errno));
75 return false;
78 #if 0
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"),
81 strerror(errno));
82 if (_fd) {
83 close(_fd);
84 _fd = -1;
85 return false;
88 #endif
90 // Get the version number of the input event subsystem
91 int version;
92 if (ioctl(_fd, EVIOCGVERSION, &version)) {
93 log_error(_("ioctl (EVIOCGVERSION)"));
95 #if 0
96 log_debug(_("evdev driver version is %d.%d.%d"),
97 version >> 16, (version >> 8) & 0xff,
98 version & 0xff);
99 #endif
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) {
119 case BUS_PCI:
120 log_unimpl(_("is a PCI bus type"));
121 break;
122 case BUS_ISAPNP:
123 log_unimpl(_("is a PNP bus type"));
124 break;
125 case BUS_USB:
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;
148 break;
149 case BUS_HIL:
150 log_unimpl(_("is a HIL bus type"));
151 break;
152 case BUS_BLUETOOTH:
153 log_unimpl(_("is Bluetooth bus type "));
154 break;
155 #ifdef BUS_VIRTUAL
156 case BUS_VIRTUAL:
157 log_unimpl(_("is a Virtual bus type "));
158 break;
159 #endif
160 case BUS_ISA:
161 log_unimpl(_("is an ISA bus type"));
162 break;
163 case BUS_I8042:
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;
168 } else {
169 if (strstr(name, "Mouse") != 0) {
170 _type = InputDevice::MOUSE;
173 break;
174 case BUS_XTKBD:
175 log_unimpl(_("is an XTKBD bus type"));
176 break;
177 case BUS_RS232:
178 log_unimpl(_("is a serial port bus type"));
179 break;
180 case BUS_GAMEPORT:
181 log_unimpl(_("is a gameport bus type"));
182 break;
183 case BUS_PARPORT:
184 log_unimpl(_("is a parallel port bus type"));
185 break;
186 case BUS_AMIGA:
187 log_unimpl(_("is an Amiga bus type"));
188 break;
189 case BUS_ADB:
190 log_unimpl(_("is an AOB bus type"));
191 break;
192 case BUS_I2C:
193 log_unimpl(_("is an i2C bus type "));
194 break;
195 case BUS_HOST:
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;
206 break;
207 case BUS_GSC:
208 log_unimpl(_("is a GSC bus type"));
209 break;
210 #ifdef BUS_ATARI
211 case BUS_ATARI:
212 log_unimpl(_("is an Atari bus type"));
213 break;
214 #endif
215 default:
216 log_error(_("Unknown bus type %d!"), _device_info.bustype);
219 log_debug(_("Event enabled for %s on fd #%d"), _filespec, _fd);
221 #if 0
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
231 abs.resolution = 0;
232 #endif
233 abs.minimum = 0;
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));
247 } // end of _type
248 #endif
250 return true;
253 bool
254 EventDevice::check()
256 // GNASH_REPORT_FUNCTION;
258 bool activity = false;
260 if (_fd < 0) {
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
267 if (!buf) {
268 return false;
271 /// @note
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
284 /// events.
285 #if 1
286 // FIXME: debug crap
287 const char *debug[] = {
288 "EV_SYN",
289 "EV_KEY",
290 "EV_REL",
291 "EV_ABS",
292 "EV_MSC",
293 "EV_SW",
294 "unknown",
295 "unknown",
296 "unknown",
297 "unknown",
298 "unknown",
299 "EV_LED",
300 "EV_SND",
301 "EV_REP",
302 "EV_FF",
303 "EV_PWR",
304 "EV_FF_STATUS"
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);
309 #endif
311 switch (ev->type) {
312 case EV_SYN:
314 boost::shared_ptr<InputDevice::input_data_t> _newdata(new InputDevice::input_data_t);
315 #if 0
316 std::copy(_input_data.begin(), _input_data.end(), _newdata.begin());
317 #else
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;
337 #endif
338 _data.push(_newdata);
339 activity = true;
340 break;
342 // Keyboard event
343 case EV_KEY:
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;
363 } else {
364 _input_data.key = scancode_to_gnash_key(ev->code,
365 keyb_lshift || keyb_rshift);
366 // build modifier
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;
380 activity = true;
381 } // if normal key
382 break;
383 } // case EV_KEY
384 // Mouse
385 case EV_REL:
386 switch (ev->code) {
387 case REL_X:
388 log_debug(_("REL_X: %d"), ev->value);
389 _input_data.x = ev->value;
390 break;
391 case REL_Y:
392 log_debug(_("REL_Y: %d"), ev->value);
393 _input_data.y = ev->value;
394 break;
395 case REL_Z:
396 log_debug(_("REL_Z: %d"), ev->value);
397 _input_data.z = ev->value;
398 break;
399 case REL_RX:
400 log_debug(_("REL_RX: %d"), ev->value);
401 _input_data.rx = ev->value;
402 break;
403 case REL_RY:
404 log_debug(_("REL_RY: %d"), ev->value);
405 _input_data.ry = ev->value;
406 break;
407 case REL_RZ:
408 log_debug(_("REL_RZ: %d"), ev->value);
409 _input_data.rz = ev->value;
410 break;
411 case REL_HWHEEL:
412 log_debug(_("REL_HWHEEL: %d"), ev->value);
413 case REL_DIAL:
414 log_debug(_("REL_DIAL: %d"), ev->value);
415 case REL_WHEEL:
416 log_debug(_("REL_WHEEL: %d"), ev->value);
417 case REL_MISC:
418 log_debug(_("REL_MISC: %d"), ev->value);
419 default:
420 log_unimpl(_("Relative move event %d from Input Event Device"),
421 ev->value);
423 // Touchscreen or joystick
424 break;
425 // Absolute coordinates come as multiple events, one for
426 // each axis.
427 case EV_ABS:
429 switch (ev->code) {
430 case ABS_X:
431 // log_debug("ABS_X: %d", ev->value);
432 _input_data.x = ev->value;
433 break;
434 case ABS_Y:
436 // log_debug("ABS_X: %d ABS_Y: %d", _x, ev->value);
437 _input_data.y = ev->value;
439 break;
440 // FIXME: Currently the Z axis is ignored
441 case ABS_Z:
442 case ABS_WHEEL:
443 log_debug(_("ABS_Z: %d"), ev->value);
444 break;
445 case ABS_PRESSURE:
446 //log_debug("Pressure: %d", ev->value);
447 _input_data.pressure = ev->value;
448 break;
449 case ABS_VOLUME:
450 log_debug(_("ABS_VOLUME: %d"), ev->value);
451 _input_data.volumne = ev->value;
452 break;
453 case ABS_DISTANCE:
454 log_debug(_("ABS_DISTANCE: %d"), ev->value);
455 _input_data.distance = ev->value;
456 break;
457 case ABS_RX:
458 log_debug(_("ABS_RX: %d"), ev->value);
459 _input_data.rx = ev->value;
460 break;
461 case ABS_RY:
462 log_debug(_("ABS_RY: %d"), ev->value);
463 _input_data.ry = ev->value;
464 break;
465 case ABS_RZ:
466 log_debug(_("ABS_RZ: %d"), ev->value);
467 _input_data.rz = ev->value;
468 break;
469 case ABS_THROTTLE:
470 log_debug(_("ABS_THROTTLE: %d"), ev->value);
471 _input_data.throttle = ev->value;
472 break;
473 case ABS_RUDDER:
474 log_debug(_("ABS_RUDDER: %d"), ev->value);
475 _input_data.rudder = ev->value;
476 break;
477 case ABS_GAS:
478 log_debug(_("ABS_GAS: %d"), ev->value);
479 _input_data.gas = ev->value;
480 break;
481 case ABS_BRAKE:
482 log_debug(_("ABS_BRAKE: %d"), ev->value);
483 _input_data.brake = ev->value;
484 break;
485 case ABS_TILT_X:
486 log_debug(_("ABS_TILT_X: %d"), ev->value);
487 _input_data.tiltX = ev->value;
488 break;
489 case ABS_TILT_Y:
490 log_debug(_("ABS_TILT_Y: %d"), ev->value);
491 _input_data.tiltY = ev->value;
492 break;
493 default:
494 break;
496 break;
498 // EV_MSC is also used for the keyboard
499 case EV_MSC:
500 switch (ev->code) {
501 case MSC_SERIAL:
502 case MSC_PULSELED:
503 case MSC_GESTURE:
504 case MSC_RAW:
505 log_unimpl(_("Misc event from Input Event Device"));
506 break;
507 case MSC_SCAN:
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;
524 activity = true;
525 break;
526 case MSC_MAX:
527 // case MSC_CNT:
528 default:
529 log_unimpl(_("Misc event from Input Event Device"));
531 break;
532 case EV_LED:
533 log_unimpl(_("LED event from Input Event Device"));
534 break;
535 case EV_SND:
536 log_unimpl(_("Sound event from Input Event Device"));
537 break;
538 case EV_REP:
539 log_unimpl(_("Key autorepeat event from Input Event Device"));
540 break;
541 case EV_FF:
542 log_unimpl(_("Force Feedback event from Input Event Device"));
543 break;
544 case EV_FF_STATUS:
545 log_unimpl(_("Force Feedback status event from Input Event Device"));
546 break;
547 case EV_PWR:
548 log_unimpl(_("Power event from Input Event Device"));
549 break;
552 return activity;
555 gnash::key::code
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
565 // alternative...
567 switch (code) {
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;
680 struct stat st;
682 int total = 0;
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.
692 filespec[len] = '0';
693 int fd = 0;
694 while (fd >= 0) {
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"),
700 filespec);
701 // Try the next input event device file
702 total++;
703 filespec[len] = '0' + total;
704 fd = 0;
705 continue;
707 } else {
708 // No more device files to try, so we're done scanning
709 break;
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);
725 close(fd);
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)) {
731 // dev->dump();
732 // We don't care about power buttons, we mostly just want
733 // keyboards, mice, and touchscreens. Power buttons don't have
734 // a vendor ID.
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
743 total++;
744 filespec[len] = '0' + total;
747 free (filespec);
749 return devices;
752 // end of namespace
755 // local Variables:
756 // mode: C++
757 // indent-tabs-mode: nil
758 // End: