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