summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packaging/xf86-input-evdev.spec1
-rw-r--r--src/evdev.c91
-rw-r--r--src/evdev.h13
3 files changed, 105 insertions, 0 deletions
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;