Skip to content

Instantly share code, notes, and snippets.

@tristan
Last active August 29, 2015 14:05
Show Gist options
  • Save tristan/58c041eb4588b5c54ccd to your computer and use it in GitHub Desktop.
Save tristan/58c041eb4588b5c54ccd to your computer and use it in GitHub Desktop.
xf86-input-evdev-remap patch for 2.9.2
Section "InputClass"
Identifier "evdev keyboard catchall"
MatchIsKeyboard "on"
MatchDevicePath "/dev/input/event*"
MatchProduct "BD Remote Control"
Driver "evdev"
Option "event_key_remap" "119=65 159=41 161=39 207=33 256=53 311=86 313=82 315=33 357=54 371=52 358=31 401=25 407=37 412=34 436=59 437=60 438=54"
EndSection
diff --git a/man/evdev.man b/man/evdev.man
index 06613fc..53fcb3f 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -226,6 +226,17 @@ Specify the X Input 1.x type (see XListInputDevices(__libmansuffix__)).
There is rarely a need to use this option, evdev will guess the device type
based on the device's capabilities. This option is provided for devices that
need quirks.
+.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).
.TP 7
.BI "Option \*qVertScrollDelta\*q \*q" integer \*q
The amount of motion considered one unit of scrolling vertically.
diff --git a/src/evdev.c b/src/evdev.c
index 7aecf36..3aeead4 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -141,6 +141,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;
@@ -267,6 +307,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)
{
@@ -285,7 +361,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.
@@ -1179,6 +1255,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;
@@ -2003,6 +2081,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 2d6b62d..bc9cc39 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -152,6 +152,13 @@ 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 +246,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;
_pkgname=xf86-input-evdev
pkgname=${_pkgname}-remap
pkgver=2.9.2
pkgrel=1
pkgdesc="X.org evdev input driver"
arch=(i686 x86_64)
url="http://xorg.freedesktop.org/"
license=('custom')
depends=('glibc' 'systemd' 'mtdev' 'libevdev')
makedepends=('xorg-server-devel' 'resourceproto' 'scrnsaverproto')
provides=('xf86-input-evdev')
conflicts=('xorg-server<1.16.0' 'xf86-input-evdev' 'X-ABI-XINPUT_VERSION<21' 'X-ABI-XINPUT_VERSION>=22')
options=('!makeflags')
groups=('xorg-drivers' 'xorg')
source=(${url}/releases/individual/driver/${_pkgname}-${pkgver}.tar.bz2
evdev-remap.patch)
sha256sums=('792329b531afc6928ccda94e4b51a5520d4ddf8ef9a00890a5d0d31898acefec'
'030e682fac851b15d990d506b6b4918d13b71c2205472412877080d9c899ca81')
prepare () {
cd "$srcdir/${_pkgname}-${pkgver}"
patch -Np1 -i "$srcdir/evdev-remap.patch"
}
build() {
cd ${_pkgname}-${pkgver}
./configure --prefix=/usr
make
}
package() {
cd ${_pkgname}-${pkgver}
make DESTDIR="${pkgdir}" install
install -m755 -d "${pkgdir}/usr/share/licenses/${_pkgname}"
install -m644 COPYING "${pkgdir}/usr/share/licenses/${_pkgname}/"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment