diff --git a/build.linux64ARMv8/squeak.stack.spur/build.debug/mvm b/build.linux64ARMv8/squeak.stack.spur/build.debug/mvm index 94796c22d2..026d433109 100755 --- a/build.linux64ARMv8/squeak.stack.spur/build.debug/mvm +++ b/build.linux64ARMv8/squeak.stack.spur/build.debug/mvm @@ -2,7 +2,12 @@ set -e # debug Stack Spur VM with VM profiler and threaded heartbeat INSTALLDIR=sqstkspur64linuxhtDebug -OPT="-g3 -O0 -DDEBUGVM=1" +# MUSL is not libc +if [ "$MUSL" = "" ]; then +OPT="-g3 -O1 -DNDEBUG -DDEBUGVM=1" +else +OPT="-g3 -O1 -DNDEBUG -DDEBUGVM=1 -DMUSL -D_GNU_SOURCE" +fi if [ $# -ge 1 ]; then INSTALLDIR="$1"; shift diff --git a/build.linux64ARMv8/squeak.stack.spur/build/mvm b/build.linux64ARMv8/squeak.stack.spur/build/mvm index 351bdc9420..6be7e3a3cb 100755 --- a/build.linux64ARMv8/squeak.stack.spur/build/mvm +++ b/build.linux64ARMv8/squeak.stack.spur/build/mvm @@ -2,7 +2,12 @@ set -e # Stack Spur VM with VM profiler and threaded heartbeat INSTALLDIR=sqstkspur64linuxht -OPT="-g -O2 -DNDEBUG -DDEBUGVM=0" +# MUSL is not libc +if [ "$MUSL" = "" ]; then +OPT="-g -O1 -DNDEBUG -DDEBUGVM=0" +else +OPT="-g -O1 -DNDEBUG -DDEBUGVM=0 -DMUSL -D_GNU_SOURCE" +fi if [ $# -ge 1 ]; then INSTALLDIR="$1"; shift @@ -19,7 +24,8 @@ test -f plugins.ext || (test -f ../plugins.ext && cp -p ../plugins.ext . || cp - test -f config.h || ../../../platforms/unix/config/configure \ --with-vmversion=5.0 \ --with-src=spurstack64src --disable-cogit \ - --without-vm-display-fbdev --without-npsqueak \ + --without-vm-display-fbdev \ + --without-npsqueak \ TARGET_ARCH="-march=armv8-a" \ CFLAGS="$OPT -D__ARM_ARCH_ISA_A64 -DARM64 -D__arm__ -D__arm64__ -D__aarch64__" rm -f vm/sqUnixMain.o # nuke version info diff --git a/platforms/Cross/plugins/sqPluginsSCCSVersion.h b/platforms/Cross/plugins/sqPluginsSCCSVersion.h old mode 100644 new mode 100755 diff --git a/platforms/Cross/vm/sqSCCSVersion.h b/platforms/Cross/vm/sqSCCSVersion.h old mode 100644 new mode 100755 index e224fed698..4d8fa8ffdd --- a/platforms/Cross/vm/sqSCCSVersion.h +++ b/platforms/Cross/vm/sqSCCSVersion.h @@ -28,13 +28,13 @@ #if SUBVERSION # define PREFIX "r" -static char SvnRawRevisionString[] = "$Rev$"; +static char SvnRawRevisionString[] = "$Rev: 201911192350 $"; # define REV_START (SvnRawRevisionString + 6) -static char SvnRawRevisionDate[] = "$Date$"; +static char SvnRawRevisionDate[] = "$Date: Tue Nov 19 15:50:02 2019 -0800 $"; # define DATE_START (SvnRawRevisionDate + 7) -static char SvnRawRepositoryURL[] = "$URL$"; +static char SvnRawRepositoryURL[] = "$URL: kendi3he@penguin:OpenSmalltalk/oscogvm $"; # define URL_START (SvnRawRepositoryURL + 6) static char * @@ -71,16 +71,16 @@ revisionShortHash() { return "N.A."; } # undef URL_START #elif GIT # define PREFIX "" -static char GitRawRevisionString[] = "$Rev$"; +static char GitRawRevisionString[] = "$Rev: 201911192350 $"; # define REV_START (GitRawRevisionString + 6) -static char GitRawRevisionDate[] = "$Date$"; +static char GitRawRevisionDate[] = "$Date: Tue Nov 19 15:50:02 2019 -0800 $"; # define DATE_START (GitRawRevisionDate + 7) -static char GitRawRepositoryURL[] = "$URL$"; +static char GitRawRepositoryURL[] = "$URL: kendi3he@penguin:OpenSmalltalk/oscogvm $"; # define URL_START (GitRawRepositoryURL + 6) -static char GitRawRevisionShortHash[] = "$CommitHash$"; +static char GitRawRevisionShortHash[] = "$CommitHash: 9336eea43 $"; # define SHORTHASH_START (GitRawRevisionShortHash + 13) static char * diff --git a/platforms/Cross/vm/sqVirtualMachine.c b/platforms/Cross/vm/sqVirtualMachine.c index c9209c63bf..4b199332d1 100755 --- a/platforms/Cross/vm/sqVirtualMachine.c +++ b/platforms/Cross/vm/sqVirtualMachine.c @@ -550,9 +550,12 @@ struct VirtualMachine* sqGetInterpreterProxy(void) /* This lives here for now but belongs somewhere else. * platforms/Cross/vm/sqStuff.c?? */ + +#ifndef MUSL #define STDOUT_STACK_SZ 5 static int stdoutStackIdx = -1; static FILE stdoutStack[STDOUT_STACK_SZ]; +#endif /* N.B. As of cygwin 1.5.25 fopen("crash.dmp","a") DOES NOT WORK! crash.dmp * contains garbled output as if the file pointer gets set to the start of the @@ -576,6 +579,7 @@ fopen_for_append(char *filename) # define fopen_for_append(filename) fopen(filename,"a+") #endif +#ifndef MUSL void pushOutputFile(char *filenameOrStdioIndex) { @@ -625,6 +629,7 @@ popOutputFile() } *stdout = stdoutStack[stdoutStackIdx--]; } +#endif void printPhaseTime(int phase) diff --git a/platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c b/platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c index 08a40e84c1..9c37d1e01b 100644 --- a/platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c +++ b/platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c @@ -213,7 +213,8 @@ ioInitSecurity(void) if (imagePathLen) strncpy(secureUserDirectory, imageName, imagePathLen); else { - getwd(secureUserDirectory); +/*@@MUSL@@*/ + getcwd(secureUserDirectory, MAXPATHLEN); imagePathLen = strlen(secureUserDirectory); } diff --git a/platforms/unix/vm/makeEvTest.sh b/platforms/unix/vm/makeEvTest.sh new file mode 100755 index 0000000000..1cf66659e1 --- /dev/null +++ b/platforms/unix/vm/makeEvTest.sh @@ -0,0 +1,7 @@ +#!/bin/bash +export LSB_FIRST=1 +export TARGET_ARCH="-march=armv8-a" +export CFLAGS=" -D__ARM_ARCH_ISA_A64 -DARM64 -D__arm__ -D__arm64__ -D__aarch64__" +export INCLUDES="-I/home/kend/OpenSmalltalk/kens-vm/src/vm -I/home/kend/OpenSmalltalk/kens-vm/platforms/Cross/vm -I/home/kend/OpenSmalltalk/kens-vm/platforms/unix/vm -I/home/kend/OpenSmalltalk/kens-vm/build.linux64ARMv8/squeak.stack.spur/build " +gcc -o evtest $TARGET_ARCH $CFLAGS $INCLUDES sqEVTest.c +echo "[Hopefully] compiled evtest" diff --git a/platforms/unix/vm/sqEVTest.c b/platforms/unix/vm/sqEVTest.c new file mode 100644 index 0000000000..d00437fe5c --- /dev/null +++ b/platforms/unix/vm/sqEVTest.c @@ -0,0 +1,1384 @@ +/* + * Copyright (c) 1999-2000 Vojtech Pavlik + * Copyright (c) 2009-2011 Red Hat, Inc + */ + +/** + * @file + * Event device test program + * + * evtest prints the capabilities on the kernel devices in /dev/input/eventX + * and their events. Its primary purpose is for kernel or X driver + * debugging. + * + * See INSTALL for installation details or manually compile with + * gcc -o evtest evtest.c + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic + */ + +#define _GNU_SOURCE /* for asprintf */ +#include +#include + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* PATH_MAX */ + +#ifndef input_event_sec +#define input_event_sec time.tv_sec +#define input_event_usec time.tv_usec +#endif + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define BIT(x) (1UL<> OFF(bit)) & 1) + +#define DEV_INPUT_EVENT "/dev/input" +#define EVENT_DEV_NAME "event" + +#ifndef EV_SYN +#define EV_SYN 0 +#endif +#ifndef SYN_MAX +#define SYN_MAX 3 +#define SYN_CNT (SYN_MAX + 1) +#endif +#ifndef SYN_MT_REPORT +#define SYN_MT_REPORT 2 +#endif +#ifndef SYN_DROPPED +#define SYN_DROPPED 3 +#endif + +#define NAME_ELEMENT(element) [element] = #element + +enum evtest_mode { + MODE_CAPTURE, + MODE_QUERY, + MODE_VERSION, +}; + +static const struct query_mode { + const char *name; + int event_type; + int max; + int rq; +} query_modes[] = { + { "EV_KEY", EV_KEY, KEY_MAX, EVIOCGKEY(KEY_MAX) }, + { "EV_LED", EV_LED, LED_MAX, EVIOCGLED(LED_MAX) }, + { "EV_SND", EV_SND, SND_MAX, EVIOCGSND(SND_MAX) }, + { "EV_SW", EV_SW, SW_MAX, EVIOCGSW(SW_MAX) }, +}; + +static int grab_flag = 0; +static volatile sig_atomic_t stop = 0; + +static void interrupt_handler(int sig) +{ + stop = 1; +} + +/** + * Look up an entry in the query_modes table by its textual name. + * + * @param mode The name of the entry to be found. + * + * @return The requested query_mode, or NULL if it could not be found. + */ +static const struct query_mode *find_query_mode_by_name(const char *name) +{ + int i; + for (i = 0; i < sizeof(query_modes) / sizeof(*query_modes); i++) { + const struct query_mode *mode = &query_modes[i]; + if (strcmp(mode->name, name) == 0) + return mode; + } + return NULL; +} + +/** + * Look up an entry in the query_modes table by value. + * + * @param event_type The value of the entry to be found. + * + * @return The requested query_mode, or NULL if it could not be found. + */ +static const struct query_mode *find_query_mode_by_value(int event_type) +{ + int i; + for (i = 0; i < sizeof(query_modes) / sizeof(*query_modes); i++) { + const struct query_mode *mode = &query_modes[i]; + if (mode->event_type == event_type) + return mode; + } + return NULL; +} + +/** + * Find a query_mode based on a string identifier. The string can either + * be a numerical value (e.g. "5") or the name of the event type in question + * (e.g. "EV_SW"). + * + * @param query_mode The mode to search for + * + * @return The requested code's numerical value, or negative on error. + */ +static const struct query_mode *find_query_mode(const char *query_mode) +{ + if (isdigit(query_mode[0])) { + unsigned long val; + errno = 0; + val = strtoul(query_mode, NULL, 0); + if (errno) + return NULL; + return find_query_mode_by_value(val); + } else { + return find_query_mode_by_name(query_mode); + } +} + +static const char * const events[EV_MAX + 1] = { + [0 ... EV_MAX] = NULL, + NAME_ELEMENT(EV_SYN), NAME_ELEMENT(EV_KEY), + NAME_ELEMENT(EV_REL), NAME_ELEMENT(EV_ABS), + NAME_ELEMENT(EV_MSC), NAME_ELEMENT(EV_LED), + NAME_ELEMENT(EV_SND), NAME_ELEMENT(EV_REP), + NAME_ELEMENT(EV_FF), NAME_ELEMENT(EV_PWR), + NAME_ELEMENT(EV_FF_STATUS), NAME_ELEMENT(EV_SW), +}; + +static const int maxval[EV_MAX + 1] = { + [0 ... EV_MAX] = -1, + [EV_SYN] = SYN_MAX, + [EV_KEY] = KEY_MAX, + [EV_REL] = REL_MAX, + [EV_ABS] = ABS_MAX, + [EV_MSC] = MSC_MAX, + [EV_SW] = SW_MAX, + [EV_LED] = LED_MAX, + [EV_SND] = SND_MAX, + [EV_REP] = REP_MAX, + [EV_FF] = FF_MAX, + [EV_FF_STATUS] = FF_STATUS_MAX, +}; + + +#ifdef INPUT_PROP_SEMI_MT +static const char * const props[INPUT_PROP_MAX + 1] = { + [0 ... INPUT_PROP_MAX] = NULL, + NAME_ELEMENT(INPUT_PROP_POINTER), + NAME_ELEMENT(INPUT_PROP_DIRECT), + NAME_ELEMENT(INPUT_PROP_BUTTONPAD), + NAME_ELEMENT(INPUT_PROP_SEMI_MT), +#ifdef INPUT_PROP_TOPBUTTONPAD + NAME_ELEMENT(INPUT_PROP_TOPBUTTONPAD), +#endif +#ifdef INPUT_PROP_POINTING_STICK + NAME_ELEMENT(INPUT_PROP_POINTING_STICK), +#endif +#ifdef INPUT_PROP_ACCELEROMETER + NAME_ELEMENT(INPUT_PROP_ACCELEROMETER), +#endif +}; +#endif + +static const char * const keys[KEY_MAX + 1] = { + [0 ... KEY_MAX] = NULL, + NAME_ELEMENT(KEY_RESERVED), NAME_ELEMENT(KEY_ESC), + NAME_ELEMENT(KEY_1), NAME_ELEMENT(KEY_2), + NAME_ELEMENT(KEY_3), NAME_ELEMENT(KEY_4), + NAME_ELEMENT(KEY_5), NAME_ELEMENT(KEY_6), + NAME_ELEMENT(KEY_7), NAME_ELEMENT(KEY_8), + NAME_ELEMENT(KEY_9), NAME_ELEMENT(KEY_0), + NAME_ELEMENT(KEY_MINUS), NAME_ELEMENT(KEY_EQUAL), + NAME_ELEMENT(KEY_BACKSPACE), NAME_ELEMENT(KEY_TAB), + NAME_ELEMENT(KEY_Q), NAME_ELEMENT(KEY_W), + NAME_ELEMENT(KEY_E), NAME_ELEMENT(KEY_R), + NAME_ELEMENT(KEY_T), NAME_ELEMENT(KEY_Y), + NAME_ELEMENT(KEY_U), NAME_ELEMENT(KEY_I), + NAME_ELEMENT(KEY_O), NAME_ELEMENT(KEY_P), + NAME_ELEMENT(KEY_LEFTBRACE), NAME_ELEMENT(KEY_RIGHTBRACE), + NAME_ELEMENT(KEY_ENTER), NAME_ELEMENT(KEY_LEFTCTRL), + NAME_ELEMENT(KEY_A), NAME_ELEMENT(KEY_S), + NAME_ELEMENT(KEY_D), NAME_ELEMENT(KEY_F), + NAME_ELEMENT(KEY_G), NAME_ELEMENT(KEY_H), + NAME_ELEMENT(KEY_J), NAME_ELEMENT(KEY_K), + NAME_ELEMENT(KEY_L), NAME_ELEMENT(KEY_SEMICOLON), + NAME_ELEMENT(KEY_APOSTROPHE), NAME_ELEMENT(KEY_GRAVE), + NAME_ELEMENT(KEY_LEFTSHIFT), NAME_ELEMENT(KEY_BACKSLASH), + NAME_ELEMENT(KEY_Z), NAME_ELEMENT(KEY_X), + NAME_ELEMENT(KEY_C), NAME_ELEMENT(KEY_V), + NAME_ELEMENT(KEY_B), NAME_ELEMENT(KEY_N), + NAME_ELEMENT(KEY_M), NAME_ELEMENT(KEY_COMMA), + NAME_ELEMENT(KEY_DOT), NAME_ELEMENT(KEY_SLASH), + NAME_ELEMENT(KEY_RIGHTSHIFT), NAME_ELEMENT(KEY_KPASTERISK), + NAME_ELEMENT(KEY_LEFTALT), NAME_ELEMENT(KEY_SPACE), + NAME_ELEMENT(KEY_CAPSLOCK), NAME_ELEMENT(KEY_F1), + NAME_ELEMENT(KEY_F2), NAME_ELEMENT(KEY_F3), + NAME_ELEMENT(KEY_F4), NAME_ELEMENT(KEY_F5), + NAME_ELEMENT(KEY_F6), NAME_ELEMENT(KEY_F7), + NAME_ELEMENT(KEY_F8), NAME_ELEMENT(KEY_F9), + NAME_ELEMENT(KEY_F10), NAME_ELEMENT(KEY_NUMLOCK), + NAME_ELEMENT(KEY_SCROLLLOCK), NAME_ELEMENT(KEY_KP7), + NAME_ELEMENT(KEY_KP8), NAME_ELEMENT(KEY_KP9), + NAME_ELEMENT(KEY_KPMINUS), NAME_ELEMENT(KEY_KP4), + NAME_ELEMENT(KEY_KP5), NAME_ELEMENT(KEY_KP6), + NAME_ELEMENT(KEY_KPPLUS), NAME_ELEMENT(KEY_KP1), + NAME_ELEMENT(KEY_KP2), NAME_ELEMENT(KEY_KP3), + NAME_ELEMENT(KEY_KP0), NAME_ELEMENT(KEY_KPDOT), + NAME_ELEMENT(KEY_ZENKAKUHANKAKU), NAME_ELEMENT(KEY_102ND), + NAME_ELEMENT(KEY_F11), NAME_ELEMENT(KEY_F12), + NAME_ELEMENT(KEY_RO), NAME_ELEMENT(KEY_KATAKANA), + NAME_ELEMENT(KEY_HIRAGANA), NAME_ELEMENT(KEY_HENKAN), + NAME_ELEMENT(KEY_KATAKANAHIRAGANA), NAME_ELEMENT(KEY_MUHENKAN), + NAME_ELEMENT(KEY_KPJPCOMMA), NAME_ELEMENT(KEY_KPENTER), + NAME_ELEMENT(KEY_RIGHTCTRL), NAME_ELEMENT(KEY_KPSLASH), + NAME_ELEMENT(KEY_SYSRQ), NAME_ELEMENT(KEY_RIGHTALT), + NAME_ELEMENT(KEY_LINEFEED), NAME_ELEMENT(KEY_HOME), + NAME_ELEMENT(KEY_UP), NAME_ELEMENT(KEY_PAGEUP), + NAME_ELEMENT(KEY_LEFT), NAME_ELEMENT(KEY_RIGHT), + NAME_ELEMENT(KEY_END), NAME_ELEMENT(KEY_DOWN), + NAME_ELEMENT(KEY_PAGEDOWN), NAME_ELEMENT(KEY_INSERT), + NAME_ELEMENT(KEY_DELETE), NAME_ELEMENT(KEY_MACRO), + NAME_ELEMENT(KEY_MUTE), NAME_ELEMENT(KEY_VOLUMEDOWN), + NAME_ELEMENT(KEY_VOLUMEUP), NAME_ELEMENT(KEY_POWER), + NAME_ELEMENT(KEY_KPEQUAL), NAME_ELEMENT(KEY_KPPLUSMINUS), + NAME_ELEMENT(KEY_PAUSE), NAME_ELEMENT(KEY_KPCOMMA), + NAME_ELEMENT(KEY_HANGUEL), NAME_ELEMENT(KEY_HANJA), + NAME_ELEMENT(KEY_YEN), NAME_ELEMENT(KEY_LEFTMETA), + NAME_ELEMENT(KEY_RIGHTMETA), NAME_ELEMENT(KEY_COMPOSE), + NAME_ELEMENT(KEY_STOP), NAME_ELEMENT(KEY_AGAIN), + NAME_ELEMENT(KEY_PROPS), NAME_ELEMENT(KEY_UNDO), + NAME_ELEMENT(KEY_FRONT), NAME_ELEMENT(KEY_COPY), + NAME_ELEMENT(KEY_OPEN), NAME_ELEMENT(KEY_PASTE), + NAME_ELEMENT(KEY_FIND), NAME_ELEMENT(KEY_CUT), + NAME_ELEMENT(KEY_HELP), NAME_ELEMENT(KEY_MENU), + NAME_ELEMENT(KEY_CALC), NAME_ELEMENT(KEY_SETUP), + NAME_ELEMENT(KEY_SLEEP), NAME_ELEMENT(KEY_WAKEUP), + NAME_ELEMENT(KEY_FILE), NAME_ELEMENT(KEY_SENDFILE), + NAME_ELEMENT(KEY_DELETEFILE), NAME_ELEMENT(KEY_XFER), + NAME_ELEMENT(KEY_PROG1), NAME_ELEMENT(KEY_PROG2), + NAME_ELEMENT(KEY_WWW), NAME_ELEMENT(KEY_MSDOS), + NAME_ELEMENT(KEY_COFFEE), NAME_ELEMENT(KEY_DIRECTION), + NAME_ELEMENT(KEY_CYCLEWINDOWS), NAME_ELEMENT(KEY_MAIL), + NAME_ELEMENT(KEY_BOOKMARKS), NAME_ELEMENT(KEY_COMPUTER), + NAME_ELEMENT(KEY_BACK), NAME_ELEMENT(KEY_FORWARD), + NAME_ELEMENT(KEY_CLOSECD), NAME_ELEMENT(KEY_EJECTCD), + NAME_ELEMENT(KEY_EJECTCLOSECD), NAME_ELEMENT(KEY_NEXTSONG), + NAME_ELEMENT(KEY_PLAYPAUSE), NAME_ELEMENT(KEY_PREVIOUSSONG), + NAME_ELEMENT(KEY_STOPCD), NAME_ELEMENT(KEY_RECORD), + NAME_ELEMENT(KEY_REWIND), NAME_ELEMENT(KEY_PHONE), + NAME_ELEMENT(KEY_ISO), NAME_ELEMENT(KEY_CONFIG), + NAME_ELEMENT(KEY_HOMEPAGE), NAME_ELEMENT(KEY_REFRESH), + NAME_ELEMENT(KEY_EXIT), NAME_ELEMENT(KEY_MOVE), + NAME_ELEMENT(KEY_EDIT), NAME_ELEMENT(KEY_SCROLLUP), + NAME_ELEMENT(KEY_SCROLLDOWN), NAME_ELEMENT(KEY_KPLEFTPAREN), + NAME_ELEMENT(KEY_KPRIGHTPAREN), NAME_ELEMENT(KEY_F13), + NAME_ELEMENT(KEY_F14), NAME_ELEMENT(KEY_F15), + NAME_ELEMENT(KEY_F16), NAME_ELEMENT(KEY_F17), + NAME_ELEMENT(KEY_F18), NAME_ELEMENT(KEY_F19), + NAME_ELEMENT(KEY_F20), NAME_ELEMENT(KEY_F21), + NAME_ELEMENT(KEY_F22), NAME_ELEMENT(KEY_F23), + NAME_ELEMENT(KEY_F24), NAME_ELEMENT(KEY_PLAYCD), + NAME_ELEMENT(KEY_PAUSECD), NAME_ELEMENT(KEY_PROG3), + NAME_ELEMENT(KEY_PROG4), NAME_ELEMENT(KEY_SUSPEND), + NAME_ELEMENT(KEY_CLOSE), NAME_ELEMENT(KEY_PLAY), + NAME_ELEMENT(KEY_FASTFORWARD), NAME_ELEMENT(KEY_BASSBOOST), + NAME_ELEMENT(KEY_PRINT), NAME_ELEMENT(KEY_HP), + NAME_ELEMENT(KEY_CAMERA), NAME_ELEMENT(KEY_SOUND), + NAME_ELEMENT(KEY_QUESTION), NAME_ELEMENT(KEY_EMAIL), + NAME_ELEMENT(KEY_CHAT), NAME_ELEMENT(KEY_SEARCH), + NAME_ELEMENT(KEY_CONNECT), NAME_ELEMENT(KEY_FINANCE), + NAME_ELEMENT(KEY_SPORT), NAME_ELEMENT(KEY_SHOP), + NAME_ELEMENT(KEY_ALTERASE), NAME_ELEMENT(KEY_CANCEL), + NAME_ELEMENT(KEY_BRIGHTNESSDOWN), NAME_ELEMENT(KEY_BRIGHTNESSUP), + NAME_ELEMENT(KEY_MEDIA), NAME_ELEMENT(KEY_UNKNOWN), + NAME_ELEMENT(KEY_OK), + NAME_ELEMENT(KEY_SELECT), NAME_ELEMENT(KEY_GOTO), + NAME_ELEMENT(KEY_CLEAR), NAME_ELEMENT(KEY_POWER2), + NAME_ELEMENT(KEY_OPTION), NAME_ELEMENT(KEY_INFO), + NAME_ELEMENT(KEY_TIME), NAME_ELEMENT(KEY_VENDOR), + NAME_ELEMENT(KEY_ARCHIVE), NAME_ELEMENT(KEY_PROGRAM), + NAME_ELEMENT(KEY_CHANNEL), NAME_ELEMENT(KEY_FAVORITES), + NAME_ELEMENT(KEY_EPG), NAME_ELEMENT(KEY_PVR), + NAME_ELEMENT(KEY_MHP), NAME_ELEMENT(KEY_LANGUAGE), + NAME_ELEMENT(KEY_TITLE), NAME_ELEMENT(KEY_SUBTITLE), + NAME_ELEMENT(KEY_ANGLE), NAME_ELEMENT(KEY_ZOOM), + NAME_ELEMENT(KEY_MODE), NAME_ELEMENT(KEY_KEYBOARD), + NAME_ELEMENT(KEY_SCREEN), NAME_ELEMENT(KEY_PC), + NAME_ELEMENT(KEY_TV), NAME_ELEMENT(KEY_TV2), + NAME_ELEMENT(KEY_VCR), NAME_ELEMENT(KEY_VCR2), + NAME_ELEMENT(KEY_SAT), NAME_ELEMENT(KEY_SAT2), + NAME_ELEMENT(KEY_CD), NAME_ELEMENT(KEY_TAPE), + NAME_ELEMENT(KEY_RADIO), NAME_ELEMENT(KEY_TUNER), + NAME_ELEMENT(KEY_PLAYER), NAME_ELEMENT(KEY_TEXT), + NAME_ELEMENT(KEY_DVD), NAME_ELEMENT(KEY_AUX), + NAME_ELEMENT(KEY_MP3), NAME_ELEMENT(KEY_AUDIO), + NAME_ELEMENT(KEY_VIDEO), NAME_ELEMENT(KEY_DIRECTORY), + NAME_ELEMENT(KEY_LIST), NAME_ELEMENT(KEY_MEMO), + NAME_ELEMENT(KEY_CALENDAR), NAME_ELEMENT(KEY_RED), + NAME_ELEMENT(KEY_GREEN), NAME_ELEMENT(KEY_YELLOW), + NAME_ELEMENT(KEY_BLUE), NAME_ELEMENT(KEY_CHANNELUP), + NAME_ELEMENT(KEY_CHANNELDOWN), NAME_ELEMENT(KEY_FIRST), + NAME_ELEMENT(KEY_LAST), NAME_ELEMENT(KEY_AB), + NAME_ELEMENT(KEY_NEXT), NAME_ELEMENT(KEY_RESTART), + NAME_ELEMENT(KEY_SLOW), NAME_ELEMENT(KEY_SHUFFLE), + NAME_ELEMENT(KEY_BREAK), NAME_ELEMENT(KEY_PREVIOUS), + NAME_ELEMENT(KEY_DIGITS), NAME_ELEMENT(KEY_TEEN), + NAME_ELEMENT(KEY_TWEN), NAME_ELEMENT(KEY_DEL_EOL), + NAME_ELEMENT(KEY_DEL_EOS), NAME_ELEMENT(KEY_INS_LINE), + NAME_ELEMENT(KEY_DEL_LINE), + NAME_ELEMENT(KEY_VIDEOPHONE), NAME_ELEMENT(KEY_GAMES), + NAME_ELEMENT(KEY_ZOOMIN), NAME_ELEMENT(KEY_ZOOMOUT), + NAME_ELEMENT(KEY_ZOOMRESET), NAME_ELEMENT(KEY_WORDPROCESSOR), + NAME_ELEMENT(KEY_EDITOR), NAME_ELEMENT(KEY_SPREADSHEET), + NAME_ELEMENT(KEY_GRAPHICSEDITOR), NAME_ELEMENT(KEY_PRESENTATION), + NAME_ELEMENT(KEY_DATABASE), NAME_ELEMENT(KEY_NEWS), + NAME_ELEMENT(KEY_VOICEMAIL), NAME_ELEMENT(KEY_ADDRESSBOOK), + NAME_ELEMENT(KEY_MESSENGER), NAME_ELEMENT(KEY_DISPLAYTOGGLE), +#ifdef KEY_SPELLCHECK + NAME_ELEMENT(KEY_SPELLCHECK), +#endif +#ifdef KEY_LOGOFF + NAME_ELEMENT(KEY_LOGOFF), +#endif +#ifdef KEY_DOLLAR + NAME_ELEMENT(KEY_DOLLAR), +#endif +#ifdef KEY_EURO + NAME_ELEMENT(KEY_EURO), +#endif +#ifdef KEY_FRAMEBACK + NAME_ELEMENT(KEY_FRAMEBACK), +#endif +#ifdef KEY_FRAMEFORWARD + NAME_ELEMENT(KEY_FRAMEFORWARD), +#endif +#ifdef KEY_CONTEXT_MENU + NAME_ELEMENT(KEY_CONTEXT_MENU), +#endif +#ifdef KEY_MEDIA_REPEAT + NAME_ELEMENT(KEY_MEDIA_REPEAT), +#endif +#ifdef KEY_10CHANNELSUP + NAME_ELEMENT(KEY_10CHANNELSUP), +#endif +#ifdef KEY_10CHANNELSDOWN + NAME_ELEMENT(KEY_10CHANNELSDOWN), +#endif +#ifdef KEY_IMAGES + NAME_ELEMENT(KEY_IMAGES), +#endif + NAME_ELEMENT(KEY_DEL_EOL), NAME_ELEMENT(KEY_DEL_EOS), + NAME_ELEMENT(KEY_INS_LINE), NAME_ELEMENT(KEY_DEL_LINE), + NAME_ELEMENT(KEY_FN), NAME_ELEMENT(KEY_FN_ESC), + NAME_ELEMENT(KEY_FN_F1), NAME_ELEMENT(KEY_FN_F2), + NAME_ELEMENT(KEY_FN_F3), NAME_ELEMENT(KEY_FN_F4), + NAME_ELEMENT(KEY_FN_F5), NAME_ELEMENT(KEY_FN_F6), + NAME_ELEMENT(KEY_FN_F7), NAME_ELEMENT(KEY_FN_F8), + NAME_ELEMENT(KEY_FN_F9), NAME_ELEMENT(KEY_FN_F10), + NAME_ELEMENT(KEY_FN_F11), NAME_ELEMENT(KEY_FN_F12), + NAME_ELEMENT(KEY_FN_1), NAME_ELEMENT(KEY_FN_2), + NAME_ELEMENT(KEY_FN_D), NAME_ELEMENT(KEY_FN_E), + NAME_ELEMENT(KEY_FN_F), NAME_ELEMENT(KEY_FN_S), + NAME_ELEMENT(KEY_FN_B), + NAME_ELEMENT(KEY_BRL_DOT1), NAME_ELEMENT(KEY_BRL_DOT2), + NAME_ELEMENT(KEY_BRL_DOT3), NAME_ELEMENT(KEY_BRL_DOT4), + NAME_ELEMENT(KEY_BRL_DOT5), NAME_ELEMENT(KEY_BRL_DOT6), + NAME_ELEMENT(KEY_BRL_DOT7), NAME_ELEMENT(KEY_BRL_DOT8), + NAME_ELEMENT(KEY_BRL_DOT9), NAME_ELEMENT(KEY_BRL_DOT10), +#ifdef KEY_NUMERIC_0 + NAME_ELEMENT(KEY_NUMERIC_0), NAME_ELEMENT(KEY_NUMERIC_1), + NAME_ELEMENT(KEY_NUMERIC_2), NAME_ELEMENT(KEY_NUMERIC_3), + NAME_ELEMENT(KEY_NUMERIC_4), NAME_ELEMENT(KEY_NUMERIC_5), + NAME_ELEMENT(KEY_NUMERIC_6), NAME_ELEMENT(KEY_NUMERIC_7), + NAME_ELEMENT(KEY_NUMERIC_8), NAME_ELEMENT(KEY_NUMERIC_9), + NAME_ELEMENT(KEY_NUMERIC_STAR), NAME_ELEMENT(KEY_NUMERIC_POUND), +#endif +#ifdef KEY_NUMERIC_11 + NAME_ELEMENT(KEY_NUMERIC_11), NAME_ELEMENT(KEY_NUMERIC_12), +#endif + NAME_ELEMENT(KEY_BATTERY), + NAME_ELEMENT(KEY_BLUETOOTH), NAME_ELEMENT(KEY_BRIGHTNESS_CYCLE), + NAME_ELEMENT(KEY_BRIGHTNESS_ZERO), +#ifdef KEY_DASHBOARD + NAME_ELEMENT(KEY_DASHBOARD), +#endif + NAME_ELEMENT(KEY_DISPLAY_OFF), NAME_ELEMENT(KEY_DOCUMENTS), + NAME_ELEMENT(KEY_FORWARDMAIL), NAME_ELEMENT(KEY_NEW), + NAME_ELEMENT(KEY_KBDILLUMDOWN), NAME_ELEMENT(KEY_KBDILLUMUP), + NAME_ELEMENT(KEY_KBDILLUMTOGGLE), NAME_ELEMENT(KEY_REDO), + NAME_ELEMENT(KEY_REPLY), NAME_ELEMENT(KEY_SAVE), +#ifdef KEY_SCALE + NAME_ELEMENT(KEY_SCALE), +#endif + NAME_ELEMENT(KEY_SEND), + NAME_ELEMENT(KEY_SCREENLOCK), NAME_ELEMENT(KEY_SWITCHVIDEOMODE), +#ifdef KEY_UWB + NAME_ELEMENT(KEY_UWB), +#endif +#ifdef KEY_VIDEO_NEXT + NAME_ELEMENT(KEY_VIDEO_NEXT), +#endif +#ifdef KEY_VIDEO_PREV + NAME_ELEMENT(KEY_VIDEO_PREV), +#endif +#ifdef KEY_WIMAX + NAME_ELEMENT(KEY_WIMAX), +#endif +#ifdef KEY_WLAN + NAME_ELEMENT(KEY_WLAN), +#endif +#ifdef KEY_RFKILL + NAME_ELEMENT(KEY_RFKILL), +#endif +#ifdef KEY_MICMUTE + NAME_ELEMENT(KEY_MICMUTE), +#endif +#ifdef KEY_CAMERA_FOCUS + NAME_ELEMENT(KEY_CAMERA_FOCUS), +#endif +#ifdef KEY_WPS_BUTTON + NAME_ELEMENT(KEY_WPS_BUTTON), +#endif +#ifdef KEY_TOUCHPAD_TOGGLE + NAME_ELEMENT(KEY_TOUCHPAD_TOGGLE), + NAME_ELEMENT(KEY_TOUCHPAD_ON), + NAME_ELEMENT(KEY_TOUCHPAD_OFF), +#endif +#ifdef KEY_CAMERA_ZOOMIN + NAME_ELEMENT(KEY_CAMERA_ZOOMIN), NAME_ELEMENT(KEY_CAMERA_ZOOMOUT), + NAME_ELEMENT(KEY_CAMERA_UP), NAME_ELEMENT(KEY_CAMERA_DOWN), + NAME_ELEMENT(KEY_CAMERA_LEFT), NAME_ELEMENT(KEY_CAMERA_RIGHT), +#endif +#ifdef KEY_ATTENDANT_ON + NAME_ELEMENT(KEY_ATTENDANT_ON), NAME_ELEMENT(KEY_ATTENDANT_OFF), + NAME_ELEMENT(KEY_ATTENDANT_TOGGLE), NAME_ELEMENT(KEY_LIGHTS_TOGGLE), +#endif + + NAME_ELEMENT(BTN_0), NAME_ELEMENT(BTN_1), + NAME_ELEMENT(BTN_2), NAME_ELEMENT(BTN_3), + NAME_ELEMENT(BTN_4), NAME_ELEMENT(BTN_5), + NAME_ELEMENT(BTN_6), NAME_ELEMENT(BTN_7), + NAME_ELEMENT(BTN_8), NAME_ELEMENT(BTN_9), + NAME_ELEMENT(BTN_LEFT), NAME_ELEMENT(BTN_RIGHT), + NAME_ELEMENT(BTN_MIDDLE), NAME_ELEMENT(BTN_SIDE), + NAME_ELEMENT(BTN_EXTRA), NAME_ELEMENT(BTN_FORWARD), + NAME_ELEMENT(BTN_BACK), NAME_ELEMENT(BTN_TASK), + NAME_ELEMENT(BTN_TRIGGER), NAME_ELEMENT(BTN_THUMB), + NAME_ELEMENT(BTN_THUMB2), NAME_ELEMENT(BTN_TOP), + NAME_ELEMENT(BTN_TOP2), NAME_ELEMENT(BTN_PINKIE), + NAME_ELEMENT(BTN_BASE), NAME_ELEMENT(BTN_BASE2), + NAME_ELEMENT(BTN_BASE3), NAME_ELEMENT(BTN_BASE4), + NAME_ELEMENT(BTN_BASE5), NAME_ELEMENT(BTN_BASE6), + NAME_ELEMENT(BTN_DEAD), NAME_ELEMENT(BTN_C), +#ifdef BTN_SOUTH + NAME_ELEMENT(BTN_SOUTH), NAME_ELEMENT(BTN_EAST), + NAME_ELEMENT(BTN_NORTH), NAME_ELEMENT(BTN_WEST), +#else + NAME_ELEMENT(BTN_A), NAME_ELEMENT(BTN_B), + NAME_ELEMENT(BTN_X), NAME_ELEMENT(BTN_Y), +#endif + NAME_ELEMENT(BTN_Z), NAME_ELEMENT(BTN_TL), + NAME_ELEMENT(BTN_TR), NAME_ELEMENT(BTN_TL2), + NAME_ELEMENT(BTN_TR2), NAME_ELEMENT(BTN_SELECT), + NAME_ELEMENT(BTN_START), NAME_ELEMENT(BTN_MODE), + NAME_ELEMENT(BTN_THUMBL), NAME_ELEMENT(BTN_THUMBR), + NAME_ELEMENT(BTN_TOOL_PEN), NAME_ELEMENT(BTN_TOOL_RUBBER), + NAME_ELEMENT(BTN_TOOL_BRUSH), NAME_ELEMENT(BTN_TOOL_PENCIL), + NAME_ELEMENT(BTN_TOOL_AIRBRUSH), NAME_ELEMENT(BTN_TOOL_FINGER), + NAME_ELEMENT(BTN_TOOL_MOUSE), NAME_ELEMENT(BTN_TOOL_LENS), + NAME_ELEMENT(BTN_TOUCH), NAME_ELEMENT(BTN_STYLUS), + NAME_ELEMENT(BTN_STYLUS2), NAME_ELEMENT(BTN_TOOL_DOUBLETAP), + NAME_ELEMENT(BTN_TOOL_TRIPLETAP), +#ifdef BTN_TOOL_QUADTAP + NAME_ELEMENT(BTN_TOOL_QUADTAP), +#endif + NAME_ELEMENT(BTN_GEAR_DOWN), + NAME_ELEMENT(BTN_GEAR_UP), + +#ifdef BTN_DPAD_UP + NAME_ELEMENT(BTN_DPAD_UP), NAME_ELEMENT(BTN_DPAD_DOWN), + NAME_ELEMENT(BTN_DPAD_LEFT), NAME_ELEMENT(BTN_DPAD_RIGHT), +#endif +#ifdef KEY_ALS_TOGGLE + NAME_ELEMENT(KEY_ALS_TOGGLE), +#endif +#ifdef KEY_BUTTONCONFIG + NAME_ELEMENT(KEY_BUTTONCONFIG), +#endif +#ifdef KEY_TASKMANAGER + NAME_ELEMENT(KEY_TASKMANAGER), +#endif +#ifdef KEY_JOURNAL + NAME_ELEMENT(KEY_JOURNAL), +#endif +#ifdef KEY_CONTROLPANEL + NAME_ELEMENT(KEY_CONTROLPANEL), +#endif +#ifdef KEY_APPSELECT + NAME_ELEMENT(KEY_APPSELECT), +#endif +#ifdef KEY_SCREENSAVER + NAME_ELEMENT(KEY_SCREENSAVER), +#endif +#ifdef KEY_VOICECOMMAND + NAME_ELEMENT(KEY_VOICECOMMAND), +#endif +#ifdef KEY_ASSISTANT + NAME_ELEMENT(KEY_ASSISTANT), +#endif +#ifdef KEY_BRIGHTNESS_MIN + NAME_ELEMENT(KEY_BRIGHTNESS_MIN), +#endif +#ifdef KEY_BRIGHTNESS_MAX + NAME_ELEMENT(KEY_BRIGHTNESS_MAX), +#endif +#ifdef KEY_KBDINPUTASSIST_PREV + NAME_ELEMENT(KEY_KBDINPUTASSIST_PREV), +#endif +#ifdef KEY_KBDINPUTASSIST_NEXT + NAME_ELEMENT(KEY_KBDINPUTASSIST_NEXT), +#endif +#ifdef KEY_KBDINPUTASSIST_PREVGROUP + NAME_ELEMENT(KEY_KBDINPUTASSIST_PREVGROUP), +#endif +#ifdef KEY_KBDINPUTASSIST_NEXTGROUP + NAME_ELEMENT(KEY_KBDINPUTASSIST_NEXTGROUP), +#endif +#ifdef KEY_KBDINPUTASSIST_ACCEPT + NAME_ELEMENT(KEY_KBDINPUTASSIST_ACCEPT), +#endif +#ifdef KEY_KBDINPUTASSIST_CANCEL + NAME_ELEMENT(KEY_KBDINPUTASSIST_CANCEL), +#endif + +#ifdef KEY_RIGHT_UP + NAME_ELEMENT(KEY_RIGHT_UP), NAME_ELEMENT(KEY_RIGHT_DOWN), + NAME_ELEMENT(KEY_LEFT_UP), NAME_ELEMENT(KEY_LEFT_DOWN), +#endif + +#ifdef KEY_ROOT_MENU + NAME_ELEMENT(KEY_ROOT_MENU), + NAME_ELEMENT(KEY_MEDIA_TOP_MENU), + NAME_ELEMENT(KEY_AUDIO_DESC), + NAME_ELEMENT(KEY_3D_MODE), + NAME_ELEMENT(KEY_NEXT_FAVORITE), + NAME_ELEMENT(KEY_STOP_RECORD), + NAME_ELEMENT(KEY_PAUSE_RECORD), + NAME_ELEMENT(KEY_VOD), + NAME_ELEMENT(KEY_UNMUTE), + NAME_ELEMENT(KEY_FASTREVERSE), + NAME_ELEMENT(KEY_SLOWREVERSE), +#endif + +#ifdef KEY_DATA + NAME_ELEMENT(KEY_DATA), +#endif + +#ifdef KEY_ONSCREEN_KEYBOARD + NAME_ELEMENT(KEY_ONSCREEN_KEYBOARD), +#endif + +#ifdef BTN_TRIGGER_HAPPY + NAME_ELEMENT(BTN_TRIGGER_HAPPY1), NAME_ELEMENT(BTN_TRIGGER_HAPPY11), + NAME_ELEMENT(BTN_TRIGGER_HAPPY2), NAME_ELEMENT(BTN_TRIGGER_HAPPY12), + NAME_ELEMENT(BTN_TRIGGER_HAPPY3), NAME_ELEMENT(BTN_TRIGGER_HAPPY13), + NAME_ELEMENT(BTN_TRIGGER_HAPPY4), NAME_ELEMENT(BTN_TRIGGER_HAPPY14), + NAME_ELEMENT(BTN_TRIGGER_HAPPY5), NAME_ELEMENT(BTN_TRIGGER_HAPPY15), + NAME_ELEMENT(BTN_TRIGGER_HAPPY6), NAME_ELEMENT(BTN_TRIGGER_HAPPY16), + NAME_ELEMENT(BTN_TRIGGER_HAPPY7), NAME_ELEMENT(BTN_TRIGGER_HAPPY17), + NAME_ELEMENT(BTN_TRIGGER_HAPPY8), NAME_ELEMENT(BTN_TRIGGER_HAPPY18), + NAME_ELEMENT(BTN_TRIGGER_HAPPY9), NAME_ELEMENT(BTN_TRIGGER_HAPPY19), + NAME_ELEMENT(BTN_TRIGGER_HAPPY10), NAME_ELEMENT(BTN_TRIGGER_HAPPY20), + + NAME_ELEMENT(BTN_TRIGGER_HAPPY21), NAME_ELEMENT(BTN_TRIGGER_HAPPY31), + NAME_ELEMENT(BTN_TRIGGER_HAPPY22), NAME_ELEMENT(BTN_TRIGGER_HAPPY32), + NAME_ELEMENT(BTN_TRIGGER_HAPPY23), NAME_ELEMENT(BTN_TRIGGER_HAPPY33), + NAME_ELEMENT(BTN_TRIGGER_HAPPY24), NAME_ELEMENT(BTN_TRIGGER_HAPPY34), + NAME_ELEMENT(BTN_TRIGGER_HAPPY25), NAME_ELEMENT(BTN_TRIGGER_HAPPY35), + NAME_ELEMENT(BTN_TRIGGER_HAPPY26), NAME_ELEMENT(BTN_TRIGGER_HAPPY36), + NAME_ELEMENT(BTN_TRIGGER_HAPPY27), NAME_ELEMENT(BTN_TRIGGER_HAPPY37), + NAME_ELEMENT(BTN_TRIGGER_HAPPY28), NAME_ELEMENT(BTN_TRIGGER_HAPPY38), + NAME_ELEMENT(BTN_TRIGGER_HAPPY29), NAME_ELEMENT(BTN_TRIGGER_HAPPY39), + NAME_ELEMENT(BTN_TRIGGER_HAPPY30), NAME_ELEMENT(BTN_TRIGGER_HAPPY40), +#endif +#ifdef BTN_TOOL_QUINTTAP + NAME_ELEMENT(BTN_TOOL_QUINTTAP), +#endif +}; + +static const char * const absval[6] = { "Value", "Min ", "Max ", "Fuzz ", "Flat ", "Resolution "}; + +static const char * const relatives[REL_MAX + 1] = { + [0 ... REL_MAX] = NULL, + NAME_ELEMENT(REL_X), NAME_ELEMENT(REL_Y), + NAME_ELEMENT(REL_Z), NAME_ELEMENT(REL_RX), + NAME_ELEMENT(REL_RY), NAME_ELEMENT(REL_RZ), + NAME_ELEMENT(REL_HWHEEL), + NAME_ELEMENT(REL_DIAL), NAME_ELEMENT(REL_WHEEL), + NAME_ELEMENT(REL_MISC), +#ifdef REL_WHEEL_HI_RES + NAME_ELEMENT(REL_WHEEL_HI_RES), + NAME_ELEMENT(REL_HWHEEL_HI_RES), +#endif +}; + +static const char * const absolutes[ABS_MAX + 1] = { + [0 ... ABS_MAX] = NULL, + NAME_ELEMENT(ABS_X), NAME_ELEMENT(ABS_Y), + NAME_ELEMENT(ABS_Z), NAME_ELEMENT(ABS_RX), + NAME_ELEMENT(ABS_RY), NAME_ELEMENT(ABS_RZ), + NAME_ELEMENT(ABS_THROTTLE), NAME_ELEMENT(ABS_RUDDER), + NAME_ELEMENT(ABS_WHEEL), NAME_ELEMENT(ABS_GAS), + NAME_ELEMENT(ABS_BRAKE), NAME_ELEMENT(ABS_HAT0X), + NAME_ELEMENT(ABS_HAT0Y), NAME_ELEMENT(ABS_HAT1X), + NAME_ELEMENT(ABS_HAT1Y), NAME_ELEMENT(ABS_HAT2X), + NAME_ELEMENT(ABS_HAT2Y), NAME_ELEMENT(ABS_HAT3X), + NAME_ELEMENT(ABS_HAT3Y), NAME_ELEMENT(ABS_PRESSURE), + NAME_ELEMENT(ABS_DISTANCE), NAME_ELEMENT(ABS_TILT_X), + NAME_ELEMENT(ABS_TILT_Y), NAME_ELEMENT(ABS_TOOL_WIDTH), + NAME_ELEMENT(ABS_VOLUME), NAME_ELEMENT(ABS_MISC), +#ifdef ABS_MT_BLOB_ID + NAME_ELEMENT(ABS_MT_TOUCH_MAJOR), + NAME_ELEMENT(ABS_MT_TOUCH_MINOR), + NAME_ELEMENT(ABS_MT_WIDTH_MAJOR), + NAME_ELEMENT(ABS_MT_WIDTH_MINOR), + NAME_ELEMENT(ABS_MT_ORIENTATION), + NAME_ELEMENT(ABS_MT_POSITION_X), + NAME_ELEMENT(ABS_MT_POSITION_Y), + NAME_ELEMENT(ABS_MT_TOOL_TYPE), + NAME_ELEMENT(ABS_MT_BLOB_ID), +#endif +#ifdef ABS_MT_TRACKING_ID + NAME_ELEMENT(ABS_MT_TRACKING_ID), +#endif +#ifdef ABS_MT_PRESSURE + NAME_ELEMENT(ABS_MT_PRESSURE), +#endif +#ifdef ABS_MT_SLOT + NAME_ELEMENT(ABS_MT_SLOT), +#endif +#ifdef ABS_MT_TOOL_X + NAME_ELEMENT(ABS_MT_TOOL_X), + NAME_ELEMENT(ABS_MT_TOOL_Y), + NAME_ELEMENT(ABS_MT_DISTANCE), +#endif + +}; + +static const char * const misc[MSC_MAX + 1] = { + [ 0 ... MSC_MAX] = NULL, + NAME_ELEMENT(MSC_SERIAL), NAME_ELEMENT(MSC_PULSELED), + NAME_ELEMENT(MSC_GESTURE), NAME_ELEMENT(MSC_RAW), + NAME_ELEMENT(MSC_SCAN), +#ifdef MSC_TIMESTAMP + NAME_ELEMENT(MSC_TIMESTAMP), +#endif +}; + +static const char * const leds[LED_MAX + 1] = { + [0 ... LED_MAX] = NULL, + NAME_ELEMENT(LED_NUML), NAME_ELEMENT(LED_CAPSL), + NAME_ELEMENT(LED_SCROLLL), NAME_ELEMENT(LED_COMPOSE), + NAME_ELEMENT(LED_KANA), NAME_ELEMENT(LED_SLEEP), + NAME_ELEMENT(LED_SUSPEND), NAME_ELEMENT(LED_MUTE), + NAME_ELEMENT(LED_MISC), +#ifdef LED_MAIL + NAME_ELEMENT(LED_MAIL), +#endif +#ifdef LED_CHARGING + NAME_ELEMENT(LED_CHARGING), +#endif +}; + +static const char * const repeats[REP_MAX + 1] = { + [0 ... REP_MAX] = NULL, + NAME_ELEMENT(REP_DELAY), NAME_ELEMENT(REP_PERIOD) +}; + +static const char * const sounds[SND_MAX + 1] = { + [0 ... SND_MAX] = NULL, + NAME_ELEMENT(SND_CLICK), NAME_ELEMENT(SND_BELL), + NAME_ELEMENT(SND_TONE) +}; + +static const char * const syns[SYN_MAX + 1] = { + [0 ... SYN_MAX] = NULL, + NAME_ELEMENT(SYN_REPORT), + NAME_ELEMENT(SYN_CONFIG), + NAME_ELEMENT(SYN_MT_REPORT), + NAME_ELEMENT(SYN_DROPPED) +}; + +static const char * const switches[SW_MAX + 1] = { + [0 ... SW_MAX] = NULL, + NAME_ELEMENT(SW_LID), + NAME_ELEMENT(SW_TABLET_MODE), + NAME_ELEMENT(SW_HEADPHONE_INSERT), +#ifdef SW_RFKILL_ALL + NAME_ELEMENT(SW_RFKILL_ALL), +#endif +#ifdef SW_MICROPHONE_INSERT + NAME_ELEMENT(SW_MICROPHONE_INSERT), +#endif +#ifdef SW_DOCK + NAME_ELEMENT(SW_DOCK), +#endif +#ifdef SW_LINEOUT_INSERT + NAME_ELEMENT(SW_LINEOUT_INSERT), +#endif +#ifdef SW_JACK_PHYSICAL_INSERT + NAME_ELEMENT(SW_JACK_PHYSICAL_INSERT), +#endif +#ifdef SW_VIDEOOUT_INSERT + NAME_ELEMENT(SW_VIDEOOUT_INSERT), +#endif +#ifdef SW_CAMERA_LENS_COVER + NAME_ELEMENT(SW_CAMERA_LENS_COVER), + NAME_ELEMENT(SW_KEYPAD_SLIDE), + NAME_ELEMENT(SW_FRONT_PROXIMITY), +#endif +#ifdef SW_ROTATE_LOCK + NAME_ELEMENT(SW_ROTATE_LOCK), +#endif +#ifdef SW_LINEIN_INSERT + NAME_ELEMENT(SW_LINEIN_INSERT), +#endif +#ifdef SW_MUTE_DEVICE + NAME_ELEMENT(SW_MUTE_DEVICE), +#endif +#ifdef SW_PEN_INSERTED + NAME_ELEMENT(SW_PEN_INSERTED), +#endif +}; + +static const char * const force[FF_MAX + 1] = { + [0 ... FF_MAX] = NULL, + NAME_ELEMENT(FF_RUMBLE), NAME_ELEMENT(FF_PERIODIC), + NAME_ELEMENT(FF_CONSTANT), NAME_ELEMENT(FF_SPRING), + NAME_ELEMENT(FF_FRICTION), NAME_ELEMENT(FF_DAMPER), + NAME_ELEMENT(FF_INERTIA), NAME_ELEMENT(FF_RAMP), + NAME_ELEMENT(FF_SQUARE), NAME_ELEMENT(FF_TRIANGLE), + NAME_ELEMENT(FF_SINE), NAME_ELEMENT(FF_SAW_UP), + NAME_ELEMENT(FF_SAW_DOWN), NAME_ELEMENT(FF_CUSTOM), + NAME_ELEMENT(FF_GAIN), NAME_ELEMENT(FF_AUTOCENTER), +}; + +static const char * const forcestatus[FF_STATUS_MAX + 1] = { + [0 ... FF_STATUS_MAX] = NULL, + NAME_ELEMENT(FF_STATUS_STOPPED), NAME_ELEMENT(FF_STATUS_PLAYING), +}; + +static const char * const * const names[EV_MAX + 1] = { + [0 ... EV_MAX] = NULL, + [EV_SYN] = syns, [EV_KEY] = keys, + [EV_REL] = relatives, [EV_ABS] = absolutes, + [EV_MSC] = misc, [EV_LED] = leds, + [EV_SND] = sounds, [EV_REP] = repeats, + [EV_SW] = switches, + [EV_FF] = force, [EV_FF_STATUS] = forcestatus, +}; + +/** + * Convert a string to a specific key/snd/led/sw code. The string can either + * be the name of the key in question (e.g. "SW_DOCK") or the numerical + * value, either as decimal (e.g. "5") or as hex (e.g. "0x5"). + * + * @param mode The mode being queried (key, snd, led, sw) + * @param kstr The string to parse and convert + * + * @return The requested code's numerical value, or negative on error. + */ +static int get_keycode(const struct query_mode *query_mode, const char *kstr) +{ + if (isdigit(kstr[0])) { + unsigned long val; + errno = 0; + val = strtoul(kstr, NULL, 0); + if (errno) { + fprintf(stderr, "Could not interpret value %s\n", kstr); + return -1; + } + return (int) val; + } else { + const char * const *keynames = names[query_mode->event_type]; + int i; + + for (i = 0; i < query_mode->max; i++) { + const char *name = keynames[i]; + if (name && strcmp(name, kstr) == 0) + return i; + } + + return -1; + } +} + +/** + * Filter for the AutoDevProbe scandir on /dev/input. + * + * @param dir The current directory entry provided by scandir. + * + * @return Non-zero if the given directory entry starts with "event", or zero + * otherwise. + */ +static int is_event_device(const struct dirent *dir) { + return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0; +} + +/** + * Scans all /dev/input/event*, display them and ask the user which one to + * open. + * + * @return The event device file name of the device file selected. This + * string is allocated and must be freed by the caller. + */ +static char* scan_devices(void) +{ + struct dirent **namelist; + int i, ndev, devnum, match; + char *filename; + int max_device = 0; + + ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, versionsort); + if (ndev <= 0) + return NULL; + + fprintf(stderr, "Available devices:\n"); + + for (i = 0; i < ndev; i++) + { + char fname[PATH_MAX]; + int fd = -1; + char name[256] = "???"; + + snprintf(fname, sizeof(fname), + "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name); + fd = open(fname, O_RDONLY); + if (fd < 0) + continue; + ioctl(fd, EVIOCGNAME(sizeof(name)), name); + + fprintf(stderr, "%s: %s\n", fname, name); + close(fd); + + match = sscanf(namelist[i]->d_name, "event%d", &devnum); + if (match >= 1 && devnum > max_device) + max_device = devnum; + + free(namelist[i]); + } + + fprintf(stderr, "Select the device event number [0-%d]: ", max_device); + + match = scanf("%d", &devnum); + if (match < 1 || devnum > max_device || devnum < 0) + return NULL; + + if (asprintf(&filename, "%s/%s%d", + DEV_INPUT_EVENT, EVENT_DEV_NAME, + devnum) < 0) + return NULL; + + return filename; +} + +static int version(void) +{ +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "" +#endif + printf("%s %s\n", program_invocation_short_name, PACKAGE_VERSION); + return EXIT_SUCCESS; +} + + +/** + * Print usage information. + */ +static int usage(void) +{ + printf("USAGE:\n"); + printf(" Capture mode:\n"); + printf(" %s [--grab] /dev/input/eventX\n", program_invocation_short_name); + printf(" --grab grab the device for exclusive access\n"); + printf("\n"); + printf(" Query mode: (check exit code)\n"); + printf(" %s --query /dev/input/eventX \n", + program_invocation_short_name); + + printf("\n"); + printf(" is one of: EV_KEY, EV_SW, EV_LED, EV_SND\n"); + printf(" can either be a numerical value, or the textual name of the\n"); + printf("key/switch/LED/sound being queried (e.g. SW_DOCK).\n"); + + return EXIT_FAILURE; +} + +/** + * Print additional information for absolute axes (min/max, current value, + * etc.). + * + * @param fd The file descriptor to the device. + * @param axis The axis identifier (e.g. ABS_X). + */ +static void print_absdata(int fd, int axis) +{ + int abs[6] = {0}; + int k; + + ioctl(fd, EVIOCGABS(axis), abs); + for (k = 0; k < 6; k++) + if ((k < 3) || abs[k]) + printf(" %s %6d\n", absval[k], abs[k]); +} + +static void print_repdata(int fd) +{ + int i; + unsigned int rep[2]; + + ioctl(fd, EVIOCGREP, rep); + + for (i = 0; i <= REP_MAX; i++) { + printf(" Repeat code %d (%s)\n", i, names[EV_REP] ? (names[EV_REP][i] ? names[EV_REP][i] : "?") : "?"); + printf(" Value %6d\n", rep[i]); + } + +} + +static inline const char* typename(unsigned int type) +{ + return (type <= EV_MAX && events[type]) ? events[type] : "?"; +} + +static inline const char* codename(unsigned int type, unsigned int code) +{ + return (type <= EV_MAX && code <= maxval[type] && names[type] && names[type][code]) ? names[type][code] : "?"; +} + +#ifdef INPUT_PROP_SEMI_MT +static inline const char* propname(unsigned int prop) +{ + return (prop <= INPUT_PROP_MAX && props[prop]) ? props[prop] : "?"; +} +#endif + +static int get_state(int fd, unsigned int type, unsigned long *array, size_t size) +{ + int rc; + + switch(type) { + case EV_LED: + rc = ioctl(fd, EVIOCGLED(size), array); + break; + case EV_SND: + rc = ioctl(fd, EVIOCGSND(size), array); + break; + case EV_SW: + rc = ioctl(fd, EVIOCGSW(size), array); + break; + case EV_KEY: + /* intentionally not printing the value for EV_KEY, let the + * repeat handle this */ + default: + return 1; + } + if (rc == -1) + return 1; + + return 0; +} + +/** + * Print static device information (no events). This information includes + * version numbers, device name and all bits supported by this device. + * + * @param fd The file descriptor to the device. + * @return 0 on success or 1 otherwise. + */ +static int print_device_info(int fd) +{ + unsigned int type, code; + int version; + unsigned short id[4]; + char name[256] = "Unknown"; + unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; + unsigned long state[KEY_CNT] = {0}; +#ifdef INPUT_PROP_SEMI_MT + unsigned int prop; + unsigned long propbits[INPUT_PROP_MAX]; +#endif + int stateval; + int have_state; + + if (ioctl(fd, EVIOCGVERSION, &version)) { + perror("evtest: can't get version"); + return 1; + } + + printf("Input driver version is %d.%d.%d\n", + version >> 16, (version >> 8) & 0xff, version & 0xff); + + ioctl(fd, EVIOCGID, id); + printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", + id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]); + + ioctl(fd, EVIOCGNAME(sizeof(name)), name); + printf("Input device name: \"%s\"\n", name); + + memset(bit, 0, sizeof(bit)); + ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]); + printf("Supported events:\n"); + + for (type = 0; type < EV_MAX; type++) { + if (test_bit(type, bit[0]) && type != EV_REP) { + have_state = (get_state(fd, type, state, sizeof(state)) == 0); + + printf(" Event type %d (%s)\n", type, typename(type)); + if (type == EV_SYN) continue; + ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit[type]); + for (code = 0; code < KEY_MAX; code++) + if (test_bit(code, bit[type])) { + if (have_state) { + stateval = test_bit(code, state); + printf(" Event code %d (%s) state %d\n", + code, codename(type, code), stateval); + } else { + printf(" Event code %d (%s)\n", code, codename(type, code)); + } + if (type == EV_ABS) + print_absdata(fd, code); + } + } + } + + if (test_bit(EV_REP, bit[0])) { + printf("Key repeat handling:\n"); + printf(" Repeat type %d (%s)\n", EV_REP, events[EV_REP] ? events[EV_REP] : "?"); + print_repdata(fd); + } +#ifdef INPUT_PROP_SEMI_MT + memset(propbits, 0, sizeof(propbits)); + ioctl(fd, EVIOCGPROP(sizeof(propbits)), propbits); + printf("Properties:\n"); + for (prop = 0; prop < INPUT_PROP_MAX; prop++) { + if (test_bit(prop, propbits)) + printf(" Property type %d (%s)\n", prop, propname(prop)); + } +#endif + + return 0; +} + +/** + * Print device events as they come in. + * + * @param fd The file descriptor to the device. + * @return 0 on success or 1 otherwise. + */ +static int print_events(int fd) +{ + struct input_event ev[64]; + int i, rd; + fd_set rdfs; + + FD_ZERO(&rdfs); + FD_SET(fd, &rdfs); + + while (!stop) { + select(fd + 1, &rdfs, NULL, NULL, NULL); + if (stop) + break; + rd = read(fd, ev, sizeof(ev)); + + if (rd < (int) sizeof(struct input_event)) { + printf("expected %d bytes, got %d\n", (int) sizeof(struct input_event), rd); + perror("\nevtest: error reading"); + return 1; + } + + for (i = 0; i < rd / sizeof(struct input_event); i++) { + unsigned int type, code; + + type = ev[i].type; + code = ev[i].code; + + printf("Event: time %ld.%06ld, ", ev[i].input_event_sec, ev[i].input_event_usec); + + if (type == EV_SYN) { + if (code == SYN_MT_REPORT) + printf("++++++++++++++ %s ++++++++++++\n", codename(type, code)); + else if (code == SYN_DROPPED) + printf(">>>>>>>>>>>>>> %s <<<<<<<<<<<<\n", codename(type, code)); + else + printf("-------------- %s ------------\n", codename(type, code)); + } else { + printf("type %d (%s), code %d (%s), ", + type, typename(type), + code, codename(type, code)); + if (type == EV_MSC && (code == MSC_RAW || code == MSC_SCAN)) + printf("value %02x\n", ev[i].value); + else + printf("value %d\n", ev[i].value); + } + } + + } + + ioctl(fd, EVIOCGRAB, (void*)0); + return EXIT_SUCCESS; +} + +/** + * Grab and immediately ungrab the device. + * + * @param fd The file descriptor to the device. + * @return 0 if the grab was successful, or 1 otherwise. + */ +static int test_grab(int fd, int grab_flag) +{ + int rc; + + rc = ioctl(fd, EVIOCGRAB, (void*)1); + + if (rc == 0 && !grab_flag) + ioctl(fd, EVIOCGRAB, (void*)0); + + return rc; +} + +/** + * Enter capture mode. The requested event device will be monitored, and any + * captured events will be decoded and printed on the console. + * + * @param device The device to monitor, or NULL if the user should be prompted. + * @return 0 on success, non-zero on error. + */ +static int do_capture(const char *device, int grab_flag) +{ + int fd; + char *filename = NULL; + + if (!device) { + fprintf(stderr, "No device specified, trying to scan all of %s/%s*\n", + DEV_INPUT_EVENT, EVENT_DEV_NAME); + + if (getuid() != 0) + fprintf(stderr, "Not running as root, no devices may be available.\n"); + + filename = scan_devices(); + if (!filename) + return usage(); + } else + filename = strdup(device); + + if (!filename) + return EXIT_FAILURE; + + if ((fd = open(filename, O_RDONLY)) < 0) { + perror("evtest"); + if (errno == EACCES && getuid() != 0) + fprintf(stderr, "You do not have access to %s. Try " + "running as root instead.\n", + filename); + goto error; + } + + if (!isatty(fileno(stdout))) + setbuf(stdout, NULL); + + if (print_device_info(fd)) + goto error; + + printf("Testing ... (interrupt to exit)\n"); + + if (test_grab(fd, grab_flag)) + { + printf("***********************************************\n"); + printf(" This device is grabbed by another process.\n"); + printf(" No events are available to evtest while the\n" + " other grab is active.\n"); + printf(" In most cases, this is caused by an X driver,\n" + " try VT-switching and re-run evtest again.\n"); + printf(" Run the following command to see processes with\n" + " an open fd on this device\n" + " \"fuser -v %s\"\n", filename); + printf("***********************************************\n"); + } + + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + free(filename); + + return print_events(fd); + +error: + free(filename); + return EXIT_FAILURE; +} + +/** + * Perform a one-shot state query on a specific device. The query can be of + * any known mode, on any valid keycode. + * + * @param device Path to the evdev device node that should be queried. + * @param query_mode The event type that is being queried (e.g. key, switch) + * @param keycode The code of the key/switch/sound/LED to be queried + * @return 0 if the state bit is unset, 10 if the state bit is set, 1 on error. + */ +static int query_device(const char *device, const struct query_mode *query_mode, int keycode) +{ + int fd; + int r; + unsigned long state[NBITS(query_mode->max)]; + + fd = open(device, O_RDONLY); + if (fd < 0) { + perror("open"); + return EXIT_FAILURE; + } + memset(state, 0, sizeof(state)); + r = ioctl(fd, query_mode->rq, state); + close(fd); + + if (r == -1) { + perror("ioctl"); + return EXIT_FAILURE; + } + + if (test_bit(keycode, state)) + return 10; /* different from EXIT_FAILURE */ + else + return 0; +} + +/** + * Enter query mode. The requested event device will be queried for the state + * of a particular switch/key/sound/LED. + * + * @param device The device to query. + * @param mode The mode (event type) that is to be queried (snd, sw, key, led) + * @param keycode The key code to query the state of. + * @return 0 if the state bit is unset, 10 if the state bit is set. + */ +static int do_query(const char *device, const char *event_type, const char *keyname) +{ + const struct query_mode *query_mode; + int keycode; + + if (!device) { + fprintf(stderr, "Device argument is required for query.\n"); + return usage(); + } + + query_mode = find_query_mode(event_type); + if (!query_mode) { + fprintf(stderr, "Unrecognised event type: %s\n", event_type); + return usage(); + } + + keycode = get_keycode(query_mode, keyname); + if (keycode < 0) { + fprintf(stderr, "Unrecognised key name: %s\n", keyname); + return usage(); + } else if (keycode > query_mode->max) { + fprintf(stderr, "Key %d is out of bounds.\n", keycode); + return EXIT_FAILURE; + } + + return query_device(device, query_mode, keycode); +} + +static const struct option long_options[] = { + { "grab", no_argument, &grab_flag, 1 }, + { "query", no_argument, NULL, MODE_QUERY }, + { "version", no_argument, NULL, MODE_VERSION }, + { 0, }, +}; + +int main (int argc, char **argv) +{ + const char *device = NULL; + const char *keyname; + const char *event_type; + enum evtest_mode mode = MODE_CAPTURE; + + while (1) { + int option_index = 0; + int c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + switch (c) { + case 0: + break; + case MODE_QUERY: + mode = c; + break; + case MODE_VERSION: + return version(); + default: + return usage(); + } + } + + if (optind < argc) + device = argv[optind++]; + + if (mode == MODE_CAPTURE) + return do_capture(device, grab_flag); + + if ((argc - optind) < 2) { + fprintf(stderr, "Query mode requires device, type and key parameters\n"); + return usage(); + } + + event_type = argv[optind++]; + keyname = argv[optind++]; + return do_query(device, event_type, keyname); +} + +/* vim: set noexpandtab tabstop=8 shiftwidth=8: */ diff --git a/platforms/unix/vm/sqUnixMain.c b/platforms/unix/vm/sqUnixMain.c index ed5f5e3ab1..5b17d04f6d 100644 --- a/platforms/unix/vm/sqUnixMain.c +++ b/platforms/unix/vm/sqUnixMain.c @@ -859,6 +859,11 @@ sqInt primitivePluginDestroyRequest(void) { return dpy->primitivePluginDestroyR sqInt primitivePluginRequestState(void) { return dpy->primitivePluginRequestState(); } +#ifdef MUSL +void pushOutputFile(char *filenameOrStdioIndex) {;} +void popOutputFile() {;} +#endif + /*** errors ***/ static void outOfMemory(void)