aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/Makefile.am4
-rw-r--r--man/evdev.man12
-rw-r--r--src/evdev.c84
-rw-r--r--src/evdev.h9
4 files changed, 108 insertions, 1 deletions
diff --git a/man/Makefile.am b/man/Makefile.am
index 66c207f..3e78cf5 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -36,12 +36,16 @@ SED = sed
XORGRELSTRING = @PACKAGE_STRING@
XORGMANNAME = X Version 11
+# should allow configure override like xserver's configure.ac does
+XKBPATH=${datadir}/X11/xkb
+
MAN_SUBSTS = \
-e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
-e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
-e 's|__xservername__|Xorg|g' \
-e 's|__xconfigfile__|xorg.conf|g' \
-e 's|__projectroot__|$(prefix)|g' \
+ -e 's|__xkb_path__|$(XKBPATH)|g' \
-e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \
-e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
-e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
diff --git a/man/evdev.man b/man/evdev.man
index 49ab12c..6da4bba 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -186,6 +186,18 @@ is mapped to the negative Y axis motion and button number
.I N2
is mapped to the positive Y axis motion. Default: "4 5". Property:
"Evdev Wheel Emulation Axes".
+.TP 7
+.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 "__xkb_path__/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 66b746a..7a9da6d 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -120,6 +120,46 @@ static Atom prop_axis_label = 0;
static Atom prop_btn_label = 0;
#endif
+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)xcalloc(1,sizeof(EvdevKeyRemap));
+ }
+ if (!ev->keyremap->sl[slice]) {
+ ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)xcalloc(1,sizeof(EvdevKeyRemapSlice));
+ }
+ 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;
+ xfree(ev->keyremap->sl[slice]);
+ }
+ xfree(ev->keyremap);
+ ev->keyremap=0;
+}
+
/* All devices the evdev driver has allocated and knows about.
* MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
* cannot be used by evdev, leaving us with a space of 2 at the end. */
@@ -267,6 +307,41 @@ SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
}
}
+static void
+SetRemapOption(InputInfoPtr pInfo,const char* name,EvdevPtr ev)
+{
+ char *s,*c;
+ unsigned long int code,value;
+ int consumed;
+
+ s = xf86SetStrOption(pInfo->options, name, NULL);
+ if (!s) return;
+ if (!s[0]) {
+ xfree(s);
+ return;
+ }
+
+ c=s;
+ while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) {
+ 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,code);
+ continue;
+ }
+ xf86Msg(X_INFO,"%s: remapping %ld into %ld.\n",pInfo->name,code,value);
+ addRemap(ev,code,value-MIN_KEYCODE);
+ c+=consumed;
+ }
+
+ if (*c!='\0') {
+ xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n",
+ pInfo->name, c);
+ }
+}
+
static int wheel_up_button = 4;
static int wheel_down_button = 5;
static int wheel_left_button = 6;
@@ -275,10 +350,14 @@ static int wheel_right_button = 7;
void
EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
{
- int code = ev->code + MIN_KEYCODE;
+ int code;
+ static char warned[KEY_CNT];
EventQueuePtr pQueue;
EvdevPtr pEvdev = pInfo->private;
+ ev->code=remapKey((EvdevPtr)(pInfo->private),ev->code);
+ code = ev->code + MIN_KEYCODE;
+
/* Filter all repeated events from device.
We'll do softrepeat in the server, but only since 1.6 */
if (value == 2
@@ -1129,6 +1208,8 @@ EvdevAddKeyClass(DeviceIntPtr device)
if (!pEvdev->rmlvo.options)
SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options);
+ SetRemapOption(pInfo,"event_key_remap",pEvdev);
+
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl))
return !Success;
@@ -1612,6 +1693,7 @@ EvdevProc(DeviceIntPtr device, int what)
pInfo->fd = -1;
}
EvdevRemoveDevice(pInfo);
+ freeRemap(pEvdev);
pEvdev->min_maj = 0;
break;
}
diff --git a/src/evdev.h b/src/evdev.h
index 1133985..a404c8f 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -114,6 +114,13 @@ typedef struct {
} EventQueueRec, *EventQueuePtr;
typedef struct {
+ uint8_t cd[256];
+} EvdevKeyRemapSlice;
+typedef struct {
+ EvdevKeyRemapSlice* sl[256];
+} EvdevKeyRemap, *EvdevKeyRemapPtr;
+
+typedef struct {
const char *device;
int grabDevice; /* grab the event device? */
@@ -173,6 +180,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;