1#!/usr/bin/perl
2#
3# qt_tslib_inject.pl:
4#
5#   touch screen input injection tool for use with x11vnc.
6#
7# example usage:
8#
9#   x11vnc ... -rawfb console -pipeinput ./qt_tslib_inject_input.pl -env INJECT_OPTIONS=cal=/etc/pointercal
10#
11# See options below.
12#
13# tested on qtmoko (neo freerunner) with tslib.
14
15#
16# Copyright (c) 2010 by Karl J. Runge <runge@karlrunge.com>
17#
18# qt_tslib_inject.pl is free software; you can redistribute it and/or modify
19# it under the terms of the GNU General Public License as published by
20# the Free Software Foundation; either version 2 of the License, or (at
21# your option) any later version.
22#
23# qt_tslib_inject.pl is distributed in the hope that it will be useful,
24# but WITHOUT ANY WARRANTY; without even the implied warranty of
25# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26# GNU General Public License for more details.
27#
28# You should have received a copy of the GNU General Public License
29# along with qt_tslib_inject.pl; if not, write to the Free Software
30# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
31# or see <http://www.gnu.org/licenses/>.
32#
33
34set_constants();
35
36# one can set these env. vars. before running:
37
38# the device file to inject the events into:
39#
40$dev = $ENV{INJECT_DEV};
41$dev = "/dev/input/event1" unless $dev;
42
43# options, see below. useful: cal=/etc/pointercal
44#
45$options = $ENV{INJECT_OPTIONS};
46$options = '' unless $options ne '';
47
48$debug = 0;	# enable debugging output:
49$pressure = 1;	# level of touch pad pressure for click.
50$btn_touch = 0;	# send BTN_TOUCH on clicks instead of pressure changes.
51$absalways = 0;	# send a zero pressure absolute position event whenever mouse moves.
52$dragskip = 0;	# how often to skip injecting motion event while dragging.
53
54$a_xform = '';	# tslib's calibration coefficients.
55@a = ();
56
57%keycmds = ();	# user defined hotkeys to run external commands.
58
59# separate the options by comma, e.g. pressure=5,cal=/etc/pointercal
60
61if ($options =~ /absalways/i) {
62	# set to always send a zero pressure ABS event when mouse moves
63	$absalways = 1;
64}
65if ($options =~ /btn_touch/i) {
66	# send BTN_TOUCH on clicks.
67	$btn_touch = 1;
68}
69if ($options =~ /pressure=(\d+)/i) {
70	# level of touchpad pressure to use on a touch.
71	$pressure = $1;
72}
73if ($options =~ /dragskip=(\d+)/i) {
74	# when dragging with pressure, skip this many events.
75	$dragskip = $1;
76}
77if ($options =~ /cal=([^,]+)/i) {
78	# tslib's /etc/pointercal linear transform:
79	$a_xform = $1;
80	if (-f $a_xform) {
81		$a_xform = `head -n 1 '$a_xform'`;
82		chomp $a_xform;
83		$a_xform =~ s/^\s*//;
84		$a_xform =~ s/\s*$//;
85	}
86}
87if ($options =~ /keycmds=([^,]+)/i) {
88	# format: keysym1:command1+keysym2:command2+...
89	# e.g.: keycmds=F6:date+F7:'./x11vnc-0.9.10 -connect ./ctl.txt -R reset'
90	my $str = $1;
91	if (-f $str && open(F, "<$str")) {
92		$str = '';
93		while (<F>) {
94			chomp;
95			$_ =~ s/^\s*//;
96			$_ =~ s/\s*$//;
97			next if /^#/;
98			next if $_ eq "";
99			$str .= '+' if $str ne '';
100			$str .= $_;
101		}
102		close F;
103	}
104	foreach my $part (split(/\+/, $str)) {
105		my ($key, $cmd) = split(/:/, $part, 2);
106		if ($key !~ /^\s*$/) {
107			$keycmds{$key} = $cmd;
108		}
109	}
110}
111if ($options =~ /debug=(\d+)/i) {
112	# debug printout
113	$debug = $1;
114} elsif ($options =~ /debug/i) {
115	$debug = 1;
116}
117
118# end of the top part that user should read and understand
119# for setting options, etc.
120######################################################################
121
122$start = time();
123
124# open the device for writing:
125#
126$modes = $O_WRONLY;
127printf("open modes: 0x%x\n", $modes) if $debug;
128
129sysopen(FD, $dev, $modes) || die "$dev: $!";
130
131my $curr_mask = 0;
132my $curr_x = 0;
133my $curr_y = 0;
134my $down_count = 0;
135
136# read input events from x11vnc through STDIN:
137#
138while (<>) {
139	chomp;
140	if (/^Pointer/) {
141		my ($p, $client, $x, $y, $mask, $hint) = split(' ', $_, 6);
142		do_pointer($client, $x, $y, $mask, $hint);
143	} elsif (/^Keysym/) {
144		my ($k, $client, $down, $keysym, $name, $hint) = split(' ', $_, 6);
145		do_keysym($client, $down, $keysym, $name, $hint);
146	}
147}
148
149close(FD);
150
151exit(0);
152
153sub do_keysym {
154	# qtmoko/neo does not support keystroke input.  so these will be ignored.
155	# (one possibility would to be enable qtmoko to read from /dev/tty0.
156	# but the injection mechanism would need to be modified.)
157        my ($client, $down, $keysym, $name, $hint) = @_;
158
159	$ENV{DO_KEYSYM} = "$client $down $keysym $name $hint";
160
161	# one could implement his own 'hot keys' here.
162
163	# process any keycmds:
164	if (%keycmds && (exists $keycmds{$name} || exists $keycmds{ALL})) {
165		my $cmd = $keycmds{$name};
166		if (!exists $keycmds{$name}) {
167			$cmd = $keycmds{ALL};
168			print STDERR "keycmds: $name/ALL: running: $cmd\n";
169			system("$cmd");
170		} elsif ($down) {
171			print STDERR "keycmds: $name: running: $cmd\n";
172			system("$cmd");
173		}
174		return;
175	}
176
177	$name = "XK_$name";
178	my $nolookup = 0;
179	if (! exists $key_lookup{$name}) {
180		$nolookup = 1;
181	} elsif (! defined $key_lookup{$name}) {
182		$nolookup = 2;
183	} elsif ($key_lookup{$name} =~ /^\s*$/) {
184		$nolookup = 3;
185	}
186	if ($nolookup) {
187		print STDERR "do_keysym: key not implemented-$nolookup $down $keysym $name $hint.\n" if $debug;
188		return;
189	}
190
191	print STDERR gettime() . " do_keysym: $name\n" if $debug;
192	do_key($key_lookup{$name}, $down);
193}
194
195sub do_pointer {
196        my ($client, $x, $y, $mask, $hint) = @_;
197	my $x2 = $x;
198	my $y2 = $y;
199	if ($a_xform ne '') {
200		# this is tslib's /etc/pointercal format.
201		if (! @a) {
202			# -528 33408 -3417516 -44200 408 40292028 56541
203			@a = split(' ', $a_xform);
204			foreach my $a (@a) {
205				$a += 0.0;
206			}
207		}
208		# this is the inverse of the tslib transformation:
209		#
210		$x2 = ( $a[4] * ($a[6] * $x - $a[2]) - $a[1] * ($a[6] * $y - $a[5]) )
211			/ ( $a[4] * $a[0] - $a[1] * $a[3]);
212		$y2 = ( $a[0] * ($a[6] * $y - $a[5]) - $a[3] * ($a[6] * $x - $a[2]) )
213			/ ( $a[4] * $a[0] - $a[1] * $a[3]);
214		$x2 = int($x2);
215		$y2 = int($y2);
216	}
217
218	print STDERR gettime() . " do_pointer $x $y (=> $x2 $y2) $mask $hint.\n" if $debug;
219
220	if (! $btn_touch) {
221		if ($curr_mask == 0 && $mask == 0) {
222			do_abs($x2, $y2, 0) if $absalways;
223		} elsif ($curr_mask == 0 && $mask != 0) {
224			do_abs($x2, $y2, $pressure);
225			$down_count = 0;
226		} elsif ($curr_mask != 0 && $mask == 0) {
227			do_abs($x2, $y2, 0);
228		} elsif ($curr_mask != 0 && $mask != 0) {
229			$down_count++;
230			if ($dragskip > 0) {
231				if ($down_count % $dragskip == 0) {
232					do_abs($x2, $y2, $pressure);
233				} else {
234					print STDERR "dragskip $down_count $dragskip\n" if $debug;
235				}
236			} else {
237				do_abs($x2, $y2, $pressure);
238			}
239		}
240	} else {
241		if ($curr_mask == 0 && $mask == 0) {
242			do_abs($x2, $y2, 0) if $absalways;
243		} elsif ($curr_mask == 0 && $mask != 0) {
244			do_abs($x2, $y2, 0);
245			do_btn($BTN_TOUCH, 1);
246		} elsif ($curr_mask != 0 && $mask == 0) {
247			do_abs($x2, $y2, 0);
248			do_btn($BTN_TOUCH, 0);
249		} elsif ($curr_mask != 0 && $mask != 0) {
250			;
251		}
252	}
253
254	$curr_mask = $mask;
255	$curr_x = $x2;
256	$curr_y = $y2;
257}
258
259# struct input_event {
260#         struct timeval time;
261#         __u16 type;
262#         __u16 code;
263#         __s32 value;
264# };
265
266sub do_syn {
267	my $ev = gtod();
268	$ev .= pack("S", $EV_SYN);
269	$ev .= pack("S", $SYN_REPORT);
270	$ev .= pack("i", 0);
271	print STDERR "do_syn EV_SYN\n" if $debug;
272	my $ret = syswrite(FD, $ev, length($ev));
273	if (!defined $ret) {
274		print STDERR "do_syn: $!\n";
275	}
276}
277
278sub do_key {
279	# not supported by qtmoko
280	my ($key, $down) = @_;
281	my $ev = gtod();
282	$ev .= pack("S", $EV_KEY);
283	$ev .= pack("S", $key);
284	$ev .= pack("i", $down);
285	print STDERR "do_key $key $down\n" if $debug;
286	my $ret = syswrite(FD, $ev, length($ev));
287	if (!defined $ret) {
288		print STDERR "do_key: $!\n";
289	}
290	do_syn();
291}
292
293sub do_btn {
294	# only BTN_TOUCH supported by qtmoko (but it seems to be ignored??)
295	my ($button, $down) = @_;
296	my $ev = gtod();
297	$ev .= pack("S", $EV_KEY);
298	$ev .= pack("S", $button);
299	$ev .= pack("i", $down);
300	print STDERR "do_btn $button $down\n" if $debug;
301	my $ret = syswrite(FD, $ev, length($ev));
302	if (!defined $ret) {
303		print STDERR "do_btn: $!\n";
304	}
305	do_syn();
306}
307
308sub do_abs {
309	# absolute method is the workhorse for the touchscreen.
310	my ($x, $y, $p) = @_;
311	my $ev = gtod();
312	$ev .= pack("S", $EV_ABS);
313	$ev .= pack("S", $ABS_Y);
314	$ev .= pack("i", $y);
315	print STDERR "do_abs y=$y\n" if $debug;
316	my $ret = syswrite(FD, $ev, length($ev));
317	if (!defined $ret) {
318		print STDERR "do_abs: $!\n";
319	}
320	$ev = gtod();
321	$ev .= pack("S", $EV_ABS);
322	$ev .= pack("S", $ABS_X);
323	$ev .= pack("i", $x);
324	print STDERR "do_abs x=$x\n" if $debug;
325	$ret = syswrite(FD, $ev, length($ev));
326	if (!defined $ret) {
327		print STDERR "do_abs: $!\n";
328	}
329	$ev = gtod();
330	$ev .= pack("S", $EV_ABS);
331	$ev .= pack("S", $ABS_PRESSURE);
332	$ev .= pack("i", $p);
333	print STDERR "do_abs p=$p\n" if $debug;
334	$ret = syswrite(FD, $ev, length($ev));
335	if (!defined $ret) {
336		print STDERR "do_abs: $!\n";
337	}
338	do_syn();
339}
340
341sub do_rel {
342	# not supported by qtmoko
343	my ($dx, $dy) = @_;
344	my $ev = gtod();
345	$ev .= pack("S", $EV_REL);
346	$ev .= pack("S", $REL_Y);
347	$ev .= pack("i", $dy);
348	print STDERR "do_rel dy=$dy\n" if $debug;
349	my $ret = syswrite(FD, $ev, length($ev));
350	if (!defined $ret) {
351		print STDERR "do_rel: $!\n";
352	}
353	$ev = gtod();
354	$ev .= pack("S", $EV_REL);
355	$ev .= pack("S", $REL_X);
356	$ev .= pack("i", $dx);
357	print STDERR "do_rel dx=$dx\n";
358	$ret = syswrite(FD, $ev, length($ev));
359	if (!defined $ret) {
360		print STDERR "do_rel: $!\n";
361	}
362	do_syn();
363}
364
365sub gtod {
366	# 32 bit machines.  TBD use perl module Time:HiRes.
367	$tv = ("\0" x 4) x 2;   # assumes long is 4 bytes. should use pack.
368	$tz = ("\0" x 4) x 2;
369	syscall($linux_gettimeofday_syscall, $tv, $tz);
370	return $tv;
371}
372
373sub gettime {
374	my $tv = gtod();
375	my ($tv_sec, $tv_usec) = unpack("L2", $tv);
376	$tv_usec2 = sprintf("%8.6f", $tv_usec/1000000.0);
377	if ( $tv_usec2 =~ /^0\./ ) {
378		$tv_usec2 =~ s/^0\././;
379		$tv_sec = "$tv_sec$tv_usec2";
380	} else {
381		$tv_sec = $tv_sec + ($tv_usec/1000000.0);
382	}
383	return sprintf("%.3f", $tv_sec - $start);
384}
385
386sub fsleep {
387        my ($time) = @_;
388        select(undef, undef, undef, $time) if $time;
389}
390
391sub set_constants {
392
393# from /usr/include/linux/uinput.h /usr/include/linux/input.h and x11vnc.
394
395# #define ABS_MAX                 0x3f = 63
396#
397# #define UINPUT_MAX_NAME_SIZE    80
398#
399# struct input_id {
400#         __u16 bustype;
401#         __u16 vendor;
402#         __u16 product;
403#         __u16 version;
404# };
405#
406# struct uinput_user_dev {
407#         char name[UINPUT_MAX_NAME_SIZE];
408#         struct input_id id;
409#         int ff_effects_max;
410#         int absmax[ABS_MAX + 1];
411#         int absmin[ABS_MAX + 1];
412#         int absfuzz[ABS_MAX + 1];
413#         int absflat[ABS_MAX + 1];
414# };
415# #endif  /* __UINPUT_H_ */
416
417$EV_SYN                  = 0x00;
418$EV_KEY                  = 0x01;
419$EV_REL                  = 0x02;
420$EV_ABS                  = 0x03;
421$EV_MSC                  = 0x04;
422$EV_SW                   = 0x05;
423$EV_LED                  = 0x11;
424$EV_SND                  = 0x12;
425$EV_REP                  = 0x14;
426$EV_FF                   = 0x15;
427$EV_PWR                  = 0x16;
428$EV_FF_STATUS            = 0x17;
429$EV_MAX                  = 0x1f;
430
431$ID_BUS                  = 0;
432$ID_VENDOR               = 1;
433$ID_PRODUCT              = 2;
434$ID_VERSION              = 3;
435
436$BUS_PCI                 = 0x01;
437$BUS_ISAPNP              = 0x02;
438$BUS_USB                 = 0x03;
439$BUS_HIL                 = 0x04;
440$BUS_BLUETOOTH           = 0x05;
441$BUS_VIRTUAL             = 0x06;
442
443$BUS_ISA                 = 0x10;
444$BUS_I8042               = 0x11;
445$BUS_XTKBD               = 0x12;
446$BUS_RS232               = 0x13;
447$BUS_GAMEPORT            = 0x14;
448$BUS_PARPORT             = 0x15;
449$BUS_AMIGA               = 0x16;
450$BUS_ADB                 = 0x17;
451$BUS_I2C                 = 0x18;
452$BUS_HOST                = 0x19;
453$BUS_GSC                 = 0x1A;
454$BUS_ATARI               = 0x1B;
455
456$REL_X                   = 0x00;
457$REL_Y                   = 0x01;
458$REL_Z                   = 0x02;
459$REL_RX                  = 0x03;
460$REL_RY                  = 0x04;
461$REL_RZ                  = 0x05;
462$REL_HWHEEL              = 0x06;
463$REL_DIAL                = 0x07;
464$REL_WHEEL               = 0x08;
465$REL_MISC                = 0x09;
466
467$ABS_X                   = 0x00;
468$ABS_Y                   = 0x01;
469$ABS_Z                   = 0x02;
470$ABS_RX                  = 0x03;
471$ABS_RY                  = 0x04;
472$ABS_RZ                  = 0x05;
473$ABS_THROTTLE            = 0x06;
474$ABS_RUDDER              = 0x07;
475$ABS_WHEEL               = 0x08;
476$ABS_GAS                 = 0x09;
477$ABS_BRAKE               = 0x0a;
478$ABS_HAT0X               = 0x10;
479$ABS_HAT0Y               = 0x11;
480$ABS_HAT1X               = 0x12;
481$ABS_HAT1Y               = 0x13;
482$ABS_HAT2X               = 0x14;
483$ABS_HAT2Y               = 0x15;
484$ABS_HAT3X               = 0x16;
485$ABS_HAT3Y               = 0x17;
486$ABS_PRESSURE            = 0x18;
487$ABS_DISTANCE            = 0x19;
488$ABS_TILT_X              = 0x1a;
489$ABS_TILT_Y              = 0x1b;
490$ABS_TOOL_WIDTH          = 0x1c;
491$ABS_VOLUME              = 0x20;
492$ABS_MISC                = 0x28;
493$ABS_MT_TOUCH_MAJOR      = 0x30;
494$ABS_MT_TOUCH_MINOR      = 0x31;
495$ABS_MT_WIDTH_MAJOR      = 0x32;
496$ABS_MT_WIDTH_MINOR      = 0x33;
497$ABS_MT_ORIENTATION      = 0x34;
498$ABS_MT_POSITION_X       = 0x35;
499$ABS_MT_POSITION_Y       = 0x36;
500$ABS_MT_TOOL_TYPE        = 0x37;
501$ABS_MT_BLOB_ID          = 0x38;
502$ABS_MT_TRACKING_ID      = 0x39;
503#$ABS_MAX = 0x3f;
504
505
506$BTN_MISC                = 0x100;
507$BTN_0                   = 0x100;
508$BTN_1                   = 0x101;
509$BTN_2                   = 0x102;
510$BTN_3                   = 0x103;
511$BTN_4                   = 0x104;
512$BTN_5                   = 0x105;
513$BTN_6                   = 0x106;
514$BTN_7                   = 0x107;
515$BTN_8                   = 0x108;
516$BTN_9                   = 0x109;
517
518$BTN_MOUSE               = 0x110;
519$BTN_LEFT                = 0x110;
520$BTN_RIGHT               = 0x111;
521$BTN_MIDDLE              = 0x112;
522$BTN_SIDE                = 0x113;
523$BTN_EXTRA               = 0x114;
524$BTN_FORWARD             = 0x115;
525$BTN_BACK                = 0x116;
526$BTN_TASK                = 0x117;
527
528$BTN_JOYSTICK            = 0x120;
529$BTN_TRIGGER             = 0x120;
530$BTN_THUMB               = 0x121;
531$BTN_THUMB2              = 0x122;
532$BTN_TOP                 = 0x123;
533$BTN_TOP2                = 0x124;
534$BTN_PINKIE              = 0x125;
535$BTN_BASE                = 0x126;
536$BTN_BASE2               = 0x127;
537$BTN_BASE3               = 0x128;
538$BTN_BASE4               = 0x129;
539$BTN_BASE5               = 0x12a;
540$BTN_BASE6               = 0x12b;
541$BTN_DEAD                = 0x12f;
542
543$BTN_GAMEPAD             = 0x130;
544$BTN_A                   = 0x130;
545$BTN_B                   = 0x131;
546$BTN_C                   = 0x132;
547$BTN_X                   = 0x133;
548$BTN_Y                   = 0x134;
549$BTN_Z                   = 0x135;
550$BTN_TL                  = 0x136;
551$BTN_TR                  = 0x137;
552$BTN_TL2                 = 0x138;
553$BTN_TR2                 = 0x139;
554$BTN_SELECT              = 0x13a;
555$BTN_START               = 0x13b;
556$BTN_MODE                = 0x13c;
557$BTN_THUMBL              = 0x13d;
558$BTN_THUMBR              = 0x13e;
559
560$BTN_DIGI                = 0x140;
561$BTN_TOOL_PEN            = 0x140;
562$BTN_TOOL_RUBBER         = 0x141;
563$BTN_TOOL_BRUSH          = 0x142;
564$BTN_TOOL_PENCIL         = 0x143;
565$BTN_TOOL_AIRBRUSH       = 0x144;
566$BTN_TOOL_FINGER         = 0x145;
567$BTN_TOOL_MOUSE          = 0x146;
568$BTN_TOOL_LENS           = 0x147;
569$BTN_TOUCH               = 0x14a;
570$BTN_STYLUS              = 0x14b;
571$BTN_STYLUS2             = 0x14c;
572$BTN_TOOL_DOUBLETAP      = 0x14d;
573$BTN_TOOL_TRIPLETAP      = 0x14e;
574
575$BTN_WHEEL               = 0x150;
576$BTN_GEAR_DOWN           = 0x150;
577$BTN_GEAR_UP             = 0x151;
578
579$SYN_REPORT              = 0;
580$SYN_CONFIG              = 1;
581$SYN_MT_REPORT           = 2;
582
583$KEY_RESERVED = 0;
584$KEY_ESC =      1;
585$KEY_1 =        2;
586$KEY_2 =        3;
587$KEY_3 =        4;
588$KEY_4 =        5;
589$KEY_5 =        6;
590$KEY_6 =        7;
591$KEY_7 =        8;
592$KEY_8 =        9;
593$KEY_9 =        10;
594$KEY_0 =        11;
595$KEY_MINUS =    12;
596$KEY_EQUAL =    13;
597$KEY_BACKSPACE =        14;
598$KEY_TAB =      15;
599$KEY_Q =        16;
600$KEY_W =        17;
601$KEY_E =        18;
602$KEY_R =        19;
603$KEY_T =        20;
604$KEY_Y =        21;
605$KEY_U =        22;
606$KEY_I =        23;
607$KEY_O =        24;
608$KEY_P =        25;
609$KEY_LEFTBRACE =        26;
610$KEY_RIGHTBRACE =       27;
611$KEY_ENTER =    28;
612$KEY_LEFTCTRL = 29;
613$KEY_A =        30;
614$KEY_S =        31;
615$KEY_D =        32;
616$KEY_F =        33;
617$KEY_G =        34;
618$KEY_H =        35;
619$KEY_J =        36;
620$KEY_K =        37;
621$KEY_L =        38;
622$KEY_SEMICOLON =        39;
623$KEY_APOSTROPHE =       40;
624$KEY_GRAVE =    41;
625$KEY_LEFTSHIFT =        42;
626$KEY_BACKSLASH =        43;
627$KEY_Z =        44;
628$KEY_X =        45;
629$KEY_C =        46;
630$KEY_V =        47;
631$KEY_B =        48;
632$KEY_N =        49;
633$KEY_M =        50;
634$KEY_COMMA =    51;
635$KEY_DOT =      52;
636$KEY_SLASH =    53;
637$KEY_RIGHTSHIFT =       54;
638$KEY_KPASTERISK =       55;
639$KEY_LEFTALT =  56;
640$KEY_SPACE =    57;
641$KEY_CAPSLOCK = 58;
642$KEY_F1 =       59;
643$KEY_F2 =       60;
644$KEY_F3 =       61;
645$KEY_F4 =       62;
646$KEY_F5 =       63;
647$KEY_F6 =       64;
648$KEY_F7 =       65;
649$KEY_F8 =       66;
650$KEY_F9 =       67;
651$KEY_F10 =      68;
652$KEY_NUMLOCK =  69;
653$KEY_SCROLLLOCK =       70;
654$KEY_KP7 =      71;
655$KEY_KP8 =      72;
656$KEY_KP9 =      73;
657$KEY_KPMINUS =  74;
658$KEY_KP4 =      75;
659$KEY_KP5 =      76;
660$KEY_KP6 =      77;
661$KEY_KPPLUS =   78;
662$KEY_KP1 =      79;
663$KEY_KP2 =      80;
664$KEY_KP3 =      81;
665$KEY_KP0 =      82;
666$KEY_KPDOT =    83;
667$KEY_103RD =    84;
668$KEY_F13 =      85;
669$KEY_102ND =    86;
670$KEY_F11 =      87;
671$KEY_F12 =      88;
672$KEY_F14 =      89;
673$KEY_F15 =      90;
674$KEY_F16 =      91;
675$KEY_F17 =      92;
676$KEY_F18 =      93;
677$KEY_F19 =      94;
678$KEY_F20 =      95;
679$KEY_KPENTER =  96;
680$KEY_RIGHTCTRL =        97;
681$KEY_KPSLASH =  98;
682$KEY_SYSRQ =    99;
683$KEY_RIGHTALT = 100;
684$KEY_LINEFEED = 101;
685$KEY_HOME =     102;
686$KEY_UP =       103;
687$KEY_PAGEUP =   104;
688$KEY_LEFT =     105;
689$KEY_RIGHT =    106;
690$KEY_END =      107;
691$KEY_DOWN =     108;
692$KEY_PAGEDOWN = 109;
693$KEY_INSERT =   110;
694$KEY_DELETE =   111;
695$KEY_MACRO =    112;
696$KEY_MUTE =     113;
697$KEY_VOLUMEDOWN =       114;
698$KEY_VOLUMEUP = 115;
699$KEY_POWER =    116;
700$KEY_KPEQUAL =  117;
701$KEY_KPPLUSMINUS =      118;
702$KEY_PAUSE =    119;
703$KEY_F21 =      120;
704$KEY_F22 =      121;
705$KEY_F23 =      122;
706$KEY_F24 =      123;
707$KEY_KPCOMMA =  124;
708$KEY_LEFTMETA = 125;
709$KEY_RIGHTMETA =        126;
710$KEY_COMPOSE =  127;
711$KEY_STOP =     128;
712$KEY_AGAIN =    129;
713$KEY_PROPS =    130;
714$KEY_UNDO =     131;
715$KEY_FRONT =    132;
716$KEY_COPY =     133;
717$KEY_OPEN =     134;
718$KEY_PASTE =    135;
719$KEY_FIND =     136;
720$KEY_CUT =      137;
721$KEY_HELP =     138;
722$KEY_MENU =     139;
723$KEY_CALC =     140;
724$KEY_SETUP =    141;
725$KEY_SLEEP =    142;
726$KEY_WAKEUP =   143;
727$KEY_FILE =     144;
728$KEY_SENDFILE = 145;
729$KEY_DELETEFILE =       146;
730$KEY_XFER =     147;
731$KEY_PROG1 =    148;
732$KEY_PROG2 =    149;
733$KEY_WWW =      150;
734$KEY_MSDOS =    151;
735$KEY_COFFEE =   152;
736$KEY_DIRECTION =        153;
737$KEY_CYCLEWINDOWS =     154;
738$KEY_MAIL =     155;
739$KEY_BOOKMARKS =        156;
740$KEY_COMPUTER = 157;
741$KEY_BACK =     158;
742$KEY_FORWARD =  159;
743$KEY_CLOSECD =  160;
744$KEY_EJECTCD =  161;
745$KEY_EJECTCLOSECD =     162;
746$KEY_NEXTSONG = 163;
747$KEY_PLAYPAUSE =        164;
748$KEY_PREVIOUSSONG =     165;
749$KEY_STOPCD =   166;
750$KEY_RECORD =   167;
751$KEY_REWIND =   168;
752$KEY_PHONE =    169;
753$KEY_ISO =      170;
754$KEY_CONFIG =   171;
755$KEY_HOMEPAGE = 172;
756$KEY_REFRESH =  173;
757$KEY_EXIT =     174;
758$KEY_MOVE =     175;
759$KEY_EDIT =     176;
760$KEY_SCROLLUP = 177;
761$KEY_SCROLLDOWN =       178;
762$KEY_KPLEFTPAREN =      179;
763$KEY_KPRIGHTPAREN =     180;
764$KEY_INTL1 =    181;
765$KEY_INTL2 =    182;
766$KEY_INTL3 =    183;
767$KEY_INTL4 =    184;
768$KEY_INTL5 =    185;
769$KEY_INTL6 =    186;
770$KEY_INTL7 =    187;
771$KEY_INTL8 =    188;
772$KEY_INTL9 =    189;
773$KEY_LANG1 =    190;
774$KEY_LANG2 =    191;
775$KEY_LANG3 =    192;
776$KEY_LANG4 =    193;
777$KEY_LANG5 =    194;
778$KEY_LANG6 =    195;
779$KEY_LANG7 =    196;
780$KEY_LANG8 =    197;
781$KEY_LANG9 =    198;
782$KEY_PLAYCD =   200;
783$KEY_PAUSECD =  201;
784$KEY_PROG3 =    202;
785$KEY_PROG4 =    203;
786$KEY_SUSPEND =  205;
787$KEY_CLOSE =    206;
788$KEY_PLAY =     207;
789$KEY_FASTFORWARD =      208;
790$KEY_BASSBOOST =        209;
791$KEY_PRINT =    210;
792$KEY_HP =       211;
793$KEY_CAMERA =   212;
794$KEY_SOUND =    213;
795$KEY_QUESTION = 214;
796$KEY_EMAIL =    215;
797$KEY_CHAT =     216;
798$KEY_SEARCH =   217;
799$KEY_CONNECT =  218;
800$KEY_FINANCE =  219;
801$KEY_SPORT =    220;
802$KEY_SHOP =     221;
803$KEY_ALTERASE = 222;
804$KEY_CANCEL =   223;
805$KEY_BRIGHTNESSDOWN =   224;
806$KEY_BRIGHTNESSUP =     225;
807$KEY_MEDIA =    226;
808$KEY_UNKNOWN =  240;
809$KEY_OK =       0x160;
810$KEY_SELECT =   0x161;
811$KEY_GOTO =     0x162;
812$KEY_CLEAR =    0x163;
813$KEY_POWER2 =   0x164;
814$KEY_OPTION =   0x165;
815$KEY_INFO =     0x166;
816$KEY_TIME =     0x167;
817$KEY_VENDOR =   0x168;
818$KEY_ARCHIVE =  0x169;
819$KEY_PROGRAM =  0x16a;
820$KEY_CHANNEL =  0x16b;
821$KEY_FAVORITES =        0x16c;
822$KEY_EPG =      0x16d;
823$KEY_PVR =      0x16e;
824$KEY_MHP =      0x16f;
825$KEY_LANGUAGE = 0x170;
826$KEY_TITLE =    0x171;
827$KEY_SUBTITLE = 0x172;
828$KEY_ANGLE =    0x173;
829$KEY_ZOOM =     0x174;
830$KEY_MODE =     0x175;
831$KEY_KEYBOARD = 0x176;
832$KEY_SCREEN =   0x177;
833$KEY_PC =       0x178;
834$KEY_TV =       0x179;
835$KEY_TV2 =      0x17a;
836$KEY_VCR =      0x17b;
837$KEY_VCR2 =     0x17c;
838$KEY_SAT =      0x17d;
839$KEY_SAT2 =     0x17e;
840$KEY_CD =       0x17f;
841$KEY_TAPE =     0x180;
842$KEY_RADIO =    0x181;
843$KEY_TUNER =    0x182;
844$KEY_PLAYER =   0x183;
845$KEY_TEXT =     0x184;
846$KEY_DVD =      0x185;
847$KEY_AUX =      0x186;
848$KEY_MP3 =      0x187;
849$KEY_AUDIO =    0x188;
850$KEY_VIDEO =    0x189;
851$KEY_DIRECTORY =        0x18a;
852$KEY_LIST =     0x18b;
853$KEY_MEMO =     0x18c;
854$KEY_CALENDAR = 0x18d;
855$KEY_RED =      0x18e;
856$KEY_GREEN =    0x18f;
857$KEY_YELLOW =   0x190;
858$KEY_BLUE =     0x191;
859$KEY_CHANNELUP =        0x192;
860$KEY_CHANNELDOWN =      0x193;
861$KEY_FIRST =    0x194;
862$KEY_LAST =     0x195;
863$KEY_AB =       0x196;
864$KEY_NEXT =     0x197;
865$KEY_RESTART =  0x198;
866$KEY_SLOW =     0x199;
867$KEY_SHUFFLE =  0x19a;
868$KEY_BREAK =    0x19b;
869$KEY_PREVIOUS = 0x19c;
870$KEY_DIGITS =   0x19d;
871$KEY_TEEN =     0x19e;
872$KEY_TWEN =     0x19f;
873$KEY_DEL_EOL =  0x1c0;
874$KEY_DEL_EOS =  0x1c1;
875$KEY_INS_LINE = 0x1c2;
876$KEY_DEL_LINE = 0x1c3;
877$KEY_MAX =      0x1ff;
878
879
880        $key_lookup{XK_Escape}  = $KEY_ESC;
881        $key_lookup{XK_1}               = $KEY_1;
882        $key_lookup{XK_2}               = $KEY_2;
883        $key_lookup{XK_3}               = $KEY_3;
884        $key_lookup{XK_4}               = $KEY_4;
885        $key_lookup{XK_5}               = $KEY_5;
886        $key_lookup{XK_6}               = $KEY_6;
887        $key_lookup{XK_7}               = $KEY_7;
888        $key_lookup{XK_8}               = $KEY_8;
889        $key_lookup{XK_9}               = $KEY_9;
890        $key_lookup{XK_0}               = $KEY_0;
891        $key_lookup{XK_exclam}  = $KEY_1;
892        $key_lookup{XK_at}              = $KEY_2;
893        $key_lookup{XK_numbersign}      = $KEY_3;
894        $key_lookup{XK_dollar}  = $KEY_4;
895        $key_lookup{XK_percent} = $KEY_5;
896        $key_lookup{XK_asciicircum}     = $KEY_6;
897        $key_lookup{XK_ampersand}       = $KEY_7;
898        $key_lookup{XK_asterisk}        = $KEY_8;
899        $key_lookup{XK_parenleft}       = $KEY_9;
900        $key_lookup{XK_parenright}      = $KEY_0;
901        $key_lookup{XK_minus}   = $KEY_MINUS;
902        $key_lookup{XK_underscore}      = $KEY_MINUS;
903        $key_lookup{XK_equal}   = $KEY_EQUAL;
904        $key_lookup{XK_plus}    = $KEY_EQUAL;
905        $key_lookup{XK_BackSpace}       = $KEY_BACKSPACE;
906        $key_lookup{XK_Tab}             = $KEY_TAB;
907        $key_lookup{XK_q}               = $KEY_Q;
908        $key_lookup{XK_Q}               = $KEY_Q;
909        $key_lookup{XK_w}               = $KEY_W;
910        $key_lookup{XK_W}               = $KEY_W;
911        $key_lookup{XK_e}               = $KEY_E;
912        $key_lookup{XK_E}               = $KEY_E;
913        $key_lookup{XK_r}               = $KEY_R;
914        $key_lookup{XK_R}               = $KEY_R;
915        $key_lookup{XK_t}               = $KEY_T;
916        $key_lookup{XK_T}               = $KEY_T;
917        $key_lookup{XK_y}               = $KEY_Y;
918        $key_lookup{XK_Y}               = $KEY_Y;
919        $key_lookup{XK_u}               = $KEY_U;
920        $key_lookup{XK_U}               = $KEY_U;
921        $key_lookup{XK_i}               = $KEY_I;
922        $key_lookup{XK_I}               = $KEY_I;
923        $key_lookup{XK_o}               = $KEY_O;
924        $key_lookup{XK_O}               = $KEY_O;
925        $key_lookup{XK_p}               = $KEY_P;
926        $key_lookup{XK_P}               = $KEY_P;
927        $key_lookup{XK_braceleft}       = $KEY_LEFTBRACE;
928        $key_lookup{XK_braceright}      = $KEY_RIGHTBRACE;
929        $key_lookup{XK_bracketleft}     = $KEY_LEFTBRACE;
930        $key_lookup{XK_bracketright}    = $KEY_RIGHTBRACE;
931        $key_lookup{XK_Return}  = $KEY_ENTER;
932        $key_lookup{XK_Control_L}       = $KEY_LEFTCTRL;
933        $key_lookup{XK_a}               = $KEY_A;
934        $key_lookup{XK_A}               = $KEY_A;
935        $key_lookup{XK_s}               = $KEY_S;
936        $key_lookup{XK_S}               = $KEY_S;
937        $key_lookup{XK_d}               = $KEY_D;
938        $key_lookup{XK_D}               = $KEY_D;
939        $key_lookup{XK_f}               = $KEY_F;
940        $key_lookup{XK_F}               = $KEY_F;
941        $key_lookup{XK_g}               = $KEY_G;
942        $key_lookup{XK_G}               = $KEY_G;
943        $key_lookup{XK_h}               = $KEY_H;
944        $key_lookup{XK_H}               = $KEY_H;
945        $key_lookup{XK_j}               = $KEY_J;
946        $key_lookup{XK_J}               = $KEY_J;
947        $key_lookup{XK_k}               = $KEY_K;
948        $key_lookup{XK_K}               = $KEY_K;
949        $key_lookup{XK_l}               = $KEY_L;
950        $key_lookup{XK_L}               = $KEY_L;
951        $key_lookup{XK_semicolon}       = $KEY_SEMICOLON;
952        $key_lookup{XK_colon}   = $KEY_SEMICOLON;
953        $key_lookup{XK_apostrophe}      = $KEY_APOSTROPHE;
954        $key_lookup{XK_quotedbl}        = $KEY_APOSTROPHE;
955        $key_lookup{XK_grave}   = $KEY_GRAVE;
956        $key_lookup{XK_asciitilde}      = $KEY_GRAVE;
957        $key_lookup{XK_Shift_L} = $KEY_LEFTSHIFT;
958        $key_lookup{XK_backslash}       = $KEY_BACKSLASH;
959        $key_lookup{XK_bar}             = $KEY_BACKSLASH;
960        $key_lookup{XK_z}               = $KEY_Z;
961        $key_lookup{XK_Z}               = $KEY_Z;
962        $key_lookup{XK_x}               = $KEY_X;
963        $key_lookup{XK_X}               = $KEY_X;
964        $key_lookup{XK_c}               = $KEY_C;
965        $key_lookup{XK_C}               = $KEY_C;
966        $key_lookup{XK_v}               = $KEY_V;
967        $key_lookup{XK_V}               = $KEY_V;
968        $key_lookup{XK_b}               = $KEY_B;
969        $key_lookup{XK_B}               = $KEY_B;
970        $key_lookup{XK_n}               = $KEY_N;
971        $key_lookup{XK_N}               = $KEY_N;
972        $key_lookup{XK_m}               = $KEY_M;
973        $key_lookup{XK_M}               = $KEY_M;
974        $key_lookup{XK_comma}   = $KEY_COMMA;
975        $key_lookup{XK_less}    = $KEY_COMMA;
976        $key_lookup{XK_period}  = $KEY_DOT;
977        $key_lookup{XK_greater} = $KEY_DOT;
978        $key_lookup{XK_slash}   = $KEY_SLASH;
979        $key_lookup{XK_question}        = $KEY_SLASH;
980        $key_lookup{XK_Shift_R} = $KEY_RIGHTSHIFT;
981        $key_lookup{XK_KP_Multiply}     = $KEY_KPASTERISK;
982        $key_lookup{XK_Alt_L}   = $KEY_LEFTALT;
983        $key_lookup{XK_space}   = $KEY_SPACE;
984        $key_lookup{XK_Caps_Lock}       = $KEY_CAPSLOCK;
985        $key_lookup{XK_F1}              = $KEY_F1;
986        $key_lookup{XK_F2}              = $KEY_F2;
987        $key_lookup{XK_F3}              = $KEY_F3;
988        $key_lookup{XK_F4}              = $KEY_F4;
989        $key_lookup{XK_F5}              = $KEY_F5;
990        $key_lookup{XK_F6}              = $KEY_F6;
991        $key_lookup{XK_F7}              = $KEY_F7;
992        $key_lookup{XK_F8}              = $KEY_F8;
993        $key_lookup{XK_F9}              = $KEY_F9;
994        $key_lookup{XK_F10}             = $KEY_F10;
995        $key_lookup{XK_Num_Lock}        = $KEY_NUMLOCK;
996        $key_lookup{XK_Scroll_Lock}     = $KEY_SCROLLLOCK;
997        $key_lookup{XK_KP_7}            = $KEY_KP7;
998        $key_lookup{XK_KP_8}            = $KEY_KP8;
999        $key_lookup{XK_KP_9}            = $KEY_KP9;
1000        $key_lookup{XK_KP_Subtract}     = $KEY_KPMINUS;
1001        $key_lookup{XK_KP_4}            = $KEY_KP4;
1002        $key_lookup{XK_KP_5}            = $KEY_KP5;
1003        $key_lookup{XK_KP_6}            = $KEY_KP6;
1004        $key_lookup{XK_KP_Add}  = $KEY_KPPLUS;
1005        $key_lookup{XK_KP_1}            = $KEY_KP1;
1006        $key_lookup{XK_KP_2}            = $KEY_KP2;
1007        $key_lookup{XK_KP_3}            = $KEY_KP3;
1008        $key_lookup{XK_KP_0}            = $KEY_KP0;
1009        $key_lookup{XK_KP_Decimal}      = $KEY_KPDOT;
1010        $key_lookup{XK_F13}             = $KEY_F13;
1011        $key_lookup{XK_F11}             = $KEY_F11;
1012        $key_lookup{XK_F12}             = $KEY_F12;
1013        $key_lookup{XK_F14}             = $KEY_F14;
1014        $key_lookup{XK_F15}             = $KEY_F15;
1015        $key_lookup{XK_F16}             = $KEY_F16;
1016        $key_lookup{XK_F17}             = $KEY_F17;
1017        $key_lookup{XK_F18}             = $KEY_F18;
1018        $key_lookup{XK_F19}             = $KEY_F19;
1019        $key_lookup{XK_F20}             = $KEY_F20;
1020        $key_lookup{XK_KP_Enter}        = $KEY_KPENTER;
1021        $key_lookup{XK_Control_R}       = $KEY_RIGHTCTRL;
1022        $key_lookup{XK_KP_Divide}       = $KEY_KPSLASH;
1023        $key_lookup{XK_Sys_Req} = $KEY_SYSRQ;
1024        $key_lookup{XK_Alt_R}   = $KEY_RIGHTALT;
1025        $key_lookup{XK_Linefeed}        = $KEY_LINEFEED;
1026        $key_lookup{XK_Home}            = $KEY_HOME;
1027        $key_lookup{XK_Up}              = $KEY_UP;
1028        $key_lookup{XK_Page_Up} = $KEY_PAGEUP;
1029        $key_lookup{XK_Left}            = $KEY_LEFT;
1030        $key_lookup{XK_Right}   = $KEY_RIGHT;
1031        $key_lookup{XK_End}             = $KEY_END;
1032        $key_lookup{XK_Down}            = $KEY_DOWN;
1033        $key_lookup{XK_Page_Down}       = $KEY_PAGEDOWN;
1034        $key_lookup{XK_Insert}  = $KEY_INSERT;
1035        $key_lookup{XK_Delete}  = $KEY_DELETE;
1036        $key_lookup{XK_KP_Equal}        = $KEY_KPEQUAL;
1037        $key_lookup{XK_Pause}   = $KEY_PAUSE;
1038        $key_lookup{XK_F21}             = $KEY_F21;
1039        $key_lookup{XK_F22}             = $KEY_F22;
1040        $key_lookup{XK_F23}             = $KEY_F23;
1041        $key_lookup{XK_F24}             = $KEY_F24;
1042        $key_lookup{XK_KP_Separator}    = $KEY_KPCOMMA;
1043        $key_lookup{XK_Meta_L}  = $KEY_LEFTMETA;
1044        $key_lookup{XK_Meta_R}  = $KEY_RIGHTMETA;
1045        $key_lookup{XK_Multi_key}       = $KEY_COMPOSE;
1046
1047$ABS_MAX = 63;
1048
1049$UI_DEV_CREATE  = 0x5501;
1050$UI_DEV_DESTROY = 0x5502;
1051$UI_SET_EVBIT   = 0x40045564;
1052$UI_SET_KEYBIT  = 0x40045565;
1053$UI_SET_RELBIT  = 0x40045566;
1054$UI_SET_ABSBIT  = 0x40045567;
1055
1056# FIXME: time hires, etc.
1057$linux_gettimeofday_syscall = 78;
1058
1059$O_RDONLY = 00;
1060$O_WRONLY = 01;
1061$O_RDWR   = 02;
1062$O_NDELAY = 04000;
1063
1064}
1065