IR remote control autorepeat / evdev

Mauro Carvalho Chehab mchehab at redhat.com
Fri May 13 00:51:02 PDT 2011


Em 12-05-2011 08:05, Peter Hutterer escreveu:
> On Thu, May 12, 2011 at 03:36:47AM +0200, Mauro Carvalho Chehab wrote:
>> Em 12-05-2011 03:10, Mauro Carvalho Chehab escreveu:
>>> Em 12-05-2011 02:37, Anssi Hannula escreveu:
>>
>>>> I don't see any other places:
>>>> $ git grep 'REP_PERIOD' .
>>>> dvb/dvb-usb/dvb-usb-remote.c:   input_dev->rep[REP_PERIOD] =
>>>> d->props.rc.legacy.rc_interval;
>>>
>>> Indeed, the REP_PERIOD is not adjusted on other drivers. I agree that we
>>> should change it to something like 125ms, for example, as 33ms is too 
>>> short, as it takes up to 114ms for a repeat event to arrive.
>>>
>> IMO, the enclosed patch should do a better job with repeat events, without
>> needing to change rc-core/input/event logic.
>>
>> -
>>
>> Subject: Use a more consistent value for RC repeat period
>> From: Mauro Carvalho Chehab <mchehab at redhat.com>
>>
>> The default REP_PERIOD is 33 ms. This doesn't make sense for IR's,
>> as, in general, an IR repeat scancode is provided at every 110/115ms,
>> depending on the RC protocol. So, increase its default, to do a
>> better job avoiding ghost repeat events.
>>
>> Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
>>
>> diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
>> index f53f9c6..ee67169 100644
>> --- a/drivers/media/rc/rc-main.c
>> +++ b/drivers/media/rc/rc-main.c
>> @@ -1044,6 +1044,13 @@ int rc_register_device(struct rc_dev *dev)
>>  	 */
>>  	dev->input_dev->rep[REP_DELAY] = 500;
>>  
>> +	/*
>> +	 * As a repeat event on protocols like RC-5 and NEC take as long as
>> +	 * 110/114ms, using 33ms as a repeat period is not the right thing
>> +	 * to do.
>> +	 */
>> +	dev->input_dev->rep[REP_PERIOD] = 125;
>> +
>>  	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
>>  	printk(KERN_INFO "%s: %s as %s\n",
>>  		dev_name(&dev->dev),
> 
> so if I get this right, a XkbSetControls(.. XkbRepeatKeysMask ...) by a
> client to set the repeat rate would provide the same solution - for those
> clients/devices affected. 

Yes, if we preserve the same logic. The above will probably still generate
ghost repeats if the user keeps the IR pressed for a long time, as we're using
a separate timer at the rc-core logic than the one used inside evdev.

> The interesting question is how clients would identify the devices that are
> affected by this (other than trial and error).

That is easy. I've added a logic that detects it on Xorg evdev on some RFC patches
I've prepared in the past to allow using a keycode with more than 247 for IR's.
I'll work on a new version for it and submit again when I have some time.
Anyway, I'm enclosing a patch with the old version. 

Basically, GetRCInputs.c file adds a logic that returns a list of input devices
that are Remote Controllers, using rc-core.

This logic inside evdev gets the RC devices and adds a flag identifying them
as such:

+    /* Check if the device is a remote controller */
+    pRCDevList = GetRCInputDevices(&NumDevices);
+    for (i = 0; i < NumDevices; i++) {
+        if (!strcmp(device, pRCDevList[i].InputName)) {
+             pEvdev->flags |= EVDEV_RC_EVENTS;
+             break;
+        }
+    }

Thanks,
Mauro

-

diff --git a/src/GetRCInputs.c b/src/GetRCInputs.c
new file mode 100644
index 0000000..0e03e3a
--- /dev/null
+++ b/src/GetRCInputs.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author:
+ * 	Mauro Carvalho Chehab <mchehab at redhat.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "evdev.h"
+
+#include <X11/keysym.h>
+#include <X11/extensions/XI.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <dirent.h>
+
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+#include <xorgVersion.h>
+#include <xkbsrv.h>
+
+struct UEvents {
+    char           *key;
+    char           *value;
+    struct UEvents *next;
+};
+
+struct SysfsNames  {
+    char              *name;
+    struct SysfsNames *next;
+};
+
+struct RCDevice {
+    char *SysfsName;    /* Device sysfs node name */
+    char *InputName;    /* Input device file name */
+};
+
+static void FreeNames(struct SysfsNames *names)
+{
+    struct SysfsNames *old;
+    do {
+        old = names;
+        names = names->next;
+        if (old->name)
+            free(old->name);
+        free(old);
+    } while (names);
+}
+
+static struct SysfsNames *SeekSysfsDir(char *dname, char *NodeName)
+{
+    DIR                *dir;
+    struct dirent      *entry;
+    struct SysfsNames  *names, *CurName;
+
+    names = calloc(sizeof(*names), 1);
+
+    CurName = names;
+
+    dir = opendir(dname);
+    if (!dir) {
+        perror(dname);
+        return NULL;
+    }
+    entry = readdir(dir);
+    while (entry) {
+        if (!NodeName || !strncmp(entry->d_name, NodeName, strlen(NodeName))) {
+            CurName->name = malloc(strlen(dname) + strlen(entry->d_name) + 2);
+            if (!CurName->name)
+                goto err;
+            strcpy(CurName->name, dname);
+            strcat(CurName->name, entry->d_name);
+            if (NodeName)
+                strcat(CurName->name, "/");
+            CurName->next = calloc(sizeof(*CurName), 1);
+            if (!CurName->next)
+                goto err;
+            CurName = CurName->next;
+        }
+        entry = readdir(dir);
+    }
+    closedir(dir);
+
+    if (names == CurName) {
+        xf86Msg(X_ERROR, "Couldn't find any node at %s%s*.\n",
+            dname, NodeName);
+        free (names);
+        names = NULL;
+    }
+    return names;
+
+err:
+    perror("Seek dir");
+    FreeNames(names);
+    return NULL;
+}
+
+static void FreeUevent(struct UEvents *uevent)
+{
+    struct UEvents *old;
+    do {
+        old = uevent;
+        uevent = uevent->next;
+        if (old->key)
+            free(old->key);
+        if (old->value)
+            free(old->value);
+        free(old);
+    } while (uevent);
+}
+
+static struct UEvents *ReadSysfsUevents(char *dname)
+{
+    FILE           *fp;
+    struct UEvents *next, *uevent;
+    char           *event = "uevent", *file, s[4096];
+
+    next = uevent = calloc(1, sizeof(*uevent));
+
+    file = malloc(strlen(dname) + strlen(event) + 1);
+    strcpy(file, dname);
+    strcat(file, event);
+
+    fp = fopen(file, "r");
+    if (!fp) {
+        perror(file);
+        free(file);
+        return NULL;
+    }
+    while (fgets(s, sizeof(s), fp)) {
+        char *p = strtok(s, "=");
+        if (!p)
+            continue;
+        next->key = malloc(strlen(p) + 1);
+        if (!next->key) {
+            perror("next->key");
+            free(file);
+            FreeUevent(uevent);
+            return NULL;
+        }
+        strcpy(next->key, p);
+
+        p = strtok(NULL, "\n");
+        if (!p) {
+            xf86Msg(X_ERROR, "Error on uevent information\n");
+            fclose(fp);
+            free(file);
+            FreeUevent(uevent);
+            return NULL;
+        }
+        next->value = malloc(strlen(p) + 1);
+        if (!next->value) {
+            perror("next->value");
+            free(file);
+            FreeUevent(uevent);
+            return NULL;
+        }
+        strcpy(next->value, p);
+
+        next->next = calloc(1, sizeof(*next));
+        if (!next->next) {
+            perror("next->next");
+            free(file);
+            FreeUevent(uevent);
+            return NULL;
+        }
+        next = next->next;
+    }
+    fclose(fp);
+    free(file);
+
+    return uevent;
+}
+
+static struct SysfsNames *FindDevice(char *name)
+{
+    char                     dname[256];
+    char                     *input = "rc";
+    static struct SysfsNames *names, *cur;
+    /*
+     * Get event sysfs node
+     */
+    snprintf(dname, sizeof(dname), "/sys/class/rc/");
+
+    names = SeekSysfsDir(dname, input);
+    if (!names)
+        return NULL;
+
+    if (name) {
+        static struct SysfsNames *tmp;
+        char *p, *n;
+        int found = 0;
+
+        n = malloc(strlen(name) + 2);
+        strcpy(n, name);
+        strcat(n,"/");
+        for (cur = names; cur->next; cur = cur->next) {
+            if (cur->name) {
+                p = cur->name + strlen(dname);
+                if (p && !strcmp(p, n)) {
+                    found = 1;
+                    break;
+                }
+            }
+        }
+        free(n);
+        if (!found) {
+            FreeNames(names);
+            xf86Msg(X_ERROR, "Not found device %s\n", name);
+            return NULL;
+        }
+        tmp = calloc(sizeof(*names), 1);
+        tmp->name = cur->name;
+        cur->name = NULL;
+        FreeNames(names);
+        return tmp;
+    }
+
+    return names;
+}
+
+static int GetAttribs(struct RCDevice *RCDev, char *SysfsName)
+{
+    struct UEvents           *uevent;
+    char                     *input = "input", *event = "event";
+    char                     *DEV = "/dev/";
+    static struct SysfsNames *InputNames, *event_names;
+
+    /* Clean the attributes */
+    memset(RCDev, 0, sizeof(*RCDev));
+
+    RCDev->SysfsName = SysfsName;
+
+    InputNames = SeekSysfsDir(RCDev->SysfsName, input);
+    if (!InputNames)
+        return EINVAL;
+    if (InputNames->next->next) {
+        xf86Msg(X_ERROR, "Found more than one input interface."
+                "This is currently unsupported\n");
+        return EINVAL;
+    }
+
+    event_names = SeekSysfsDir(InputNames->name, event);
+    FreeNames(InputNames);
+    if (!event_names) {
+        FreeNames(event_names);
+        return EINVAL;
+    }
+    if (event_names->next->next) {
+        FreeNames(event_names);
+        xf86Msg(X_ERROR, "Found more than one event interface."
+                "This is currently unsupported\n");
+        return EINVAL;
+    }
+
+    uevent = ReadSysfsUevents(event_names->name);
+    FreeNames(event_names);
+
+    if (!uevent)
+        return EINVAL;
+
+    while (uevent->next) {
+        if (!strcmp(uevent->key, "DEVNAME")) {
+            RCDev->InputName = malloc(strlen(uevent->value) + strlen(DEV) + 1);
+            strcpy(RCDev->InputName, DEV);
+            strcat(RCDev->InputName, uevent->value);
+            break;
+        }
+        uevent = uevent->next;
+    }
+    FreeUevent(uevent);
+
+    if (!RCDev->InputName) {
+        xf86Msg(X_ERROR, "Input device name not found.\n");
+        return EINVAL;
+    }
+
+    return 0;
+}
+
+RCDeviceListPtr GetRCInputDevices(int *num)
+{
+    struct RCDevice          RCDev;
+    static struct SysfsNames *names, *cur;
+    RCDeviceListPtr          RCDevList;
+    int                      n = 0;
+
+    *num = 0;
+
+    names = FindDevice(NULL);
+    if (!names)
+        return NULL;
+    for (cur = names; cur->next; cur = cur->next)
+        if (cur->name)
+            n++;
+
+    RCDevList = malloc(n * sizeof(RCDeviceList));
+    if (!RCDevList)
+        goto error;
+
+    *num = n;
+
+    n = 0;
+    for (cur = names; cur->next; cur = cur->next) {
+        if (cur->name) {
+            if (GetAttribs(&RCDev, cur->name)) {
+                free (RCDevList);
+                return NULL;
+            }
+            xf86Msg(X_INFO, "Found %s (%s)\n",
+                    RCDev.SysfsName, RCDev.InputName);
+
+            strncpy(RCDevList[n].SysfsName, RCDev.SysfsName,
+                    sizeof(RCDevList[n].SysfsName) - 1);
+	    RCDevList[n].SysfsName[sizeof(RCDevList[n].SysfsName) - 1] = '\0';
+            strncpy(RCDevList[n].InputName, RCDev.InputName,
+                    sizeof(RCDevList[n].InputName) - 1);
+	    RCDevList[n].InputName[sizeof(RCDevList[n].InputName) - 1] = '\0';
+            n++;
+        }
+    }
+
+error:
+    FreeNames(names);
+
+    return RCDevList;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index a5c89ac..a42fe35 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,5 +36,6 @@ AM_CPPFLAGS =-I$(top_srcdir)/include
                                @DRIVER_NAME at .h \
                                emuMB.c \
                                emuWheel.c \
-                               draglock.c
+                               draglock.c \
+                               GetRCInputs.c
 
diff --git a/src/Makefile.in b/src/Makefile.in
index 3d6195d..1299c58 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -95,7 +95,7 @@ am__installdirs = "$(DESTDIR)$(@DRIVER_NAME at _drv_ladir)"
 LTLIBRARIES = $(@DRIVER_NAME at _drv_la_LTLIBRARIES)
 @DRIVER_NAME at _drv_la_LIBADD =
 am_ at DRIVER_NAME@_drv_la_OBJECTS = @DRIVER_NAME at .lo emuMB.lo \
-	emuWheel.lo draglock.lo
+	emuWheel.lo draglock.lo GetRCInputs.lo
 @DRIVER_NAME at _drv_la_OBJECTS = $(am_ at DRIVER_NAME@_drv_la_OBJECTS)
 AM_V_lt = $(am__v_lt_$(V))
 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@ -281,7 +281,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
                                @DRIVER_NAME at .h \
                                emuMB.c \
                                emuWheel.c \
-                               draglock.c
+                               draglock.c \
+                               GetRCInputs.c
 
 all: all-am
 
diff --git a/src/evdev.c b/src/evdev.c
index 512e957..7a0af1c 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -296,6 +296,575 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
     pEvdev->num_queue++;
 }
 
+/*
+ * Those are new keycodes added for 2.6.38 and used by some Remote Controllers
+ */
+#ifndef KEY_10CHANNELSUP
+#define KEY_10CHANNELSUP        0x1b8   /* 10 channels up (10+) */
+#define KEY_10CHANNELSDOWN      0x1b9   /* 10 channels down (10-) */
+#endif
+
+int rc_keymap[] = {
+	[KEY_RESERVED] = KEY_RESERVED,                    /* not assigned */
+	[KEY_ESC] = KEY_ESC,
+	[KEY_1] = KEY_1,
+	[KEY_2] = KEY_2,
+	[KEY_3] = KEY_3,
+	[KEY_4] = KEY_4,
+	[KEY_5] = KEY_5,
+	[KEY_6] = KEY_6,
+	[KEY_7] = KEY_7,
+	[KEY_8] = KEY_8,
+	[KEY_9] = KEY_9,
+	[KEY_0] = KEY_0,
+	[KEY_MINUS] = KEY_MINUS,
+	[KEY_EQUAL] = KEY_EQUAL,
+	[KEY_BACKSPACE] = KEY_BACKSPACE,
+	[KEY_TAB] = KEY_TAB,
+	[KEY_Q] = KEY_Q,
+	[KEY_W] = KEY_W,
+	[KEY_E] = KEY_E,
+	[KEY_R] = KEY_R,
+	[KEY_T] = KEY_T,
+	[KEY_Y] = KEY_Y,
+	[KEY_U] = KEY_U,
+	[KEY_I] = KEY_I,
+	[KEY_O] = KEY_O,
+	[KEY_P] = KEY_P,
+	[KEY_LEFTBRACE] = KEY_LEFTBRACE,
+	[KEY_RIGHTBRACE] = KEY_RIGHTBRACE,
+	[KEY_ENTER] = KEY_ENTER,
+	[KEY_LEFTCTRL] = KEY_LEFTCTRL,
+	[KEY_A] = KEY_A,
+	[KEY_S] = KEY_S,
+	[KEY_D] = KEY_D,
+	[KEY_F] = KEY_F,
+	[KEY_G] = KEY_G,
+	[KEY_H] = KEY_H,
+	[KEY_J] = KEY_J,
+	[KEY_K] = KEY_K,
+	[KEY_L] = KEY_L,
+	[KEY_SEMICOLON] = KEY_SEMICOLON,
+	[KEY_APOSTROPHE] = KEY_APOSTROPHE,
+	[KEY_GRAVE] = KEY_GRAVE,
+	[KEY_LEFTSHIFT] = KEY_LEFTSHIFT,
+	[KEY_BACKSLASH] = KEY_BACKSLASH,
+	[KEY_Z] = KEY_Z,
+	[KEY_X] = KEY_X,
+	[KEY_C] = KEY_C,
+	[KEY_V] = KEY_V,
+	[KEY_B] = KEY_B,
+	[KEY_N] = KEY_N,
+	[KEY_M] = KEY_M,
+	[KEY_COMMA] = KEY_COMMA,
+	[KEY_DOT] = KEY_DOT,
+	[KEY_SLASH] = KEY_SLASH,
+	[KEY_RIGHTSHIFT] = KEY_RIGHTSHIFT,
+	[KEY_KPASTERISK] = KEY_KPASTERISK,
+	[KEY_LEFTALT] = KEY_LEFTALT,
+	[KEY_SPACE] = KEY_SPACE,
+	[KEY_CAPSLOCK] = KEY_CAPSLOCK,
+	[KEY_F1] = KEY_F1,
+	[KEY_F2] = KEY_F2,
+	[KEY_F3] = KEY_F3,
+	[KEY_F4] = KEY_F4,
+	[KEY_F5] = KEY_F5,
+	[KEY_F6] = KEY_F6,
+	[KEY_F7] = KEY_F7,
+	[KEY_F8] = KEY_F8,
+	[KEY_F9] = KEY_F9,
+	[KEY_F10] = KEY_F10,
+	[KEY_NUMLOCK] = KEY_NUMLOCK,
+	[KEY_SCROLLLOCK] = KEY_RESERVED,                  /* not assigned */
+	[KEY_KP7] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP8] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP9] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KPMINUS] = KEY_KPMINUS,
+	[KEY_KP4] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP5] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP6] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KPPLUS] = KEY_KPPLUS,
+	[KEY_KP1] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP2] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP3] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KP0] = KEY_RESERVED,                         /* not assigned */
+	[KEY_KPDOT] = KEY_RESERVED,                       /* not assigned */
+	[84] = KEY_RESERVED,                              /* not defined on linux/input.h yet */
+	[KEY_ZENKAKUHANKAKU] = KEY_RESERVED,              /* not assigned */
+	[KEY_102ND] = KEY_RESERVED,                       /* not assigned */
+	[KEY_F11] = KEY_F11,
+	[KEY_F12] = KEY_F12,
+	[KEY_RO] = KEY_RESERVED,                          /* not assigned */
+	[KEY_KATAKANA] = KEY_RESERVED,                    /* not assigned */
+	[KEY_HIRAGANA] = KEY_RESERVED,                    /* not assigned */
+	[KEY_HENKAN] = KEY_RESERVED,                      /* not assigned */
+	[KEY_KATAKANAHIRAGANA] = KEY_RESERVED,            /* not assigned */
+	[KEY_MUHENKAN] = KEY_RESERVED,                    /* not assigned */
+	[KEY_KPJPCOMMA] = KEY_RESERVED,                   /* not assigned */
+	[KEY_KPENTER] = KEY_RESERVED,                     /* not assigned */
+	[KEY_RIGHTCTRL] = KEY_RESERVED,                   /* not assigned */
+	[KEY_KPSLASH] = KEY_RESERVED,                     /* not assigned */
+	[KEY_SYSRQ] = KEY_RESERVED,                       /* not assigned */
+	[KEY_RIGHTALT] = KEY_RESERVED,                    /* not assigned */
+	[KEY_LINEFEED] = KEY_RESERVED,                    /* not assigned */
+	[KEY_HOME] = KEY_HOME,
+	[KEY_UP] = KEY_UP,
+	[KEY_PAGEUP] = KEY_PAGEUP,
+	[KEY_LEFT] = KEY_LEFT,
+	[KEY_RIGHT] = KEY_RIGHT,
+	[KEY_END] = KEY_END,
+	[KEY_DOWN] = KEY_DOWN,
+	[KEY_PAGEDOWN] = KEY_PAGEDOWN,
+	[KEY_INSERT] = KEY_INSERT,
+	[KEY_DELETE] = KEY_DELETE,
+	[KEY_MACRO] = KEY_MACRO,
+	[KEY_MUTE] = KEY_MUTE,
+	[KEY_VOLUMEDOWN] = KEY_VOLUMEDOWN,
+	[KEY_VOLUMEUP] = KEY_VOLUMEUP,
+	[KEY_POWER] = KEY_POWER,
+	[KEY_KPEQUAL] = KEY_RESERVED,                     /* not assigned */
+	[KEY_KPPLUSMINUS] = KEY_KPPLUSMINUS,
+	[KEY_PAUSE] = KEY_PAUSE,
+	[KEY_SCALE] = KEY_RESERVED,                       /* not assigned */
+	[KEY_KPCOMMA] = KEY_RESERVED,                     /* not assigned */
+	[KEY_HANGEUL] = KEY_RESERVED,                     /* not assigned */
+	[KEY_HANJA] = KEY_RESERVED,                       /* not assigned */
+	[KEY_YEN] = KEY_RESERVED,                         /* not assigned */
+	[KEY_LEFTMETA] = KEY_RESERVED,                    /* not assigned */
+	[KEY_RIGHTMETA] = KEY_RESERVED,                   /* not assigned */
+	[KEY_COMPOSE] = KEY_RESERVED,                     /* not assigned */
+	[KEY_STOP] = KEY_STOP,
+	[KEY_AGAIN] = KEY_AGAIN,
+	[KEY_PROPS] = KEY_PROPS,
+	[KEY_UNDO] = KEY_UNDO,
+	[KEY_FRONT] = KEY_FRONT,
+	[KEY_COPY] = KEY_RESERVED,                        /* not assigned */
+	[KEY_OPEN] = KEY_OPEN,
+	[KEY_PASTE] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FIND] = KEY_RESERVED,                        /* not assigned */
+	[KEY_CUT] = KEY_RESERVED,                         /* not assigned */
+	[KEY_HELP] = KEY_HELP,
+	[KEY_MENU] = KEY_MENU,
+	[KEY_CALC] = KEY_RESERVED,                        /* not assigned */
+	[KEY_SETUP] = KEY_SETUP,
+	[KEY_SLEEP] = KEY_SLEEP,
+	[KEY_WAKEUP] = KEY_RESERVED,                      /* not assigned */
+	[KEY_FILE] = KEY_RESERVED,                        /* not assigned */
+	[KEY_SENDFILE] = KEY_RESERVED,                    /* not assigned */
+	[KEY_DELETEFILE] = KEY_RESERVED,                  /* not assigned */
+	[KEY_XFER] = KEY_RESERVED,                        /* not assigned */
+	[KEY_PROG1] = KEY_PROG1,
+	[KEY_PROG2] = KEY_PROG2,
+	[KEY_WWW] = KEY_WWW,
+	[KEY_MSDOS] = KEY_RESERVED,                       /* not assigned */
+	[KEY_SCREENLOCK] = KEY_RESERVED,                  /* not assigned */
+	[KEY_DIRECTION] = KEY_RESERVED,                   /* not assigned */
+	[KEY_CYCLEWINDOWS] = KEY_CYCLEWINDOWS,
+	[KEY_MAIL] = KEY_MAIL,
+	[KEY_BOOKMARKS] = KEY_BOOKMARKS,
+	[KEY_COMPUTER] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BACK] = KEY_BACK,
+	[KEY_FORWARD] = KEY_FORWARD,
+	[KEY_CLOSECD] = KEY_CLOSECD,
+	[KEY_EJECTCD] = KEY_EJECTCD,
+	[KEY_EJECTCLOSECD] = KEY_EJECTCLOSECD,
+	[KEY_NEXTSONG] = KEY_NEXTSONG,
+	[KEY_PLAYPAUSE] = KEY_PLAYPAUSE,
+	[KEY_PREVIOUSSONG] = KEY_PREVIOUSSONG,
+	[KEY_STOPCD] = KEY_STOPCD,
+	[KEY_RECORD] = KEY_RECORD,
+	[KEY_REWIND] = KEY_REWIND,
+	[KEY_PHONE] = KEY_PHONE,
+	[KEY_ISO] = KEY_RESERVED,                         /* not assigned */
+	[KEY_CONFIG] = KEY_CONFIG,
+	[KEY_HOMEPAGE] = KEY_HOMEPAGE,
+	[KEY_REFRESH] = KEY_REFRESH,
+	[KEY_EXIT] = KEY_EXIT,
+	[KEY_MOVE] = KEY_RESERVED,                        /* not assigned */
+	[KEY_EDIT] = KEY_EDIT,
+	[KEY_SCROLLUP] = KEY_RESERVED,                    /* not assigned */
+	[KEY_SCROLLDOWN] = KEY_RESERVED,                  /* not assigned */
+	[KEY_KPLEFTPAREN] = KEY_RESERVED,                 /* not assigned */
+	[KEY_KPRIGHTPAREN] = KEY_RESERVED,                /* not assigned */
+	[KEY_NEW] = KEY_NEW,
+	[KEY_REDO] = KEY_RESERVED,                        /* not assigned */
+	[KEY_F13] = KEY_F13,
+	[KEY_F14] = KEY_F14,
+	[KEY_F15] = KEY_F15,
+	[KEY_F16] = KEY_F16,
+	[KEY_F17] = KEY_F17,
+	[KEY_F18] = KEY_F18,
+	[KEY_F19] = KEY_F19,
+	[KEY_F20] = KEY_RESERVED,                         /* not assigned */
+	[KEY_F21] = KEY_F21,
+	[KEY_F22] = KEY_F22,
+	[KEY_F23] = KEY_F23,
+	[KEY_F24] = KEY_F24,
+	[195] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[196] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[197] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[198] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[199] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_PLAYCD] = KEY_PLAYCD,
+	[KEY_PAUSECD] = KEY_PAUSECD,
+	[KEY_PROG3] = KEY_PROG3,
+	[KEY_PROG4] = KEY_RESERVED,                       /* not assigned */
+	[KEY_DASHBOARD] = KEY_RESERVED,                   /* not assigned */
+	[KEY_SUSPEND] = KEY_SUSPEND,
+	[KEY_CLOSE] = KEY_CLOSE,
+	[KEY_PLAY] = KEY_PLAY,
+	[KEY_FASTFORWARD] = KEY_FASTFORWARD,
+	[KEY_BASSBOOST] = KEY_RESERVED,                   /* not assigned */
+	[KEY_PRINT] = KEY_PRINT,
+	[KEY_HP] = KEY_RESERVED,                          /* not assigned */
+	[KEY_CAMERA] = KEY_CAMERA,
+	[KEY_SOUND] = KEY_SOUND,
+	[KEY_QUESTION] = KEY_RESERVED,                    /* not assigned */
+	[KEY_EMAIL] = KEY_EMAIL,
+	[KEY_CHAT] = KEY_RESERVED,                        /* not assigned */
+	[KEY_SEARCH] = KEY_SEARCH,
+	[KEY_CONNECT] = KEY_RESERVED,                     /* not assigned */
+	[KEY_FINANCE] = KEY_RESERVED,                     /* not assigned */
+	[KEY_SPORT] = KEY_RESERVED,                       /* not assigned */
+	[KEY_SHOP] = KEY_RESERVED,                        /* not assigned */
+	[KEY_ALTERASE] = KEY_RESERVED,                    /* not assigned */
+	[KEY_CANCEL] = KEY_CANCEL,
+	[KEY_BRIGHTNESSDOWN] = KEY_BRIGHTNESSDOWN,
+	[KEY_BRIGHTNESSUP] = KEY_BRIGHTNESSUP,
+	[KEY_MEDIA] = KEY_MEDIA,
+	[KEY_SWITCHVIDEOMODE] = KEY_SWITCHVIDEOMODE,
+	[KEY_KBDILLUMTOGGLE] = KEY_RESERVED,              /* not assigned */
+	[KEY_KBDILLUMDOWN] = KEY_RESERVED,                /* not assigned */
+	[KEY_KBDILLUMUP] = KEY_RESERVED,                  /* not assigned */
+	[KEY_SEND] = KEY_RESERVED,                        /* not assigned */
+	[KEY_REPLY] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FORWARDMAIL] = KEY_RESERVED,                 /* not assigned */
+	[KEY_SAVE] = KEY_SAVE,
+	[KEY_DOCUMENTS] = KEY_RESERVED,                   /* not assigned */
+	[KEY_BATTERY] = KEY_RESERVED,                     /* not assigned */
+	[KEY_BLUETOOTH] = KEY_RESERVED,                   /* not assigned */
+	[KEY_WLAN] = KEY_RESERVED,                        /* not assigned */
+	[KEY_UWB] = KEY_RESERVED,                         /* not assigned */
+	[KEY_UNKNOWN] = KEY_UNKNOWN,
+	[KEY_VIDEO_NEXT] = KEY_RESERVED,                  /* not assigned */
+	[KEY_VIDEO_PREV] = KEY_RESERVED,                  /* not assigned */
+	[KEY_BRIGHTNESS_CYCLE] = KEY_RESERVED,            /* not assigned */
+	[KEY_BRIGHTNESS_ZERO] = KEY_RESERVED,             /* not assigned */
+	[KEY_DISPLAY_OFF] = KEY_RESERVED,                 /* not assigned */
+	[KEY_WIMAX] = KEY_RESERVED,                       /* not assigned */
+	[KEY_RFKILL] = KEY_RESERVED,                      /* not assigned */
+	[248] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[249] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[250] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[251] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[252] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[253] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[254] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[255] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[256] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[257] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[258] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[259] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[260] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[261] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[262] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[263] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[264] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[265] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[266] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[267] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[268] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[269] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[270] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[271] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[272] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[273] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[274] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[275] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[276] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[277] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[278] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[279] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[280] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[281] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[282] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[283] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[284] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[285] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[286] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[287] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[288] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[289] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[290] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[291] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[292] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[293] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[294] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[295] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[296] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[297] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[298] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[299] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[300] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[301] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[302] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[303] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[304] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[305] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[306] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[307] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[308] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[309] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[310] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[311] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[312] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[313] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[314] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[315] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[316] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[317] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[318] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[319] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[320] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[321] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[322] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[323] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[324] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[325] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[326] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[327] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[328] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[329] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[330] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[331] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[332] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[333] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[334] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[335] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[336] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[337] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[338] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[339] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[340] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[341] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[342] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[343] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[344] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[345] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[346] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[347] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[348] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[349] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[350] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[351] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_OK] = 125,                                   /* KEY_LEFTMETA */
+	[KEY_SELECT] = 153,                               /* KEY_DIRECTION */
+	[KEY_GOTO] = 94,                                  /* KEY_MUHENKAN */
+	[KEY_CLEAR] = 84,                                 /* currently unused */
+	[KEY_POWER2] = 135,                               /* KEY_PASTE */
+	[KEY_OPTION] = 126,                               /* KEY_RIGHTMETA */
+	[KEY_INFO] = 96,                                  /* KEY_KPENTER */
+	[KEY_TIME] = 180,                                 /* KEY_KPRIGHTPAREN */
+	[KEY_VENDOR] = KEY_RESERVED,                      /* not assigned */
+	[KEY_ARCHIVE] = KEY_RESERVED,                     /* not assigned */
+	[KEY_PROGRAM] = KEY_RESERVED,                     /* not assigned */
+	[KEY_CHANNEL] = 81,                               /* KEY_KP3 */
+	[KEY_FAVORITES] = 91,                             /* KEY_HIRAGANA */
+	[KEY_EPG] = 90,                                   /* KEY_KATAKANA */
+	[KEY_PVR] = 137,                                  /* KEY_CUT */
+	[KEY_MHP] = 120,                                  /* KEY_SCALE */
+	[KEY_LANGUAGE] = 98,                              /* KEY_KPSLASH */
+	[KEY_TITLE] = 182,                                /* KEY_REDO */
+	[KEY_SUBTITLE] = 178,                             /* KEY_SCROLLDOWN */
+	[KEY_ANGLE] = 73,                                 /* KEY_KP9 */
+	[KEY_ZOOM] = 203,                                 /* KEY_PROG4 */
+	[KEY_MODE] = 121,                                 /* KEY_KPCOMMA */
+	[KEY_KEYBOARD] = 97,                              /* KEY_RIGHTCTRL */
+	[KEY_SCREEN] = 151,                               /* KEY_MSDOS */
+	[KEY_PC] = 127,                                   /* KEY_COMPOSE */
+	[KEY_TV] = 195,                                   /* currently unused */
+	[KEY_TV2] = 196,                                  /* currently unused */
+	[KEY_VCR] = 197,                                  /* currently unused */
+	[KEY_VCR2] = KEY_RESERVED,                        /* not assigned */
+	[KEY_SAT] = 147,                                  /* KEY_XFER */
+	[KEY_SAT2] = KEY_RESERVED,                        /* not assigned */
+	[KEY_CD] = 80,                                    /* KEY_KP2 */
+	[KEY_TAPE] = KEY_RESERVED,                        /* not assigned */
+	[KEY_RADIO] = 140,                                /* KEY_CALC */
+	[KEY_TUNER] = 190,                                /* KEY_F20 */
+	[KEY_PLAYER] = 133,                               /* KEY_COPY */
+	[KEY_TEXT] = 179,                                 /* KEY_KPLEFTPAREN */
+	[KEY_DVD] = 86,                                   /* KEY_102ND */
+	[KEY_AUX] = 76,                                   /* KEY_KP5 */
+	[KEY_MP3] = 122,                                  /* KEY_HANGEUL */
+	[KEY_AUDIO] = 75,                                 /* KEY_KP4 */
+	[KEY_VIDEO] = 198,                                /* currently unused */
+	[KEY_DIRECTORY] = KEY_RESERVED,                   /* not assigned */
+	[KEY_LIST] = 100,                                 /* KEY_RIGHTALT */
+	[KEY_MEMO] = KEY_RESERVED,                        /* not assigned */
+	[KEY_CALENDAR] = KEY_RESERVED,                    /* not assigned */
+	[KEY_RED] = 143,                                  /* KEY_WAKEUP */
+	[KEY_GREEN] = 95,                                 /* KEY_KPJPCOMMA */
+	[KEY_YELLOW] = 199,                               /* currently unused */
+	[KEY_BLUE] = 77,                                  /* KEY_KP6 */
+	[KEY_CHANNELUP] = 83,                             /* KEY_KPDOT */
+	[KEY_CHANNELDOWN] = 82,                           /* KEY_KP0 */
+	[KEY_FIRST] = 92,                                 /* KEY_HENKAN */
+	[KEY_LAST] = 99,                                  /* KEY_SYSRQ */
+	[KEY_AB] = 72,                                    /* KEY_KP8 */
+	[KEY_NEXT] = 123,                                 /* KEY_HANJA */
+	[KEY_RESTART] = 144,                              /* KEY_FILE */
+	[KEY_SLOW] = 170,                                 /* KEY_ISO */
+	[KEY_SHUFFLE] = 157,                              /* KEY_COMPUTER */
+	[KEY_BREAK] = 79,                                 /* KEY_KP1 */
+	[KEY_PREVIOUS] = 136,                             /* KEY_FIND */
+	[KEY_DIGITS] = 85,                                /* KEY_ZENKAKUHANKAKU */
+	[KEY_TEEN] = KEY_RESERVED,                        /* not assigned */
+	[KEY_TWEN] = KEY_RESERVED,                        /* not assigned */
+	[KEY_VIDEOPHONE] = KEY_RESERVED,                  /* not assigned */
+	[KEY_GAMES] = KEY_RESERVED,                       /* not assigned */
+	[KEY_ZOOMIN] = 204,                               /* KEY_DASHBOARD */
+	[KEY_ZOOMOUT] = 209,                              /* KEY_BASSBOOST */
+	[KEY_ZOOMRESET] = KEY_RESERVED,                   /* not assigned */
+	[KEY_WORDPROCESSOR] = KEY_RESERVED,               /* not assigned */
+	[KEY_EDITOR] = KEY_RESERVED,                      /* not assigned */
+	[KEY_SPREADSHEET] = KEY_RESERVED,                 /* not assigned */
+	[KEY_GRAPHICSEDITOR] = KEY_RESERVED,              /* not assigned */
+	[KEY_PRESENTATION] = KEY_RESERVED,                /* not assigned */
+	[KEY_DATABASE] = KEY_RESERVED,                    /* not assigned */
+	[KEY_NEWS] = KEY_RESERVED,                        /* not assigned */
+	[KEY_VOICEMAIL] = KEY_RESERVED,                   /* not assigned */
+	[KEY_ADDRESSBOOK] = KEY_RESERVED,                 /* not assigned */
+	[KEY_MESSENGER] = KEY_RESERVED,                   /* not assigned */
+	[KEY_DISPLAYTOGGLE] = KEY_RESERVED,               /* not assigned */
+	[KEY_SPELLCHECK] = KEY_RESERVED,                  /* not assigned */
+	[KEY_LOGOFF] = KEY_RESERVED,                      /* not assigned */
+	[KEY_DOLLAR] = KEY_RESERVED,                      /* not assigned */
+	[KEY_EURO] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FRAMEBACK] = KEY_RESERVED,                   /* not assigned */
+	[KEY_FRAMEFORWARD] = KEY_RESERVED,                /* not assigned */
+	[KEY_CONTEXT_MENU] = KEY_RESERVED,                /* not assigned */
+	[KEY_MEDIA_REPEAT] = 117,                         /* KEY_KPEQUAL */
+	[KEY_10CHANNELSUP] = 71,                          /* KEY_KP7 */
+	[KEY_10CHANNELSDOWN] = 70,                        /* KEY_SCROLLLOCK */
+	[442] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[443] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[444] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[445] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[446] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[447] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_DEL_EOL] = KEY_RESERVED,                     /* not assigned */
+	[KEY_DEL_EOS] = KEY_RESERVED,                     /* not assigned */
+	[KEY_INS_LINE] = KEY_RESERVED,                    /* not assigned */
+	[KEY_DEL_LINE] = KEY_RESERVED,                    /* not assigned */
+	[452] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[453] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[454] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[455] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[456] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[457] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[458] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[459] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[460] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[461] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[462] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[463] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_FN] = 93,                                    /* KEY_KATAKANAHIRAGANA */
+	[KEY_FN_ESC] = KEY_RESERVED,                      /* not assigned */
+	[KEY_FN_F1] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F2] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F3] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F4] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F5] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F6] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F7] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F8] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F9] = KEY_RESERVED,                       /* not assigned */
+	[KEY_FN_F10] = KEY_RESERVED,                      /* not assigned */
+	[KEY_FN_F11] = KEY_RESERVED,                      /* not assigned */
+	[KEY_FN_F12] = KEY_RESERVED,                      /* not assigned */
+	[KEY_FN_1] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FN_2] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FN_D] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FN_E] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FN_F] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FN_S] = KEY_RESERVED,                        /* not assigned */
+	[KEY_FN_B] = KEY_RESERVED,                        /* not assigned */
+	[485] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[486] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[487] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[488] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[489] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[490] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[491] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[492] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[493] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[494] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[495] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[496] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_BRL_DOT1] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT2] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT3] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT4] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT5] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT6] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT7] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT8] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT9] = KEY_RESERVED,                    /* not assigned */
+	[KEY_BRL_DOT10] = KEY_RESERVED,                   /* not assigned */
+	[507] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[508] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[509] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[510] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[511] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_NUMERIC_0] = 11,                             /* KEY_0 */
+	[KEY_NUMERIC_1] = 2,                              /* KEY_1 */
+	[KEY_NUMERIC_2] = 3,                              /* KEY_2 */
+	[KEY_NUMERIC_3] = 4,                              /* KEY_3 */
+	[KEY_NUMERIC_4] = 5,                              /* KEY_4 */
+	[KEY_NUMERIC_5] = 6,                              /* KEY_5 */
+	[KEY_NUMERIC_6] = 7,                              /* KEY_6 */
+	[KEY_NUMERIC_7] = 8,                              /* KEY_7 */
+	[KEY_NUMERIC_8] = 9,                              /* KEY_8 */
+	[KEY_NUMERIC_9] = 10,                             /* KEY_9 */
+	[KEY_NUMERIC_STAR] = 55,                          /* KEY_KPASTERISK */
+	[KEY_NUMERIC_POUND] = 124,                        /* KEY_YEN */
+	[524] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[525] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[526] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[527] = KEY_RESERVED,                             /* not defined on linux/input.h yet */
+	[KEY_CAMERA_FOCUS] = KEY_RESERVED,                /* not assigned */
+	[KEY_WPS_BUTTON] = KEY_RESERVED,                  /* not assigned */
+	[530] = KEY_RESERVED,                             /* KEY_TOUCHPAD_TOGGLE - not assigned */
+	[531] = KEY_RESERVED,                             /* KEY_TOUCHPAD_ON - not assigned */
+	[531] = KEY_RESERVED,                             /* KEY_TOUCHPAD_OFF - not assigned */
+};
+
+void
+EvdevQueueRCEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
+{
+    int code;
+    EventQueuePtr pQueue;
+    EvdevPtr pEvdev = pInfo->private;
+
+    if (ev->code >= ArrayLength(rc_keymap))
+        code = KEY_RESERVED + MIN_KEYCODE;
+    else
+        code = rc_keymap[ev->code] + MIN_KEYCODE;
+
+    if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
+    {
+        xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
+        return;
+    }
+
+    pQueue = &pEvdev->queue[pEvdev->num_queue];
+    pQueue->type = EV_QUEUE_KEY;
+    pQueue->key = code;
+    pQueue->val = value;
+    pEvdev->num_queue++;
+}
+
 void
 EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
 {
@@ -468,6 +1037,8 @@ EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
 
     if (button)
         EvdevQueueButtonEvent(pInfo, button, value);
+    else if (pEvdev->flags & EVDEV_RC_EVENTS)
+        EvdevQueueRCEvent(pInfo, ev, value);
     else
         EvdevQueueKbdEvent(pInfo, ev, value);
 }
@@ -2012,6 +2583,8 @@ EvdevOpenDevice(InputInfoPtr pInfo)
 {
     EvdevPtr pEvdev = pInfo->private;
     char *device = (char*)pEvdev->device;
+    RCDeviceListPtr pRCDevList;
+    int NumDevices, i;
 
     if (!device)
     {
@@ -2047,6 +2620,25 @@ EvdevOpenDevice(InputInfoPtr pInfo)
         return FALSE;
     }
 
+    /* Check if the device is a remote controller */
+    pRCDevList = GetRCInputDevices(&NumDevices);
+    for (i = 0; i < NumDevices; i++) {
+        if (!strcmp(device, pRCDevList[i].InputName)) {
+             pEvdev->flags |= EVDEV_RC_EVENTS;
+             break;
+        }
+    }
+    if (pEvdev->flags & EVDEV_RC_EVENTS) {
+        xf86Msg(X_INFO, "%s: device '%s' is a Remote Controller\n",
+                pInfo->name, device);
+    } else {
+        xf86Msg(X_INFO, "%s: device '%s' IS NOT a Remote Controller\n",
+                pInfo->name, device);
+    }
+
+    if (pRCDevList)
+        free(pRCDevList);
+
     return TRUE;
 }
 
diff --git a/src/evdev.h b/src/evdev.h
index 4945140..b891992 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -71,6 +71,7 @@
 #define EVDEV_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
 #define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
 #define EVDEV_RELATIVE_MODE	(1 << 11) /* Force relative events for devices with absolute axes */
+#define EVDEV_RC_EVENTS         (1 << 12) /* Device is a remote controller */
 
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
 #define HAVE_PROPERTIES 1
@@ -195,6 +196,11 @@ typedef struct {
     EventQueueRec           queue[EVDEV_MAXQUEUE];
 } EvdevRec, *EvdevPtr;
 
+typedef struct {
+    char SysfsName[255];    /* Device sysfs node name */
+    char InputName[255];    /* Input device file name */
+} RCDeviceList, *RCDeviceListPtr;
+
 /* Event posting functions */
 void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value);
 void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value);
@@ -224,6 +230,9 @@ BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv);
 void EvdevDragLockPreInit(InputInfoPtr pInfo);
 BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value);
 
+/* GetRCInputs code */
+RCDeviceListPtr GetRCInputDevices(int *num);
+
 #ifdef HAVE_PROPERTIES
 void EvdevMBEmuInitProperty(DeviceIntPtr);
 void EvdevWheelEmuInitProperty(DeviceIntPtr);


More information about the xorg-devel mailing list