Advertisement
cheako

Draft of multitouch visualiser.

Mar 6th, 2012
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 38.29 KB | None | 0 0
  1. #!/usr/bin/env perl
  2.  
  3. #
  4. # Multitouch Visualizer
  5. #
  6. #   Copyright (C) 2012 Mike Mestnik
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21.  
  22. package main;
  23.  
  24. use strict;
  25. use warnings;
  26. use Carp;
  27. use Math::Trig ':pi';
  28. use File::Spec;
  29. use Time::HiRes qw(tv_interval);
  30. #use Local::Linux::Input;
  31.  
  32. use Data::Dumper;
  33. #$Data::Dumper::Useqq = 1;
  34. use Statistics::Descriptive;
  35.  
  36. use AnyEvent;
  37. use AnyEvent::Handle;
  38. use AnyEvent::AggressiveIdle qw(aggressive_idle);
  39.  
  40. use OpenGL;
  41.  
  42. my $dev =
  43.   Local::Linux::Input->new(
  44.     File::Spec->catfile( qw%/ dev input%, 'event' . ( $ARGV[0] || 14 ) ) )
  45.   or die @_;
  46.  
  47. warn Dumper $dev;
  48. exit;
  49.  
  50. glpOpenWindow;
  51. my ( $appxa, $appxb, $appya, $appyb ) = ( -1104, 1360, 1600, -2048 );
  52. glOrtho( $appxa, $appxb, $appya, $appyb, -1, 1 );
  53. glClearColor( 0, 0, 0, 1 );
  54. glClear(GL_COLOR_BUFFER_BIT);
  55. glEnable(GL_BLEND);
  56. glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  57.  
  58. print "Press Ctrl-C to exit.\n";
  59.  
  60. my %stat = (
  61.     tv_sec  => Statistics::Descriptive::Sparse->new(),
  62.     tv_usec => Statistics::Descriptive::Sparse->new(),
  63.     x       => Statistics::Descriptive::Sparse->new(),
  64.     y       => Statistics::Descriptive::Sparse->new(),
  65.     size    => Statistics::Descriptive::Sparse->new(),
  66.     hard    => Statistics::Descriptive::Sparse->new(),
  67.     other   => Statistics::Descriptive::Sparse->new(),
  68. );
  69. my @objects;
  70. my $fiveseven = -1;
  71. my $cv        = AnyEvent->condvar;
  72. my $hdl;
  73. $hdl = AnyEvent::Handle->new(
  74.     fh       => $dev->fh,
  75.     on_error => sub {
  76.         my ( $hdl, $fatal, $msg ) = @_;
  77.         $hdl->destroy;
  78.     },
  79.     on_read => sub {
  80.         my $input_device = $dev;
  81.         my @event        = $input_device->poll(0.01);
  82.         for ( my $iev = 0 ; $iev < $#event - 1 ; $iev++ ) {
  83.             my $ev = $event[$iev];
  84.             next
  85.               if ( ( $ev->{type} == 0 && $ev->{code} == 0 && $ev->{value} == 0 )
  86.                 || $ev->{type} == 2 );
  87.             if (
  88.                   $ev->{type} == 0 && defined $event[ 1 + $iev ]
  89.                 ? $event[ 1 + $iev ]->{type} == 0
  90.                 : 0
  91.               )
  92.             {
  93.                 if (
  94.                     defined $event[ 2 + $iev ]
  95.                     ? $event[ 2 + $iev ]->{type} == 0
  96.                     && defined $event[ 3 + $iev ]
  97.                         ? $event[ 3 + $iev ]->{type} == 0
  98.                         : 0
  99.                     : 0
  100.                   )
  101.                 {
  102.                     $stat{tv_sec}->add_data( $ev->{tv_sec} );
  103.                     $stat{tv_usec}->add_data( $ev->{tv_usec} );
  104.                     print $stat{tv_sec}->count() . " Super End\n";
  105.                     $iev += 3;
  106.                     next;
  107.                 }
  108.                 else {
  109.                     $stat{tv_sec}->add_data( $ev->{tv_sec} );
  110.                     $stat{tv_usec}->add_data( $ev->{tv_usec} );
  111.                     print $stat{tv_sec}->count() . " End\n";
  112.                     $iev++;
  113.                     next;
  114.                 }
  115.             }
  116.             if (
  117.                    $ev->{type} == 3
  118.                 && $ev->{code} == 57
  119.                 && (
  120.                     defined $event[ 1 + $iev ] ? $event[ 1 + $iev ]->{type} == 3
  121.                     && $event[ 1 + $iev ]->{code} == 48 : 0 )
  122.                 && (
  123.                     defined $event[ 2 + $iev ] ? $event[ 2 + $iev ]->{type} == 3
  124.                     && $event[ 2 + $iev ]->{code} == 49 : 0 )
  125.               )
  126.             {
  127.                 if (
  128.                     (
  129.                         defined $event[ 3 + $iev ]
  130.                         ? $event[ 3 + $iev ]->{type} == 3
  131.                         && $event[ 3 + $iev ]->{code} == 52
  132.                         : 0
  133.                     )
  134.                     && (
  135.                         defined $event[ 4 + $iev ]
  136.                         ? $event[ 4 + $iev ]->{type} == 3
  137.                         && $event[ 4 + $iev ]->{code} == 53
  138.                         : 0
  139.                     )
  140.                     && (
  141.                         defined $event[ 5 + $iev ]
  142.                         ? $event[ 5 + $iev ]->{type} == 3
  143.                         && $event[ 5 + $iev ]->{code} == 54
  144.                         : 0
  145.                     )
  146.                   )
  147.                 {
  148.                     $stat{tv_sec}->add_data( $ev->{tv_sec} );
  149.                     $stat{tv_usec}->add_data( $ev->{tv_usec} );
  150.                     $stat{x}->add_data( $event[ 4 + $iev ]->{value} );
  151.                     $stat{y}->add_data( $event[ 5 + $iev ]->{value} );
  152.                     $stat{size}->add_data( $event[ 1 + $iev ]->{value} );
  153.                     $stat{hard}->add_data( $event[ 2 + $iev ]->{value} );
  154.                     $stat{other}->add_data( $event[ 3 + $iev ]->{value} );
  155.                     print Dumper [ $ev, %stat ];
  156.  
  157.              # 3824, 1330820887.862841 , type => Big Packet, new => 0,
  158.              # Area => 0/1008~404.807324840764, Hard => 0/1004~350.656050955414,
  159.              # 52 => -31/32~-0.78781847133758, X => -1100/1358~3.77945859872611,
  160.              # Y => -1593/2047~-2.87300955414013,
  161.                     my $size = $event[ 1 + $iev ]->{value} / 32;
  162.                     my ( $x, $y ) = (
  163.                         $event[ 4 + $iev ]->{value},
  164.                         $event[ 5 + $iev ]->{value}
  165.                     );
  166.  
  167.                     push(
  168.                         @objects,
  169.                         {
  170.                             tv_time => [ $ev->{tv_sec}, $ev->{tv_usec} ],
  171.                             new   => $ev->{value} != $fiveseven,
  172.                             force => $event[ 2 + $iev ]->{value} / 1024,
  173.                             x     => $x,
  174.                             y     => $y,
  175.                             size  => $size
  176.                         }
  177.                     );
  178.  
  179.                     $fiveseven = $ev->{value};
  180.                     $iev += 5;
  181.                     next;
  182.                 }
  183.                 else {
  184.                     $stat{tv_sec}->add_data( $ev->{tv_sec} );
  185.                     $stat{tv_usec}->add_data( $ev->{tv_usec} );
  186.                     $stat{size}->add_data( $event[ 1 + $iev ]->{value} );
  187.                     $stat{hard}->add_data( $event[ 2 + $iev ]->{value} );
  188.                     print Dumper [ $ev, %stat ];
  189.                     $fiveseven = $ev->{value};
  190.                     $iev += 2;
  191.                     next;
  192.                 }
  193.             }
  194.             print Dumper [$ev];
  195.         }
  196.     }
  197. );
  198.  
  199. aggressive_idle(
  200.     sub {
  201.         my $ctr = 0;
  202.         foreach my $obj (@objects) {
  203.             my $fade = tv_interval( $obj->{tv_time} );
  204.             $ctr++ if $fade > 2;
  205.             eval { local $SIG{'__DIE__'}; $fade = 1 - sqrt($fade); };
  206.             $fade = 0 if $@;
  207.             glColor4f( 1, $obj->{new}, $obj->{force}, $fade );
  208.  
  209.             DrawCircle( $obj->{x}, $obj->{y}, $obj->{size} );
  210.         }
  211.         my $err = glGetError();
  212.         die $err if $err;
  213.         glpFlush();
  214.         glClear(GL_COLOR_BUFFER_BIT);
  215.  
  216.         if ( $ctr > 1 ) {
  217.             foreach my $ii ( 1 .. $ctr ) {
  218.                 shift @objects;
  219.             }
  220.         }
  221.     }
  222. );
  223.  
  224. $cv->recv;
  225.  
  226. sub DrawCircle {
  227.     my ( $cx, $cy, $r ) = @_;
  228.     my $num_segments = 1 + 10 * sqrt($r);
  229.     my $theta        = pi2 / $num_segments;
  230.     my $tangetial_factor =
  231.       Math::Trig::tan($theta);    # calculate the tangential factor
  232.  
  233.     my $radial_factor = cos($theta);    # calculate the radial factor
  234.  
  235.     my ( $x, $y ) = ( $r, 0 );          # we start at angle = 0
  236.  
  237.     glBegin(GL_LINE_LOOP);
  238.     foreach my $ii ( 0 .. $num_segments ) {
  239.         glVertex2f( $x + $cx, $y + $cy );    # output vertex
  240.  
  241.  # calculate the tangential vector
  242.  # remember, the radial vector is (x, y)
  243.  # to get the tangential vector we flip those coordinates and negate one of them
  244.  
  245.         my $tx = -$y;
  246.         my $ty = $x;
  247.  
  248.         # add the tangential vector
  249.  
  250.         $x += $tx * $tangetial_factor;
  251.         $y += $ty * $tangetial_factor;
  252.  
  253.         # correct using the radial factor
  254.  
  255.         $x *= $radial_factor;
  256.         $y *= $radial_factor;
  257.     }
  258.     glEnd();
  259. }
  260. exit 0;
  261.  
  262. package Local::Linux::Input;
  263.  
  264. use base 'Linux::Input';
  265. # These didn't do anything, using constants.
  266. #require "sys/ioctl.ph"; # These two are for the ioctl calls not needed any more.
  267. #require "linux/input.ph";  # You may need to run 'cd /usr/include; h2ph -a linux/input.h'
  268. use Inline 'C';
  269. use strict;
  270. use warnings;
  271. use Data::Dumper;
  272. #$Data::Dumper::Useqq = 1;
  273.  
  274. # instaniate a new input device
  275. sub new {
  276.     my $class    = shift;
  277.     my $filename = shift;
  278.     my $self     = {};
  279.     bless( $self => $class );
  280.     my $strsz = 128;
  281.  
  282.     $self->{fh} = IO::File->new("< $filename");
  283.     die($!) unless ( $self->{fh} );
  284.  
  285.     my $name="\x00" x $strsz;
  286. # EVIOCGNAME($strsz);
  287.     if (! ioctl( $self->{fh}, 0x80004506 + ($strsz<<16), $name ) < 0 ) {
  288.         warn("evdev ioctl");
  289.     }
  290.     $self->{name} = unpack("A$strsz", $name);
  291.  
  292.     my $phys="\x00" x $strsz;
  293. # EVIOCGPHYS($strsz);
  294.     if (! ioctl( $self->{fh}, 0x80004507 + ($strsz<<16), $phys ) < 0 ) {
  295.         warn("event ioctl");
  296.     }
  297.     $self->{phys} = unpack("A$strsz", $phys);
  298.  
  299.     $strsz=4096;
  300.     my $device_info = "\x00" x $strsz;
  301.     sprint_device_info($device_info, fileno($self->{fh}),$strsz);
  302.     $self->{device_info} = unpack("A$strsz", $device_info);
  303.  
  304.     return $self;
  305. }
  306.  
  307. __DATA__
  308. __C__
  309.  
  310. /*
  311.  *  Copyright (c) 1999-2000 Vojtech Pavlik
  312.  *  Copyright (c) 2009-2011 Red Hat, Inc
  313.  */
  314.  
  315. /**
  316.  * @file
  317.  * Event device test program
  318.  *
  319.  * evtest prints the capabilities on the kernel devices in /dev/input/eventX
  320.  * and their events. Its primary purpose is for kernel or X driver
  321.  * debugging.
  322.  *
  323.  * See INSTALL for installation details or manually compile with
  324.  * gcc -o evtest evtest.c
  325.  */
  326.  
  327. /*
  328.  * This program is free software; you can redistribute it and/or modify
  329.  * it under the terms of the GNU General Public License as published by
  330.  * the Free Software Foundation; either version 2 of the License, or
  331.  * (at your option) any later version.
  332.  *
  333.  * This program is distributed in the hope that it will be useful,
  334.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  335.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  336.  * GNU General Public License for more details.
  337.  *
  338.  * You should have received a copy of the GNU General Public License
  339.  * along with this program; if not, write to the Free Software
  340.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  341.  *
  342.  * Should you need to contact me, the author, you can do so either by
  343.  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  344.  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  345.  */
  346.  
  347. #define _GNU_SOURCE /* for asprintf */
  348. #include <stdio.h>
  349. #include <stdint.h>
  350.  
  351. #if HAVE_CONFIG_H
  352. #include <config.h>
  353. #endif
  354.  
  355. #include <linux/version.h>
  356. #include <linux/input.h>
  357.  
  358. #include <string.h>
  359. #include <fcntl.h>
  360. #include <unistd.h>
  361. #include <stdio.h>
  362. #include <stdlib.h>
  363. #include <dirent.h>
  364. #include <errno.h>
  365. #include <getopt.h>
  366. #include <ctype.h>
  367.  
  368. #define BITS_PER_LONG (sizeof(long) * 8)
  369. #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
  370. #define OFF(x)  ((x)%BITS_PER_LONG)
  371. #define BIT(x)  (1UL<<OFF(x))
  372. #define LONG(x) ((x)/BITS_PER_LONG)
  373. #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
  374.  
  375. #define DEV_INPUT_EVENT "/dev/input"
  376. #define EVENT_DEV_NAME "event"
  377.  
  378. #ifndef EV_SYN
  379. #define EV_SYN 0
  380. #endif
  381. #ifndef SYN_MT_REPORT
  382. #define SYN_MT_REPORT 2
  383. #endif
  384.  
  385. #define NAME_ELEMENT(element) [element] = #element
  386.  
  387. enum evtest_mode {
  388.     MODE_CAPTURE,
  389.     MODE_QUERY,
  390.     MODE_VERSION,
  391. };
  392.  
  393. static const struct query_mode {
  394.     const char *name;
  395.     int event_type;
  396.     int max;
  397.     int rq;
  398. } query_modes[] = {
  399.     { "EV_KEY", EV_KEY, KEY_MAX, EVIOCGKEY(KEY_MAX) },
  400.     { "EV_LED", EV_LED, LED_MAX, EVIOCGLED(LED_MAX) },
  401.     { "EV_SND", EV_SND, SND_MAX, EVIOCGSND(SND_MAX) },
  402.     { "EV_SW",  EV_SW, SW_MAX, EVIOCGSW(SW_MAX) },
  403. };
  404.  
  405. /**
  406.  * Look up an entry in the query_modes table by its textual name.
  407.  *
  408.  * @param mode The name of the entry to be found.
  409.  *
  410.  * @return The requested query_mode, or NULL if it could not be found.
  411.  */
  412. static const struct query_mode *find_query_mode_by_name(const char *name)
  413. {
  414.     int i;
  415.     for (i = 0; i < sizeof(query_modes) / sizeof(*query_modes); i++) {
  416.         const struct query_mode *mode = &query_modes[i];
  417.         if (strcmp(mode->name, name) == 0)
  418.             return mode;
  419.     }
  420.     return NULL;
  421. }
  422.  
  423. /**
  424.  * Look up an entry in the query_modes table by value.
  425.  *
  426.  * @param event_type The value of the entry to be found.
  427.  *
  428.  * @return The requested query_mode, or NULL if it could not be found.
  429.  */
  430. static const struct query_mode *find_query_mode_by_value(int event_type)
  431. {
  432.     int i;
  433.     for (i = 0; i < sizeof(query_modes) / sizeof(*query_modes); i++) {
  434.         const struct query_mode *mode = &query_modes[i];
  435.         if (mode->event_type == event_type)
  436.             return mode;
  437.     }
  438.     return NULL;
  439. }
  440.  
  441. /**
  442.  * Find a query_mode based on a string identifier. The string can either
  443.  * be a numerical value (e.g. "5") or the name of the event type in question
  444.  * (e.g. "EV_SW").
  445.  *
  446.  * @param query_mode The mode to search for
  447.  *
  448.  * @return The requested code's numerical value, or negative on error.
  449. */
  450. static const struct query_mode *find_query_mode(const char *query_mode)
  451. {
  452.     if (isdigit(query_mode[0])) {
  453.         unsigned long val;
  454.         errno = 0;
  455.         val = strtoul(query_mode, NULL, 0);
  456.         if (errno)
  457.             return NULL;
  458.         return find_query_mode_by_value(val);
  459.     } else {
  460.         return find_query_mode_by_name(query_mode);
  461.     }
  462. }
  463.  
  464. static const char * const events[EV_MAX + 1] = {
  465.     [0 ... EV_MAX] = NULL,
  466.     NAME_ELEMENT(EV_SYN),           NAME_ELEMENT(EV_KEY),
  467.     NAME_ELEMENT(EV_REL),           NAME_ELEMENT(EV_ABS),
  468.     NAME_ELEMENT(EV_MSC),           NAME_ELEMENT(EV_LED),
  469.     NAME_ELEMENT(EV_SND),           NAME_ELEMENT(EV_REP),
  470.     NAME_ELEMENT(EV_FF),            NAME_ELEMENT(EV_PWR),
  471.     NAME_ELEMENT(EV_FF_STATUS),     NAME_ELEMENT(EV_SW),
  472. };
  473.  
  474. static const char * const keys[KEY_MAX + 1] = {
  475.     [0 ... KEY_MAX] = NULL,
  476.     NAME_ELEMENT(KEY_RESERVED),     NAME_ELEMENT(KEY_ESC),
  477.     NAME_ELEMENT(KEY_1),            NAME_ELEMENT(KEY_2),
  478.     NAME_ELEMENT(KEY_3),            NAME_ELEMENT(KEY_4),
  479.     NAME_ELEMENT(KEY_5),            NAME_ELEMENT(KEY_6),
  480.     NAME_ELEMENT(KEY_7),            NAME_ELEMENT(KEY_8),
  481.     NAME_ELEMENT(KEY_9),            NAME_ELEMENT(KEY_0),
  482.     NAME_ELEMENT(KEY_MINUS),        NAME_ELEMENT(KEY_EQUAL),
  483.     NAME_ELEMENT(KEY_BACKSPACE),        NAME_ELEMENT(KEY_TAB),
  484.     NAME_ELEMENT(KEY_Q),            NAME_ELEMENT(KEY_W),
  485.     NAME_ELEMENT(KEY_E),            NAME_ELEMENT(KEY_R),
  486.     NAME_ELEMENT(KEY_T),            NAME_ELEMENT(KEY_Y),
  487.     NAME_ELEMENT(KEY_U),            NAME_ELEMENT(KEY_I),
  488.     NAME_ELEMENT(KEY_O),            NAME_ELEMENT(KEY_P),
  489.     NAME_ELEMENT(KEY_LEFTBRACE),        NAME_ELEMENT(KEY_RIGHTBRACE),
  490.     NAME_ELEMENT(KEY_ENTER),        NAME_ELEMENT(KEY_LEFTCTRL),
  491.     NAME_ELEMENT(KEY_A),            NAME_ELEMENT(KEY_S),
  492.     NAME_ELEMENT(KEY_D),            NAME_ELEMENT(KEY_F),
  493.     NAME_ELEMENT(KEY_G),            NAME_ELEMENT(KEY_H),
  494.     NAME_ELEMENT(KEY_J),            NAME_ELEMENT(KEY_K),
  495.     NAME_ELEMENT(KEY_L),            NAME_ELEMENT(KEY_SEMICOLON),
  496.     NAME_ELEMENT(KEY_APOSTROPHE),       NAME_ELEMENT(KEY_GRAVE),
  497.     NAME_ELEMENT(KEY_LEFTSHIFT),        NAME_ELEMENT(KEY_BACKSLASH),
  498.     NAME_ELEMENT(KEY_Z),            NAME_ELEMENT(KEY_X),
  499.     NAME_ELEMENT(KEY_C),            NAME_ELEMENT(KEY_V),
  500.     NAME_ELEMENT(KEY_B),            NAME_ELEMENT(KEY_N),
  501.     NAME_ELEMENT(KEY_M),            NAME_ELEMENT(KEY_COMMA),
  502.     NAME_ELEMENT(KEY_DOT),          NAME_ELEMENT(KEY_SLASH),
  503.     NAME_ELEMENT(KEY_RIGHTSHIFT),       NAME_ELEMENT(KEY_KPASTERISK),
  504.     NAME_ELEMENT(KEY_LEFTALT),      NAME_ELEMENT(KEY_SPACE),
  505.     NAME_ELEMENT(KEY_CAPSLOCK),     NAME_ELEMENT(KEY_F1),
  506.     NAME_ELEMENT(KEY_F2),           NAME_ELEMENT(KEY_F3),
  507.     NAME_ELEMENT(KEY_F4),           NAME_ELEMENT(KEY_F5),
  508.     NAME_ELEMENT(KEY_F6),           NAME_ELEMENT(KEY_F7),
  509.     NAME_ELEMENT(KEY_F8),           NAME_ELEMENT(KEY_F9),
  510.     NAME_ELEMENT(KEY_F10),          NAME_ELEMENT(KEY_NUMLOCK),
  511.     NAME_ELEMENT(KEY_SCROLLLOCK),       NAME_ELEMENT(KEY_KP7),
  512.     NAME_ELEMENT(KEY_KP8),          NAME_ELEMENT(KEY_KP9),
  513.     NAME_ELEMENT(KEY_KPMINUS),      NAME_ELEMENT(KEY_KP4),
  514.     NAME_ELEMENT(KEY_KP5),          NAME_ELEMENT(KEY_KP6),
  515.     NAME_ELEMENT(KEY_KPPLUS),       NAME_ELEMENT(KEY_KP1),
  516.     NAME_ELEMENT(KEY_KP2),          NAME_ELEMENT(KEY_KP3),
  517.     NAME_ELEMENT(KEY_KP0),          NAME_ELEMENT(KEY_KPDOT),
  518.     NAME_ELEMENT(KEY_ZENKAKUHANKAKU),   NAME_ELEMENT(KEY_102ND),
  519.     NAME_ELEMENT(KEY_F11),          NAME_ELEMENT(KEY_F12),
  520.     NAME_ELEMENT(KEY_RO),           NAME_ELEMENT(KEY_KATAKANA),
  521.     NAME_ELEMENT(KEY_HIRAGANA),     NAME_ELEMENT(KEY_HENKAN),
  522.     NAME_ELEMENT(KEY_KATAKANAHIRAGANA), NAME_ELEMENT(KEY_MUHENKAN),
  523.     NAME_ELEMENT(KEY_KPJPCOMMA),        NAME_ELEMENT(KEY_KPENTER),
  524.     NAME_ELEMENT(KEY_RIGHTCTRL),        NAME_ELEMENT(KEY_KPSLASH),
  525.     NAME_ELEMENT(KEY_SYSRQ),        NAME_ELEMENT(KEY_RIGHTALT),
  526.     NAME_ELEMENT(KEY_LINEFEED),     NAME_ELEMENT(KEY_HOME),
  527.     NAME_ELEMENT(KEY_UP),           NAME_ELEMENT(KEY_PAGEUP),
  528.     NAME_ELEMENT(KEY_LEFT),         NAME_ELEMENT(KEY_RIGHT),
  529.     NAME_ELEMENT(KEY_END),          NAME_ELEMENT(KEY_DOWN),
  530.     NAME_ELEMENT(KEY_PAGEDOWN),     NAME_ELEMENT(KEY_INSERT),
  531.     NAME_ELEMENT(KEY_DELETE),       NAME_ELEMENT(KEY_MACRO),
  532.     NAME_ELEMENT(KEY_MUTE),         NAME_ELEMENT(KEY_VOLUMEDOWN),
  533.     NAME_ELEMENT(KEY_VOLUMEUP),     NAME_ELEMENT(KEY_POWER),
  534.     NAME_ELEMENT(KEY_KPEQUAL),      NAME_ELEMENT(KEY_KPPLUSMINUS),
  535.     NAME_ELEMENT(KEY_PAUSE),        NAME_ELEMENT(KEY_KPCOMMA),
  536.     NAME_ELEMENT(KEY_HANGUEL),      NAME_ELEMENT(KEY_HANJA),
  537.     NAME_ELEMENT(KEY_YEN),          NAME_ELEMENT(KEY_LEFTMETA),
  538.     NAME_ELEMENT(KEY_RIGHTMETA),        NAME_ELEMENT(KEY_COMPOSE),
  539.     NAME_ELEMENT(KEY_STOP),         NAME_ELEMENT(KEY_AGAIN),
  540.     NAME_ELEMENT(KEY_PROPS),        NAME_ELEMENT(KEY_UNDO),
  541.     NAME_ELEMENT(KEY_FRONT),        NAME_ELEMENT(KEY_COPY),
  542.     NAME_ELEMENT(KEY_OPEN),         NAME_ELEMENT(KEY_PASTE),
  543.     NAME_ELEMENT(KEY_FIND),         NAME_ELEMENT(KEY_CUT),
  544.     NAME_ELEMENT(KEY_HELP),         NAME_ELEMENT(KEY_MENU),
  545.     NAME_ELEMENT(KEY_CALC),         NAME_ELEMENT(KEY_SETUP),
  546.     NAME_ELEMENT(KEY_SLEEP),        NAME_ELEMENT(KEY_WAKEUP),
  547.     NAME_ELEMENT(KEY_FILE),         NAME_ELEMENT(KEY_SENDFILE),
  548.     NAME_ELEMENT(KEY_DELETEFILE),       NAME_ELEMENT(KEY_XFER),
  549.     NAME_ELEMENT(KEY_PROG1),        NAME_ELEMENT(KEY_PROG2),
  550.     NAME_ELEMENT(KEY_WWW),          NAME_ELEMENT(KEY_MSDOS),
  551.     NAME_ELEMENT(KEY_COFFEE),       NAME_ELEMENT(KEY_DIRECTION),
  552.     NAME_ELEMENT(KEY_CYCLEWINDOWS),     NAME_ELEMENT(KEY_MAIL),
  553.     NAME_ELEMENT(KEY_BOOKMARKS),        NAME_ELEMENT(KEY_COMPUTER),
  554.     NAME_ELEMENT(KEY_BACK),         NAME_ELEMENT(KEY_FORWARD),
  555.     NAME_ELEMENT(KEY_CLOSECD),      NAME_ELEMENT(KEY_EJECTCD),
  556.     NAME_ELEMENT(KEY_EJECTCLOSECD),     NAME_ELEMENT(KEY_NEXTSONG),
  557.     NAME_ELEMENT(KEY_PLAYPAUSE),        NAME_ELEMENT(KEY_PREVIOUSSONG),
  558.     NAME_ELEMENT(KEY_STOPCD),       NAME_ELEMENT(KEY_RECORD),
  559.     NAME_ELEMENT(KEY_REWIND),       NAME_ELEMENT(KEY_PHONE),
  560.     NAME_ELEMENT(KEY_ISO),          NAME_ELEMENT(KEY_CONFIG),
  561.     NAME_ELEMENT(KEY_HOMEPAGE),     NAME_ELEMENT(KEY_REFRESH),
  562.     NAME_ELEMENT(KEY_EXIT),         NAME_ELEMENT(KEY_MOVE),
  563.     NAME_ELEMENT(KEY_EDIT),         NAME_ELEMENT(KEY_SCROLLUP),
  564.     NAME_ELEMENT(KEY_SCROLLDOWN),       NAME_ELEMENT(KEY_KPLEFTPAREN),
  565.     NAME_ELEMENT(KEY_KPRIGHTPAREN),     NAME_ELEMENT(KEY_F13),
  566.     NAME_ELEMENT(KEY_F14),          NAME_ELEMENT(KEY_F15),
  567.     NAME_ELEMENT(KEY_F16),          NAME_ELEMENT(KEY_F17),
  568.     NAME_ELEMENT(KEY_F18),          NAME_ELEMENT(KEY_F19),
  569.     NAME_ELEMENT(KEY_F20),          NAME_ELEMENT(KEY_F21),
  570.     NAME_ELEMENT(KEY_F22),          NAME_ELEMENT(KEY_F23),
  571.     NAME_ELEMENT(KEY_F24),          NAME_ELEMENT(KEY_PLAYCD),
  572.     NAME_ELEMENT(KEY_PAUSECD),      NAME_ELEMENT(KEY_PROG3),
  573.     NAME_ELEMENT(KEY_PROG4),        NAME_ELEMENT(KEY_SUSPEND),
  574.     NAME_ELEMENT(KEY_CLOSE),        NAME_ELEMENT(KEY_PLAY),
  575.     NAME_ELEMENT(KEY_FASTFORWARD),      NAME_ELEMENT(KEY_BASSBOOST),
  576.     NAME_ELEMENT(KEY_PRINT),        NAME_ELEMENT(KEY_HP),
  577.     NAME_ELEMENT(KEY_CAMERA),       NAME_ELEMENT(KEY_SOUND),
  578.     NAME_ELEMENT(KEY_QUESTION),     NAME_ELEMENT(KEY_EMAIL),
  579.     NAME_ELEMENT(KEY_CHAT),         NAME_ELEMENT(KEY_SEARCH),
  580.     NAME_ELEMENT(KEY_CONNECT),      NAME_ELEMENT(KEY_FINANCE),
  581.     NAME_ELEMENT(KEY_SPORT),        NAME_ELEMENT(KEY_SHOP),
  582.     NAME_ELEMENT(KEY_ALTERASE),     NAME_ELEMENT(KEY_CANCEL),
  583.     NAME_ELEMENT(KEY_BRIGHTNESSDOWN),   NAME_ELEMENT(KEY_BRIGHTNESSUP),
  584.     NAME_ELEMENT(KEY_MEDIA),        NAME_ELEMENT(KEY_UNKNOWN),
  585.     NAME_ELEMENT(KEY_OK),
  586.     NAME_ELEMENT(KEY_SELECT),       NAME_ELEMENT(KEY_GOTO),
  587.     NAME_ELEMENT(KEY_CLEAR),        NAME_ELEMENT(KEY_POWER2),
  588.     NAME_ELEMENT(KEY_OPTION),       NAME_ELEMENT(KEY_INFO),
  589.     NAME_ELEMENT(KEY_TIME),         NAME_ELEMENT(KEY_VENDOR),
  590.     NAME_ELEMENT(KEY_ARCHIVE),      NAME_ELEMENT(KEY_PROGRAM),
  591.     NAME_ELEMENT(KEY_CHANNEL),      NAME_ELEMENT(KEY_FAVORITES),
  592.     NAME_ELEMENT(KEY_EPG),          NAME_ELEMENT(KEY_PVR),
  593.     NAME_ELEMENT(KEY_MHP),          NAME_ELEMENT(KEY_LANGUAGE),
  594.     NAME_ELEMENT(KEY_TITLE),        NAME_ELEMENT(KEY_SUBTITLE),
  595.     NAME_ELEMENT(KEY_ANGLE),        NAME_ELEMENT(KEY_ZOOM),
  596.     NAME_ELEMENT(KEY_MODE),         NAME_ELEMENT(KEY_KEYBOARD),
  597.     NAME_ELEMENT(KEY_SCREEN),       NAME_ELEMENT(KEY_PC),
  598.     NAME_ELEMENT(KEY_TV),           NAME_ELEMENT(KEY_TV2),
  599.     NAME_ELEMENT(KEY_VCR),          NAME_ELEMENT(KEY_VCR2),
  600.     NAME_ELEMENT(KEY_SAT),          NAME_ELEMENT(KEY_SAT2),
  601.     NAME_ELEMENT(KEY_CD),           NAME_ELEMENT(KEY_TAPE),
  602.     NAME_ELEMENT(KEY_RADIO),        NAME_ELEMENT(KEY_TUNER),
  603.     NAME_ELEMENT(KEY_PLAYER),       NAME_ELEMENT(KEY_TEXT),
  604.     NAME_ELEMENT(KEY_DVD),          NAME_ELEMENT(KEY_AUX),
  605.     NAME_ELEMENT(KEY_MP3),          NAME_ELEMENT(KEY_AUDIO),
  606.     NAME_ELEMENT(KEY_VIDEO),        NAME_ELEMENT(KEY_DIRECTORY),
  607.     NAME_ELEMENT(KEY_LIST),         NAME_ELEMENT(KEY_MEMO),
  608.     NAME_ELEMENT(KEY_CALENDAR),     NAME_ELEMENT(KEY_RED),
  609.     NAME_ELEMENT(KEY_GREEN),        NAME_ELEMENT(KEY_YELLOW),
  610.     NAME_ELEMENT(KEY_BLUE),         NAME_ELEMENT(KEY_CHANNELUP),
  611.     NAME_ELEMENT(KEY_CHANNELDOWN),      NAME_ELEMENT(KEY_FIRST),
  612.     NAME_ELEMENT(KEY_LAST),         NAME_ELEMENT(KEY_AB),
  613.     NAME_ELEMENT(KEY_NEXT),         NAME_ELEMENT(KEY_RESTART),
  614.     NAME_ELEMENT(KEY_SLOW),         NAME_ELEMENT(KEY_SHUFFLE),
  615.     NAME_ELEMENT(KEY_BREAK),        NAME_ELEMENT(KEY_PREVIOUS),
  616.     NAME_ELEMENT(KEY_DIGITS),       NAME_ELEMENT(KEY_TEEN),
  617.     NAME_ELEMENT(KEY_TWEN),         NAME_ELEMENT(KEY_DEL_EOL),
  618.     NAME_ELEMENT(KEY_DEL_EOS),      NAME_ELEMENT(KEY_INS_LINE),
  619.     NAME_ELEMENT(KEY_DEL_LINE),
  620.     NAME_ELEMENT(KEY_VIDEOPHONE),       NAME_ELEMENT(KEY_GAMES),
  621.     NAME_ELEMENT(KEY_ZOOMIN),       NAME_ELEMENT(KEY_ZOOMOUT),
  622.     NAME_ELEMENT(KEY_ZOOMRESET),        NAME_ELEMENT(KEY_WORDPROCESSOR),
  623.     NAME_ELEMENT(KEY_EDITOR),       NAME_ELEMENT(KEY_SPREADSHEET),
  624.     NAME_ELEMENT(KEY_GRAPHICSEDITOR),   NAME_ELEMENT(KEY_PRESENTATION),
  625.     NAME_ELEMENT(KEY_DATABASE),     NAME_ELEMENT(KEY_NEWS),
  626.     NAME_ELEMENT(KEY_VOICEMAIL),        NAME_ELEMENT(KEY_ADDRESSBOOK),
  627.     NAME_ELEMENT(KEY_MESSENGER),        NAME_ELEMENT(KEY_DISPLAYTOGGLE),
  628.     NAME_ELEMENT(KEY_SPELLCHECK),       NAME_ELEMENT(KEY_LOGOFF),
  629.     NAME_ELEMENT(KEY_DOLLAR),       NAME_ELEMENT(KEY_EURO),
  630.     NAME_ELEMENT(KEY_FRAMEBACK),        NAME_ELEMENT(KEY_FRAMEFORWARD),
  631.     NAME_ELEMENT(KEY_CONTEXT_MENU),     NAME_ELEMENT(KEY_MEDIA_REPEAT),
  632.     NAME_ELEMENT(KEY_DEL_EOL),      NAME_ELEMENT(KEY_DEL_EOS),
  633.     NAME_ELEMENT(KEY_INS_LINE),     NAME_ELEMENT(KEY_DEL_LINE),
  634.     NAME_ELEMENT(KEY_FN),           NAME_ELEMENT(KEY_FN_ESC),
  635.     NAME_ELEMENT(KEY_FN_F1),        NAME_ELEMENT(KEY_FN_F2),
  636.     NAME_ELEMENT(KEY_FN_F3),        NAME_ELEMENT(KEY_FN_F4),
  637.     NAME_ELEMENT(KEY_FN_F5),        NAME_ELEMENT(KEY_FN_F6),
  638.     NAME_ELEMENT(KEY_FN_F7),        NAME_ELEMENT(KEY_FN_F8),
  639.     NAME_ELEMENT(KEY_FN_F9),        NAME_ELEMENT(KEY_FN_F10),
  640.     NAME_ELEMENT(KEY_FN_F11),       NAME_ELEMENT(KEY_FN_F12),
  641.     NAME_ELEMENT(KEY_FN_1),         NAME_ELEMENT(KEY_FN_2),
  642.     NAME_ELEMENT(KEY_FN_D),         NAME_ELEMENT(KEY_FN_E),
  643.     NAME_ELEMENT(KEY_FN_F),         NAME_ELEMENT(KEY_FN_S),
  644.     NAME_ELEMENT(KEY_FN_B),
  645.     NAME_ELEMENT(KEY_BRL_DOT1),     NAME_ELEMENT(KEY_BRL_DOT2),
  646.     NAME_ELEMENT(KEY_BRL_DOT3),     NAME_ELEMENT(KEY_BRL_DOT4),
  647.     NAME_ELEMENT(KEY_BRL_DOT5),     NAME_ELEMENT(KEY_BRL_DOT6),
  648.     NAME_ELEMENT(KEY_BRL_DOT7),     NAME_ELEMENT(KEY_BRL_DOT8),
  649.     NAME_ELEMENT(KEY_BRL_DOT9),     NAME_ELEMENT(KEY_BRL_DOT10),
  650.     NAME_ELEMENT(KEY_NUMERIC_0),        NAME_ELEMENT(KEY_NUMERIC_1),
  651.     NAME_ELEMENT(KEY_NUMERIC_2),        NAME_ELEMENT(KEY_NUMERIC_3),
  652.     NAME_ELEMENT(KEY_NUMERIC_4),        NAME_ELEMENT(KEY_NUMERIC_5),
  653.     NAME_ELEMENT(KEY_NUMERIC_6),        NAME_ELEMENT(KEY_NUMERIC_7),
  654.     NAME_ELEMENT(KEY_NUMERIC_8),        NAME_ELEMENT(KEY_NUMERIC_9),
  655.     NAME_ELEMENT(KEY_NUMERIC_STAR),     NAME_ELEMENT(KEY_NUMERIC_POUND),
  656.     NAME_ELEMENT(KEY_BATTERY),
  657.     NAME_ELEMENT(KEY_BLUETOOTH),        NAME_ELEMENT(KEY_BRIGHTNESS_CYCLE),
  658.     NAME_ELEMENT(KEY_BRIGHTNESS_ZERO),  NAME_ELEMENT(KEY_DASHBOARD),
  659.     NAME_ELEMENT(KEY_DISPLAY_OFF),      NAME_ELEMENT(KEY_DOCUMENTS),
  660.     NAME_ELEMENT(KEY_FORWARDMAIL),      NAME_ELEMENT(KEY_NEW),
  661.     NAME_ELEMENT(KEY_KBDILLUMDOWN),     NAME_ELEMENT(KEY_KBDILLUMUP),
  662.     NAME_ELEMENT(KEY_KBDILLUMTOGGLE),   NAME_ELEMENT(KEY_REDO),
  663.     NAME_ELEMENT(KEY_REPLY),        NAME_ELEMENT(KEY_SAVE),
  664.     NAME_ELEMENT(KEY_SCALE),        NAME_ELEMENT(KEY_SEND),
  665.     NAME_ELEMENT(KEY_SCREENLOCK),       NAME_ELEMENT(KEY_SWITCHVIDEOMODE),
  666.     NAME_ELEMENT(KEY_UWB),          NAME_ELEMENT(KEY_VIDEO_NEXT),
  667.     NAME_ELEMENT(KEY_VIDEO_PREV),       NAME_ELEMENT(KEY_WIMAX),
  668.     NAME_ELEMENT(KEY_WLAN),
  669. #ifdef KEY_RFKILL
  670.     NAME_ELEMENT(KEY_RFKILL),
  671. #endif
  672. #ifdef KEY_WPS_BUTTON
  673.     NAME_ELEMENT(KEY_WPS_BUTTON),
  674. #endif
  675. #ifdef KEY_TOUCHPAD_TOGGLE
  676.     NAME_ELEMENT(KEY_TOUCHPAD_TOGGLE),
  677.     NAME_ELEMENT(KEY_TOUCHPAD_ON),
  678.     NAME_ELEMENT(KEY_TOUCHPAD_OFF),
  679. #endif
  680.  
  681.     NAME_ELEMENT(BTN_0),            NAME_ELEMENT(BTN_1),
  682.     NAME_ELEMENT(BTN_2),            NAME_ELEMENT(BTN_3),
  683.     NAME_ELEMENT(BTN_4),            NAME_ELEMENT(BTN_5),
  684.     NAME_ELEMENT(BTN_6),            NAME_ELEMENT(BTN_7),
  685.     NAME_ELEMENT(BTN_8),            NAME_ELEMENT(BTN_9),
  686.     NAME_ELEMENT(BTN_LEFT),         NAME_ELEMENT(BTN_RIGHT),
  687.     NAME_ELEMENT(BTN_MIDDLE),       NAME_ELEMENT(BTN_SIDE),
  688.     NAME_ELEMENT(BTN_EXTRA),        NAME_ELEMENT(BTN_FORWARD),
  689.     NAME_ELEMENT(BTN_BACK),         NAME_ELEMENT(BTN_TASK),
  690.     NAME_ELEMENT(BTN_TRIGGER),      NAME_ELEMENT(BTN_THUMB),
  691.     NAME_ELEMENT(BTN_THUMB2),       NAME_ELEMENT(BTN_TOP),
  692.     NAME_ELEMENT(BTN_TOP2),         NAME_ELEMENT(BTN_PINKIE),
  693.     NAME_ELEMENT(BTN_BASE),         NAME_ELEMENT(BTN_BASE2),
  694.     NAME_ELEMENT(BTN_BASE3),        NAME_ELEMENT(BTN_BASE4),
  695.     NAME_ELEMENT(BTN_BASE5),        NAME_ELEMENT(BTN_BASE6),
  696.     NAME_ELEMENT(BTN_DEAD),         NAME_ELEMENT(BTN_A),
  697.     NAME_ELEMENT(BTN_B),            NAME_ELEMENT(BTN_C),
  698.     NAME_ELEMENT(BTN_X),            NAME_ELEMENT(BTN_Y),
  699.     NAME_ELEMENT(BTN_Z),            NAME_ELEMENT(BTN_TL),
  700.     NAME_ELEMENT(BTN_TR),           NAME_ELEMENT(BTN_TL2),
  701.     NAME_ELEMENT(BTN_TR2),          NAME_ELEMENT(BTN_SELECT),
  702.     NAME_ELEMENT(BTN_START),        NAME_ELEMENT(BTN_MODE),
  703.     NAME_ELEMENT(BTN_THUMBL),       NAME_ELEMENT(BTN_THUMBR),
  704.     NAME_ELEMENT(BTN_TOOL_PEN),     NAME_ELEMENT(BTN_TOOL_RUBBER),
  705.     NAME_ELEMENT(BTN_TOOL_BRUSH),       NAME_ELEMENT(BTN_TOOL_PENCIL),
  706.     NAME_ELEMENT(BTN_TOOL_AIRBRUSH),    NAME_ELEMENT(BTN_TOOL_FINGER),
  707.     NAME_ELEMENT(BTN_TOOL_MOUSE),       NAME_ELEMENT(BTN_TOOL_LENS),
  708.     NAME_ELEMENT(BTN_TOUCH),        NAME_ELEMENT(BTN_STYLUS),
  709.     NAME_ELEMENT(BTN_STYLUS2),      NAME_ELEMENT(BTN_TOOL_DOUBLETAP),
  710.     NAME_ELEMENT(BTN_TOOL_TRIPLETAP),   NAME_ELEMENT(BTN_TOOL_QUADTAP),
  711.     NAME_ELEMENT(BTN_GEAR_DOWN),
  712.     NAME_ELEMENT(BTN_GEAR_UP),
  713.  
  714. #ifdef BTN_TRIGGER_HAPPY
  715.     NAME_ELEMENT(BTN_TRIGGER_HAPPY1),   NAME_ELEMENT(BTN_TRIGGER_HAPPY11),
  716.     NAME_ELEMENT(BTN_TRIGGER_HAPPY2),   NAME_ELEMENT(BTN_TRIGGER_HAPPY12),
  717.     NAME_ELEMENT(BTN_TRIGGER_HAPPY3),   NAME_ELEMENT(BTN_TRIGGER_HAPPY13),
  718.     NAME_ELEMENT(BTN_TRIGGER_HAPPY4),   NAME_ELEMENT(BTN_TRIGGER_HAPPY14),
  719.     NAME_ELEMENT(BTN_TRIGGER_HAPPY5),   NAME_ELEMENT(BTN_TRIGGER_HAPPY15),
  720.     NAME_ELEMENT(BTN_TRIGGER_HAPPY6),   NAME_ELEMENT(BTN_TRIGGER_HAPPY16),
  721.     NAME_ELEMENT(BTN_TRIGGER_HAPPY7),   NAME_ELEMENT(BTN_TRIGGER_HAPPY17),
  722.     NAME_ELEMENT(BTN_TRIGGER_HAPPY8),   NAME_ELEMENT(BTN_TRIGGER_HAPPY18),
  723.     NAME_ELEMENT(BTN_TRIGGER_HAPPY9),   NAME_ELEMENT(BTN_TRIGGER_HAPPY19),
  724.     NAME_ELEMENT(BTN_TRIGGER_HAPPY10),  NAME_ELEMENT(BTN_TRIGGER_HAPPY20),
  725.  
  726.     NAME_ELEMENT(BTN_TRIGGER_HAPPY21),  NAME_ELEMENT(BTN_TRIGGER_HAPPY31),
  727.     NAME_ELEMENT(BTN_TRIGGER_HAPPY22),  NAME_ELEMENT(BTN_TRIGGER_HAPPY32),
  728.     NAME_ELEMENT(BTN_TRIGGER_HAPPY23),  NAME_ELEMENT(BTN_TRIGGER_HAPPY33),
  729.     NAME_ELEMENT(BTN_TRIGGER_HAPPY24),  NAME_ELEMENT(BTN_TRIGGER_HAPPY34),
  730.     NAME_ELEMENT(BTN_TRIGGER_HAPPY25),  NAME_ELEMENT(BTN_TRIGGER_HAPPY35),
  731.     NAME_ELEMENT(BTN_TRIGGER_HAPPY26),  NAME_ELEMENT(BTN_TRIGGER_HAPPY36),
  732.     NAME_ELEMENT(BTN_TRIGGER_HAPPY27),  NAME_ELEMENT(BTN_TRIGGER_HAPPY37),
  733.     NAME_ELEMENT(BTN_TRIGGER_HAPPY28),  NAME_ELEMENT(BTN_TRIGGER_HAPPY38),
  734.     NAME_ELEMENT(BTN_TRIGGER_HAPPY29),  NAME_ELEMENT(BTN_TRIGGER_HAPPY39),
  735.     NAME_ELEMENT(BTN_TRIGGER_HAPPY30),  NAME_ELEMENT(BTN_TRIGGER_HAPPY40),
  736. #endif
  737. };
  738.  
  739. static const char * const absval[6] = { "Value", "Min  ", "Max  ", "Fuzz ", "Flat ", "Resolution "};
  740.  
  741. static const char * const relatives[REL_MAX + 1] = {
  742.     [0 ... REL_MAX] = NULL,
  743.     NAME_ELEMENT(REL_X),            NAME_ELEMENT(REL_Y),
  744.     NAME_ELEMENT(REL_Z),            NAME_ELEMENT(REL_RX),
  745.     NAME_ELEMENT(REL_RY),           NAME_ELEMENT(REL_RZ),
  746.     NAME_ELEMENT(REL_HWHEEL),
  747.     NAME_ELEMENT(REL_DIAL),         NAME_ELEMENT(REL_WHEEL),
  748.     NAME_ELEMENT(REL_MISC),
  749. };
  750.  
  751. static const char * const absolutes[ABS_MAX + 1] = {
  752.     [0 ... ABS_MAX] = NULL,
  753.     NAME_ELEMENT(ABS_X),            NAME_ELEMENT(ABS_Y),
  754.     NAME_ELEMENT(ABS_Z),            NAME_ELEMENT(ABS_RX),
  755.     NAME_ELEMENT(ABS_RY),           NAME_ELEMENT(ABS_RZ),
  756.     NAME_ELEMENT(ABS_THROTTLE),     NAME_ELEMENT(ABS_RUDDER),
  757.     NAME_ELEMENT(ABS_WHEEL),        NAME_ELEMENT(ABS_GAS),
  758.     NAME_ELEMENT(ABS_BRAKE),        NAME_ELEMENT(ABS_HAT0X),
  759.     NAME_ELEMENT(ABS_HAT0Y),        NAME_ELEMENT(ABS_HAT1X),
  760.     NAME_ELEMENT(ABS_HAT1Y),        NAME_ELEMENT(ABS_HAT2X),
  761.     NAME_ELEMENT(ABS_HAT2Y),        NAME_ELEMENT(ABS_HAT3X),
  762.     NAME_ELEMENT(ABS_HAT3Y),        NAME_ELEMENT(ABS_PRESSURE),
  763.     NAME_ELEMENT(ABS_DISTANCE),     NAME_ELEMENT(ABS_TILT_X),
  764.     NAME_ELEMENT(ABS_TILT_Y),       NAME_ELEMENT(ABS_TOOL_WIDTH),
  765.     NAME_ELEMENT(ABS_VOLUME),       NAME_ELEMENT(ABS_MISC),
  766. #ifdef ABS_MT_BLOB_ID
  767.     NAME_ELEMENT(ABS_MT_TOUCH_MAJOR),
  768.     NAME_ELEMENT(ABS_MT_TOUCH_MINOR),
  769.     NAME_ELEMENT(ABS_MT_WIDTH_MAJOR),
  770.     NAME_ELEMENT(ABS_MT_WIDTH_MINOR),
  771.     NAME_ELEMENT(ABS_MT_ORIENTATION),
  772.     NAME_ELEMENT(ABS_MT_POSITION_X),
  773.     NAME_ELEMENT(ABS_MT_POSITION_Y),
  774.     NAME_ELEMENT(ABS_MT_TOOL_TYPE),
  775.     NAME_ELEMENT(ABS_MT_BLOB_ID),
  776. #endif
  777. #ifdef ABS_MT_TRACKING_ID
  778.     NAME_ELEMENT(ABS_MT_TRACKING_ID),
  779. #endif
  780. #ifdef ABS_MT_PRESSURE
  781.     NAME_ELEMENT(ABS_MT_PRESSURE),
  782. #endif
  783. #ifdef ABS_MT_SLOT
  784.     NAME_ELEMENT(ABS_MT_SLOT),
  785. #endif
  786.  
  787. };
  788.  
  789. static const char * const misc[MSC_MAX + 1] = {
  790.     [ 0 ... MSC_MAX] = NULL,
  791.     NAME_ELEMENT(MSC_SERIAL),       NAME_ELEMENT(MSC_PULSELED),
  792.     NAME_ELEMENT(MSC_GESTURE),      NAME_ELEMENT(MSC_RAW),
  793.     NAME_ELEMENT(MSC_SCAN),
  794. };
  795.  
  796. static const char * const leds[LED_MAX + 1] = {
  797.     [0 ... LED_MAX] = NULL,
  798.     NAME_ELEMENT(LED_NUML),         NAME_ELEMENT(LED_CAPSL),
  799.     NAME_ELEMENT(LED_SCROLLL),      NAME_ELEMENT(LED_COMPOSE),
  800.     NAME_ELEMENT(LED_KANA),         NAME_ELEMENT(LED_SLEEP),
  801.     NAME_ELEMENT(LED_SUSPEND),      NAME_ELEMENT(LED_MUTE),
  802.     NAME_ELEMENT(LED_MISC),
  803. };
  804.  
  805. static const char * const repeats[REP_MAX + 1] = {
  806.     [0 ... REP_MAX] = NULL,
  807.     NAME_ELEMENT(REP_DELAY),        NAME_ELEMENT(REP_PERIOD)
  808. };
  809.  
  810. static const char * const sounds[SND_MAX + 1] = {
  811.     [0 ... SND_MAX] = NULL,
  812.     NAME_ELEMENT(SND_CLICK),        NAME_ELEMENT(SND_BELL),
  813.     NAME_ELEMENT(SND_TONE)
  814. };
  815.  
  816. static const char * const syns[3] = {
  817.     NAME_ELEMENT(SYN_REPORT),
  818.     NAME_ELEMENT(SYN_CONFIG),
  819. #ifdef SYN_MT_REPORT
  820.     NAME_ELEMENT(SYN_MT_REPORT)
  821. #endif
  822. };
  823.  
  824. static const char * const switches[SW_MAX + 1] = {
  825.     [0 ... SW_MAX] = NULL,
  826.     NAME_ELEMENT(SW_LID),
  827.     NAME_ELEMENT(SW_TABLET_MODE),
  828.     NAME_ELEMENT(SW_HEADPHONE_INSERT),
  829.     NAME_ELEMENT(SW_RFKILL_ALL),
  830.     NAME_ELEMENT(SW_MICROPHONE_INSERT),
  831.     NAME_ELEMENT(SW_DOCK),
  832.     NAME_ELEMENT(SW_LINEOUT_INSERT),
  833.     NAME_ELEMENT(SW_JACK_PHYSICAL_INSERT),
  834. #ifdef SW_VIDEOOUT_INSERT
  835.     NAME_ELEMENT(SW_VIDEOOUT_INSERT),
  836. #endif
  837. #ifdef SW_CAMERA_LENS_COVER
  838.     NAME_ELEMENT(SW_CAMERA_LENS_COVER),
  839.     NAME_ELEMENT(SW_KEYPAD_SLIDE),
  840.     NAME_ELEMENT(SW_FRONT_PROXIMITY),
  841. #endif
  842. #ifdef SW_ROTATE_LOCK
  843.     NAME_ELEMENT(SW_ROTATE_LOCK),
  844. #endif
  845. };
  846.  
  847. static const char * const force[FF_MAX + 1] = {
  848.     [0 ... FF_MAX] = NULL,
  849.     NAME_ELEMENT(FF_RUMBLE),        NAME_ELEMENT(FF_PERIODIC),
  850.     NAME_ELEMENT(FF_CONSTANT),      NAME_ELEMENT(FF_SPRING),
  851.     NAME_ELEMENT(FF_FRICTION),      NAME_ELEMENT(FF_DAMPER),
  852.     NAME_ELEMENT(FF_INERTIA),       NAME_ELEMENT(FF_RAMP),
  853.     NAME_ELEMENT(FF_SQUARE),        NAME_ELEMENT(FF_TRIANGLE),
  854.     NAME_ELEMENT(FF_SINE),          NAME_ELEMENT(FF_SAW_UP),
  855.     NAME_ELEMENT(FF_SAW_DOWN),      NAME_ELEMENT(FF_CUSTOM),
  856.     NAME_ELEMENT(FF_GAIN),          NAME_ELEMENT(FF_AUTOCENTER),
  857. };
  858.  
  859. static const char * const forcestatus[FF_STATUS_MAX + 1] = {
  860.     [0 ... FF_STATUS_MAX] = NULL,
  861.     NAME_ELEMENT(FF_STATUS_STOPPED),    NAME_ELEMENT(FF_STATUS_PLAYING),
  862. };
  863.  
  864. static const char * const * const names[EV_MAX + 1] = {
  865.     [0 ... EV_MAX] = NULL,
  866.     [EV_SYN] = events,          [EV_KEY] = keys,
  867.     [EV_REL] = relatives,           [EV_ABS] = absolutes,
  868.     [EV_MSC] = misc,            [EV_LED] = leds,
  869.     [EV_SND] = sounds,          [EV_REP] = repeats,
  870.     [EV_SW] = switches,
  871.     [EV_FF] = force,            [EV_FF_STATUS] = forcestatus,
  872. };
  873.  
  874. /**
  875. * Convert a string to a specific key/snd/led/sw code. The string can either
  876. * be the name of the key in question (e.g. "SW_DOCK") or the numerical
  877. * value, either as decimal (e.g. "5") or as hex (e.g. "0x5").
  878. *
  879. * @param mode The mode being queried (key, snd, led, sw)
  880. * @param kstr The string to parse and convert
  881. *
  882. * @return The requested code's numerical value, or negative on error.
  883.  */
  884. static int get_keycode(const struct query_mode *query_mode, const char *kstr)
  885. {
  886.     if (isdigit(kstr[0])) {
  887.         unsigned long val;
  888.         errno = 0;
  889.         val = strtoul(kstr, NULL, 0);
  890.         if (errno) {
  891.             fprintf(stderr, "Could not interpret value %s\n", kstr);
  892.             return -1;
  893.         }
  894.         return (int) val;
  895.     } else {
  896.         const char * const *keynames = names[query_mode->event_type];
  897.         int i;
  898.  
  899.         for (i = 0; i < query_mode->max; i++) {
  900.             const char *name = keynames[i];
  901.             if (name && strcmp(name, kstr) == 0)
  902.                 return i;
  903.         }
  904.  
  905.         return -1;
  906.     }
  907. }
  908.  
  909. /**
  910.  * Filter for the AutoDevProbe scandir on /dev/input.
  911.  *
  912.  * @param dir The current directory entry provided by scandir.
  913.  *
  914.  * @return Non-zero if the given directory entry starts with "event", or zero
  915.  * otherwise.
  916.  */
  917. static int is_event_device(const struct dirent *dir) {
  918.     return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
  919. }
  920.  
  921. /**
  922.  * Scans all /dev/input/event*, display them and ask the user which one to
  923.  * open.
  924.  *
  925.  * @return The event device file name of the device file selected. This
  926.  * string is allocated and must be freed by the caller.
  927.  */
  928. static char* scan_devices(void)
  929. {
  930.     struct dirent **namelist;
  931.     int i, ndev, devnum;
  932.     char *filename;
  933.  
  934.     ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, alphasort);
  935.     if (ndev <= 0)
  936.         return NULL;
  937.  
  938.     fprintf(stderr, "Available devices:\n");
  939.  
  940.     for (i = 0; i < ndev; i++)
  941.     {
  942.         char fname[64];
  943.         int fd = -1;
  944.         char name[256] = "???";
  945.  
  946.         snprintf(fname, sizeof(fname),
  947.              "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
  948.         fd = open(fname, O_RDONLY);
  949.         if (fd < 0)
  950.             continue;
  951.         ioctl(fd, EVIOCGNAME(sizeof(name)), name);
  952.  
  953.         fprintf(stderr, "%s:    %s\n", fname, name);
  954.         close(fd);
  955.         free(namelist[i]);
  956.     }
  957.  
  958.     fprintf(stderr, "Select the device event number [0-%d]: ", ndev - 1);
  959.     scanf("%d", &devnum);
  960.  
  961.     if (devnum >= ndev || devnum < 0)
  962.         return NULL;
  963.  
  964.     asprintf(&filename, "%s/%s%d",
  965.          DEV_INPUT_EVENT, EVENT_DEV_NAME,
  966.          devnum);
  967.  
  968.     return filename;
  969. }
  970.  
  971. static int version(void)
  972. {
  973. #ifndef PACKAGE_VERSION
  974. #define PACKAGE_VERSION "<version undefined>"
  975. #endif
  976.     printf("%s %s\n", program_invocation_short_name, PACKAGE_VERSION);
  977.     return EXIT_SUCCESS;
  978. }
  979.  
  980.  
  981. /**
  982.  * Print usage information.
  983.  */
  984. static int usage(void)
  985. {
  986.     printf("USAGE:\n");
  987.     printf(" Grab mode:\n");
  988.     printf("   %s /dev/input/eventX\n", program_invocation_short_name);
  989.     printf("\n");
  990.     printf(" Query mode: (check exit code)\n");
  991.     printf("   %s --query /dev/input/eventX <type> <value>\n",
  992.         program_invocation_short_name);
  993.  
  994.     printf("\n");
  995.     printf("<type> is one of: EV_KEY, EV_SW, EV_LED, EV_SND\n");
  996.     printf("<value> can either be a numerical value, or the textual name of the\n");
  997.     printf("key/switch/LED/sound being queried (e.g. SW_DOCK).\n");
  998.  
  999.     return EXIT_FAILURE;
  1000. }
  1001.  
  1002. /**
  1003.  * Print additional information for absolute axes (min/max, current value,
  1004.  * etc.).
  1005.  *
  1006.  * @param fd The file descriptor to the device.
  1007.  * @param axis The axis identifier (e.g. ABS_X).
  1008.  */
  1009. static size_t snprint_absdata(char *device_info, size_t bounds, int fd, int axis)
  1010. {
  1011.     int abs[6] = {0};
  1012.     int k;
  1013.         char *beg=device_info;
  1014.         char *last=device_info;
  1015.  
  1016.     ioctl(fd, EVIOCGABS(axis), abs);
  1017.     for (k = 0; k < 6; k++)
  1018.         if ((k < 3) || abs[k]) {
  1019.             device_info+=snprintf(device_info,bounds,"      %s %6d\n", absval[k], abs[k]);
  1020.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1021. }
  1022.  
  1023.     return device_info - beg;
  1024. }
  1025.  
  1026. /**
  1027.  * Print static device information (no events). This information includes
  1028.  * version numbers, device name and all bits supported by this device.
  1029.  *
  1030.  * @param fd The file descriptor to the device.
  1031.  * @return 0 on success or 1 otherwise.
  1032.  */
  1033. int sprint_device_info(char *device_info, int fd, size_t bounds)
  1034. {
  1035.     int i, j;
  1036.     int version;
  1037.     unsigned short id[4];
  1038.     char name[256] = "Unknown";
  1039.     unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
  1040.         char *last=device_info;
  1041.  
  1042.     if (ioctl(fd, EVIOCGVERSION, &version)) {
  1043.         perror("evtest: can't get version");
  1044.         return 1;
  1045.     }
  1046.  
  1047.     device_info+=snprintf(device_info,bounds,"Input driver version is %d.%d.%d\n",
  1048.         version >> 16, (version >> 8) & 0xff, version & 0xff);
  1049.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1050.  
  1051.     ioctl(fd, EVIOCGID, id);
  1052.     device_info+=snprintf(device_info,bounds,"Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
  1053.         id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]);
  1054.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1055.  
  1056.     ioctl(fd, EVIOCGNAME(sizeof(name)), name);
  1057.     device_info+=snprintf(device_info,bounds,"Input device name: \"%s\"\n", name);
  1058.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1059.  
  1060.     memset(bit, 0, sizeof(bit));
  1061.     ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
  1062.     device_info+=snprintf(device_info,bounds,"Supported events:\n");
  1063.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1064.  
  1065.     for (i = 0; i < EV_MAX; i++)
  1066.         if (test_bit(i, bit[0])) {
  1067.             device_info+=snprintf(device_info,bounds,"  Event type %d (%s)\n", i, events[i] ? events[i] : "?");
  1068.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1069.             if (!i) continue;
  1070.             ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
  1071.             for (j = 0; j < KEY_MAX; j++)
  1072.                 if (test_bit(j, bit[i])) {
  1073.                     device_info+=snprintf(device_info,bounds,"    Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
  1074.                     if (i == EV_ABS) {
  1075.                         device_info+=snprint_absdata(device_info,bounds,fd, j);
  1076.     bounds-=device_info-last; if(bounds<0) return -1; last=device_info;
  1077. }
  1078.                 }
  1079.         }
  1080.  
  1081.     return 0;
  1082. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement