From 0b8c6f1e18ff28e75bda75d2cc2c1c36c8fae4fb Mon Sep 17 00:00:00 2001 From: Gianni Ceccarelli Date: Tue, 3 Apr 2012 12:29:03 +0100 Subject: code-remap for 2.9.0 Thanks to Tristan King for reminding me to do it and checking that it works --- man/evdev.man | 11 ++++++++ src/evdev.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/evdev.h | 10 ++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/man/evdev.man b/man/evdev.man index 06613fc..08a7995 100644 --- a/man/evdev.man +++ b/man/evdev.man @@ -238,6 +238,17 @@ Default: "1". Property: "Evdev Scrolling Distance". .BI "Option \*qDialDelta\*q \*q" integer \*q The amount of motion considered one unit of turning the dial. Default: "1". Property: "Evdev Scrolling Distance". +.BI "Option \*qevent_key_remap\*q \*q" "integer=integer ..." \*q +Specifies a set of mappings for key events; the number on the +left-hand side of the equal sign must be an evdev keycode (look it up +with +.B "showkey -k" +; it can be between 0 and 65535), the number on the right-hand side of +the equal sign must be an X11 keycode (look it up in the +.B "__projectroot__/share/X11/xkb/keycodes/evdev" +file; it can be between 8 and 255). Integers can be specified as in C +source files (base-10, base-8 if they start with 0, base-16 if they +start with 0x). .SH SUPPORTED PROPERTIES The following properties are provided by the diff --git a/src/evdev.c b/src/evdev.c index 9cfc982..272b9f6 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -135,6 +135,46 @@ static Atom prop_device; static Atom prop_virtual; static Atom prop_scroll_dist; +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; +} + static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode) { InputInfoPtr pInfo; @@ -261,6 +301,42 @@ static int wheel_left_button = 6; static int wheel_right_button = 7; #endif +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); + } +} + static EventQueuePtr EvdevNextInQueue(InputInfoPtr pInfo) { @@ -279,7 +355,7 @@ EvdevNextInQueue(InputInfoPtr pInfo) void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) { - int code = ev->code + MIN_KEYCODE; + int code = remapKey((EvdevPtr)(pInfo->private),ev->code) + MIN_KEYCODE; EventQueuePtr pQueue; /* Filter all repeated events from device. @@ -1161,6 +1237,8 @@ EvdevAddKeyClass(DeviceIntPtr device) rmlvo.variant = xf86SetStrOption(pInfo->options, "xkb_variant", NULL); rmlvo.options = xf86SetStrOption(pInfo->options, "xkb_options", NULL); + SetRemapOption(pInfo,"event_key_remap"); + if (!InitKeyboardDeviceStruct(device, &rmlvo, NULL, EvdevKbdCtrl)) rc = !Success; @@ -1996,6 +2074,7 @@ EvdevProc(DeviceIntPtr device, int what) xf86IDrvMsg(pInfo, X_INFO, "Close\n"); EvdevCloseDevice(pInfo); EvdevFreeMasks(pEvdev); + freeRemap(pEvdev); pEvdev->min_maj = 0; break; diff --git a/src/evdev.h b/src/evdev.h index 2a010e6..f7c8d1e 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -152,6 +152,14 @@ typedef struct { } EventQueueRec, *EventQueuePtr; typedef struct { + uint8_t cd[256]; +} EvdevKeyRemapSlice; + +typedef struct { + EvdevKeyRemapSlice* sl[256]; +} EvdevKeyRemap, *EvdevKeyRemapPtr; + +typedef struct { struct libevdev *dev; char *device; @@ -239,6 +247,8 @@ typedef struct { unsigned char btnmap[32]; /* config-file specified button mapping */ + EvdevKeyRemapPtr keyremap; + 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; -- cgit v0.11.2