From 8778bc0d63273315e071eb7140ff42a44acba42d Mon Sep 17 00:00:00 2001 From: Jeong-Hyun Kang Date: Thu, 5 Feb 2015 15:17:11 +0900 Subject: [PATCH] Implement remap for support keys which had keycode bigger than 255 Change-Id: Ib534968886004851df605a1314de4b4a2f899cc0 --- packaging/xf86-input-evdev.spec | 1 + src/evdev.c | 91 +++++++++++++++++++++++++++++++++++++++++ src/evdev.h | 13 ++++++ 3 files changed, 105 insertions(+) diff --git a/packaging/xf86-input-evdev.spec b/packaging/xf86-input-evdev.spec index 3becc13..dd11dfa 100644 --- a/packaging/xf86-input-evdev.spec +++ b/packaging/xf86-input-evdev.spec @@ -44,6 +44,7 @@ including most mice, keyboards, tablets and touchscreens. cp %{SOURCE1001} . %build +CFLAGS="$CFLAGS -D_F_REMAP_KEYS_ " %configure make %{?_smp_mflags} diff --git a/src/evdev.c b/src/evdev.c index 54772c7..facfa32 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -140,6 +140,48 @@ static Atom prop_virtual; * cannot be used by evdev, leaving us with a space of 2 at the end. */ static EvdevPtr evdev_devices[MAXDEVICES] = {NULL}; +#ifdef _F_REMAP_KEYS_ +static uint16_t +remapKey(EvdevPtr ev, uint16_t code) +{ + uint8_t slice=code/256; + uint8_t offs=code%256; + + if (!ev->keyremap) return code; + if (!(ev->keyremap->sl[slice])) return code; + if (!(ev->keyremap->sl[slice]->cd[offs])) return code; + return ev->keyremap->sl[slice]->cd[offs]; +} + +static void +addRemap(EvdevPtr ev,uint16_t code,uint8_t value) +{ + uint8_t slice=code/256; + uint8_t offs=code%256; + + if (!ev->keyremap) { + ev->keyremap=(EvdevKeyRemapPtr)calloc(sizeof(EvdevKeyRemap),1); + } + if (!ev->keyremap->sl[slice]) { + ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)calloc(sizeof(EvdevKeyRemapSlice),1); + } + ev->keyremap->sl[slice]->cd[offs]=value; +} + +static void +freeRemap(EvdevPtr ev) +{ + uint16_t slice; + if (!ev->keyremap) return; + for (slice=0;slice<256;++slice) { + if (!ev->keyremap->sl[slice]) continue; + free(ev->keyremap->sl[slice]); + } + free(ev->keyremap); + ev->keyremap=0; +} +#endif //_F_REMAP_KEYS_ + static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode) { InputInfoPtr pInfo; @@ -332,6 +374,44 @@ static int wheel_left_button = 6; static int wheel_right_button = 7; #endif +#ifdef _F_REMAP_KEYS_ +static void +SetRemapOption(InputInfoPtr pInfo,const char* name) +{ + char *s,*c; + unsigned long int code,value; + int consumed; + EvdevPtr ev = pInfo->private; + + s = xf86SetStrOption(pInfo->options, name, NULL); + if (!s) return; + if (!s[0]) { + free(s); + return; + } + + c=s; + while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) { + c+=consumed; + if (code < 0 || code > 65535L) { + xf86Msg(X_ERROR,"%s: input code %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code); + continue; + } + if (value < MIN_KEYCODE || value > 255) { + xf86Msg(X_ERROR,"%s: output value %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,value); + continue; + } + xf86Msg(X_INFO,"%s: remapping %ld into %ld.\n",pInfo->name,code,value); + addRemap(ev,code,value-MIN_KEYCODE); + } + + if (*c!='\0') { + xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n", + pInfo->name, c); + } +} +#endif //_F_REMAP_KEYS_ + static EventQueuePtr EvdevNextInQueue(InputInfoPtr pInfo) { @@ -350,7 +430,11 @@ EvdevNextInQueue(InputInfoPtr pInfo) void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) { +#ifdef _F_REMAP_KEYS_ + int code = remapKey((EvdevPtr)(pInfo->private),ev->code) + MIN_KEYCODE; +#else //_F_REMAP_KEYS_ int code = ev->code + MIN_KEYCODE; +#endif //_F_REMAP_KEYS_ EventQueuePtr pQueue; /* Filter all repeated events from device. @@ -1191,6 +1275,10 @@ EvdevAddKeyClass(DeviceIntPtr device) if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl)) return !Success; +#ifdef _F_REMAP_KEYS_ + SetRemapOption(pInfo,"event_key_remap"); +#endif //_F_REMAP_KEYS_ + return Success; } @@ -1878,6 +1966,9 @@ EvdevProc(DeviceIntPtr device, int what) EvdevCloseDevice(pInfo); EvdevFreeMasks(pEvdev); EvdevRemoveDevice(pInfo); +#ifdef _F_REMAP_KEYS_ + freeRemap(pEvdev); +#endif //_F_REMAP_KEYS_ pEvdev->min_maj = 0; break; diff --git a/src/evdev.h b/src/evdev.h index c2f9246..44bb42b 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -145,6 +145,15 @@ typedef struct { #endif } EventQueueRec, *EventQueuePtr; +#ifdef _F_REMAP_KEYS_ +typedef struct { + uint8_t cd[256]; +} EvdevKeyRemapSlice; +typedef struct { + EvdevKeyRemapSlice* sl[256]; +} EvdevKeyRemap, *EvdevKeyRemapPtr; +#endif //_F_REMAP_KEYS_ + typedef struct { unsigned short id_vendor; unsigned short id_product; @@ -228,6 +237,10 @@ typedef struct { unsigned char btnmap[32]; /* config-file specified button mapping */ +#ifdef _F_REMAP_KEYS_ + EvdevKeyRemapPtr keyremap; +#endif //_F_REMAP_KEYS_ + int reopen_attempts; /* max attempts to re-open after read failure */ int reopen_left; /* number of attempts left to re-open the device */ OsTimerPtr reopen_timer; -- 2.7.4