AC_SYS_LARGEFILE
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_LIBTOOL
+AC_PROG_AWK
GTK_DOC_CHECK(1.10)
AC_PREFIX_DEFAULT([/usr])
AC_PATH_PROG([XSLTPROC], [xsltproc])
AS_HELP_STRING([--disable-extras], [disable extras with external dependencies]),
[], [enable_extras=yes])
if test "x$enable_extras" = xyes; then
+ AC_PATH_PROG([GPERF], [gperf])
+
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.7.0 gobject-2.0 >= 2.7.0])
AC_SUBST([GLIB_CFLAGS])
AC_SUBST([GLIB_LIBS])
extras/gudev/gudev-1.0.pc
extras/gudev/docs/Makefile
extras/gudev/docs/version.xml
+ extras/keymap/Makefile
])
AC_OUTPUT
pci.ids: ${PCI_DATABASE}
xsltproc: ${XSLTPROC}
+ gperf: ${GPERF}
])
udev-acl \
usb-db \
hid2hci \
+ keymap \
gudev
endif
--- /dev/null
+keymap
+keys-from-name.gperf
+keys-from-name.h
+keys-to-name.h
+keys.txt
+
--- /dev/null
+ACTION!="add", GOTO="keyboard_end"
+SUBSYSTEM!="input", GOTO="keyboard_end"
+KERNEL!="event*", GOTO="keyboard_end"
+
+ENV{DMI_VENDOR}="$attr{[dmi/id]sys_vendor}"
+ENV{DMI_VENDOR}=="", GOTO="keyboard_end"
+
+#
+# The following are exposed as separate input devices with low key codes, thus
+# we need to check their input device product name
+#
+
+ENV{DMI_VENDOR}=="IBM*", KERNELS=="input*", ATTRS{name}=="ThinkPad Extra Buttons", RUN+="keymap $name module-ibm"
+ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="ThinkPad Extra Buttons", RUN+="keymap $name module-lenovo"
+ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Asus Extra Buttons", ATTR{[dmi/id]product_name}=="W3J", RUN+="keymap $name module-asus-w3j"
+ENV{DMI_VENDOR}=="Sony*", KERNELS=="input*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony"
+
+# Older Vaios have some different keys
+ENV{DMI_VENDOR}=="Sony*", ATTR{[dmi/id]product_name}=="*PCG-C1*|*PCG-K25*|*PCG-F1*|*PCG-F2*|*PCG-F3*|*PCG-F4*|*PCG-F5*|*PCG-F6*|*PCG-FX*|*PCG-FRV*|*PCG-GR*|*PCG-TR*|*PCG-NV*|*PCG-Z*|*VGN-S360*|*VGN-SZ2HP_B*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony-old"
+
+#
+# The following rules belong to standard i8042 AT keyboard with high key codes.
+#
+
+DRIVERS=="atkbd", GOTO="keyboard_vendorcheck"
+GOTO="keyboard_end"
+
+LABEL="keyboard_vendorcheck"
+
+ENV{DMI_VENDOR}=="Dell*", RUN+="keymap $name dell"
+ENV{DMI_VENDOR}=="Compaq*", ATTR{[dmi/id]product_name}=="*E500*|*Evo N610c*|*Evo N600c*", RUN+="keymap $name compaq-e_evo"
+
+ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="*3000*", RUN+="keymap $name lenovo-3000"
+ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="ThinkPad X6*", ATTR{[dmi/id]product_version}=="* Tablet" RUN+="keymap $name lenovo-thinkpad_x6_tablet"
+ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="ThinkPad X200 Tablet*", ATTR{[dmi/id]product_version}=="* Tablet" RUN+="keymap $name lenovo-thinkpad_x200_tablet"
+
+ENV{DMI_VENDOR}=="Hewlett-Packard*", RUN+="keymap $name hewlett-packard"
+ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][aA][bB][lL][eE][tT]*", RUN+="keymap $name hewlett-packard-tablet"
+ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[pP][aA][vV][iI][lL][iI][oO][nN]*", RUN+="keymap $name hewlett-packard-pavilion"
+ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*Compaq*|*EliteBook*", RUN+="keymap $name hewlett-packard-compaq_elitebook"
+ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*2510p*|*2530p*", RUN+="keymap $name hewlett-packard-2510p_2530p"
+ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][xX]2*", RUN+="keymap $name hewlett-packard-tx2"
+
+ENV{DMI_VENDOR}=="Acer*", RUN+="keymap $name acer"
+ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Extensa*", ATTR{[dmi/id]product_name}=="*5210*|*5220*|*5610*|*5620*|*5720*", RUN+="keymap $name acer-extensa_5xxx"
+ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*C300*", RUN+="keymap $name acer-travelmate_c300"
+ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*6292*", RUN+="keymap $name acer-travelmate_6292"
+ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 5920G", RUN+="keymap $name acer-aspire_5920g"
+
+ENV{DMI_VENDOR}=="*BenQ*", ATTR{[dmi/id]product_name}=="*Joybook R22*", RUN+="keymap $name benq-joybook_r22"
+
+ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pro V3205*", RUN+="keymap $name fujitsu-amilo_pro_v3205"
+ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pa 2548*", RUN+="keymap $name fujitsu-amilo_pa_2548"
+ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*ESPRIMO Mobile V5*", RUN+="keymap $name fujitsu-esprimo_mobile_v5"
+ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*ESPRIMO Mobile V6*", RUN+="keymap $name fujitsu-esprimo_mobile_v6"
+ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pro Edition V3505*", RUN+="keymap $name fujitsu-amilo_pro_edition_v3505"
+ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*Amilo Si 1520*", RUN+="keymap $name fujitsu-amilo_si_1520"
+
+ENV{DMI_VENDOR}=="MEDION*", ATTR{[dmi/id]product_name}=="*FID2060*", RUN+="keymap $name medion-fid2060"
+ENV{DMI_VENDOR}=="MEDIONNB", ATTR{[dmi/id]product_name}=="A555*", RUN+="keymap $name medionnb-a555"
+
+ENV{DMI_VENDOR}=="MICRO-STAR*", RUN+="keymap $name micro-star"
+
+ENV{DMI_VENDOR}=="INVENTEC", ATTR{[dmi/id]product_name}=="SYMPHONY 6.0/7.0", RUN+="keymap $name inventec-symphony_6.0_7.0"
+
+ENV{DMI_VENDOR}=="MAXDATA", ATTR{[dmi/id]product_name}=="Pro 7000*", RUN+="keymap $name maxdata-pro_7000"
+
+ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*NC10*|*SP55S*|*SQ45S70S*|*SX60P*|*SX30S*|*R59P/R60P/R61P*|*Q210*|*Q310*|*X05*|*P560*|*R560*", RUN+="keymap $name samsung-other"
+ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*SX20S*", RUN+="keymap $name samsung-sx20s"
+ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="SQ1US", RUN+="keymap $name samsung-sq1us"
+
+ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="SATELLITE A100", RUN+="keymap $name toshiba-satellite_a100"
+ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite A110", RUN+="keymap $name toshiba-satellite_a110"
+
+ENV{DMI_VENDOR}=="OQO Inc.*", ATTR{[dmi/id]product_name}=="OQO Model 2*", RUN+="keymap $name oqo-model2"
+
+ENV{DMI_VENDOR}=="ASUS", RUN+="keymap $name asus"
+
+LABEL="keyboard_end"
--- /dev/null
+# keymap is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# keymap is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with keymap; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+include $(top_srcdir)/Makefile.am.inc
+
+# rules and keymaps
+dist_udevrules_DATA = 95-keymap.rules
+
+udevkeymapdir = $(libexecdir)/keymaps
+udevkeymap_DATA = \
+ keymaps/acer \
+ keymaps/acer-aspire_5920g \
+ keymaps/acer-extensa_5xxx \
+ keymaps/acer-travelmate_6292 \
+ keymaps/acer-travelmate_c300 \
+ keymaps/asus \
+ keymaps/benq-joybook_r22 \
+ keymaps/compaq-e_evo \
+ keymaps/dell \
+ keymaps/fujitsu-amilo_pa_2548 \
+ keymaps/fujitsu-amilo_pro_edition_v3505 \
+ keymaps/fujitsu-amilo_pro_v3205 \
+ keymaps/fujitsu-amilo_si_1520 \
+ keymaps/fujitsu-esprimo_mobile_v5 \
+ keymaps/fujitsu-esprimo_mobile_v6 \
+ keymaps/hewlett-packard \
+ keymaps/hewlett-packard-2510p_2530p \
+ keymaps/hewlett-packard-compaq_elitebook \
+ keymaps/hewlett-packard-pavilion \
+ keymaps/hewlett-packard-tablet \
+ keymaps/hewlett-packard-tx2 \
+ keymaps/inventec-symphony_6.0_7.0 \
+ keymaps/lenovo-3000 \
+ keymaps/lenovo-thinkpad_x6_tablet \
+ keymaps/lenovo-thinkpad_x200_tablet \
+ keymaps/maxdata-pro_7000 \
+ keymaps/medion-fid2060 \
+ keymaps/medionnb-a555 \
+ keymaps/micro-star \
+ keymaps/module-asus-w3j \
+ keymaps/module-ibm \
+ keymaps/module-lenovo \
+ keymaps/module-sony \
+ keymaps/module-sony-old \
+ keymaps/oqo-model2 \
+ keymaps/samsung-other \
+ keymaps/samsung-sq1us \
+ keymaps/samsung-sx20s \
+ keymaps/toshiba-satellite_a100 \
+ keymaps/toshiba-satellite_a110
+
+dist_pkgdata_SCRIPTS = findkeyboards
+
+# keymap program
+
+libexec_PROGRAMS = keymap
+
+keymap_SOURCES = keymap.c
+nodist_keymap_SOURCES = keys-from-name.h keys-to-name.h
+keymap_CPPFLAGS = $(AM_CPPFLAGS)
+
+dist_doc_DATA = README.keymap.txt
+
+EXTRA_DIST=keymaps check-keymaps.sh
+BUILT_SOURCES = keys-from-name.h keys-to-name.h
+CLEANFILES = keys.txt keys-from-name.gperf keys-from-name.h keys-to-name.h
+TESTS = check-keymaps.sh
+
+#
+# generation of keys-{from,to}-name.h from linux/input.h and gperf
+#
+
+keys.txt: /usr/include/linux/input.h
+ $(AWK) '/^#define.*KEY_/ { if ($$2 != "KEY_MAX" && $$2 != "KEY_CNT") { print $$2 } }' < $< > $@
+
+keys-from-name.gperf: keys.txt
+ $(AWK) 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print $$1 ", " $$1 }' < $< > $@
+
+keys-from-name.h: keys-from-name.gperf Makefile
+ $(GPERF) -t --ignore-case -N lookup_key -H hash_key_name -p -C < $< > $@
+
+keys-to-name.h: keys.txt Makefile
+ $(AWK) 'BEGIN{ print "const char* const key_names[KEY_CNT] = { "} { print "[" $$1 "] = \"" $$1 "\"," } END{print "};"}' < $< > $@
--- /dev/null
+= The udev keymap tool =
+
+== Introduction ==
+
+This udev extension configures computer model specific key mappings. This is
+particularly necessary for the non-standard extra keys found on many laptops,
+such as "brightness up", "next song", "www browser", or "suspend". Often these
+are accessed with the Fn key.
+
+Every key produces a "scan code", which is highly vendor/model specific for the
+nonstandard keys. This tool maintains mappings for these scan codes to standard
+"key codes", which denote the "meaning" of the key. The key codes are defined
+in /usr/include/linux/input.h.
+
+If some of your keys on your keyboard are not working at all, or produce the
+wrong effect, then a very likely cause of this is that the scan code -> key
+code mapping is incorrect on your computer.
+
+== Structure ==
+
+udev-keymap consists of the following parts:
+
+ keymaps/*:: mappings of scan codes to key code names
+
+ 95-keymap.rules:: udev rules for mapping system vendor/product names and
+ input module names to one of the keymaps above
+
+ keymap:: manipulate an evdev input device:
+ * write a key map file into a device (used by udev rules)
+ * dump current scan → key code mapping
+ * interactively display scan and key codes of pressed keys
+
+ findkeyboards:: display evdev input devices which belong to actual keyboards,
+ i. e. those suitable for the keymap program
+
+ fdi2rules.py:: convert hal keymap FDIs into udev rules and key map files
+ (Please note that this is far from perfect, since the mapping between fdi and
+ udev rules is not straightforward, and impossible in some cases.)
+
+== Fixing broken keys ==
+
+In order to make a broken key work on your system and send it back to upstream
+for inclusion you need to do the following steps:
+
+ 1. Find the keyboard device.
+
+ Run /usr/share/udev-extras/findkeyboards. This should always give you an "AT
+ keyboard" and possibly a "module". Some laptops (notably Thinkpads, Sonys, and
+ Acers) have multimedia/function keys on a separate input device instead of the
+ primary keyboard. The keyboard device should have a name like "input/event3".
+ In the following commands, the name will be written as "input/eventX".
+
+ 2. Dump current mapping:
+
+ sudo /lib/udev/keymap input/eventX > /tmp/orig-map.txt
+
+ 3. Find broken scan codes:
+
+ sudo /lib/udev/keymap -i input/eventX
+
+ Press all multimedia/function keys and check if the key name that gets printed
+ out is plausible. If it is unknown or wrong, write down the scan code (looks
+ like "0x1E") and the intended functionality of this key. Look in
+ /usr/include/linux/input.h for an available KEY_XXXXX constant which most
+ closely approximates this functionality and write it down as the new key code.
+
+ For example, you might press a key labeled "web browser" which currently
+ produces "unknown". Note down this:
+
+ 0x1E www # Fn+F2 web browser
+
+ Repeat that for all other keys. Write the resulting list into a file. Look at
+ /lib/udev/keymaps/ for existing key map files and make sure that you use the
+ same structure.
+
+ 4. Find out your system vendor and product:
+
+ cat /sys/class/dmi/id/sys_vendor
+ cat /sys/class/dmi/id/product_name
+
+ 5. Generate a device dump with "udevadm info --export-db > /tmp/udev-db.txt".
+
+ 6. Send the system vendor/product names, the key mapping from step 3,
+ /tmp/orig-map.txt from step 2, and /tmp/udev-db.txt from step 5
+ to the bug tracker, so that they can be included in the next release:
+
+ https://bugs.launchpad.net/udev-extras/+bugs
+
+For local testing, copy your map file to /lib/udev/keymaps/ with an appropriate
+name, and add an appropriate udev rule to /lib/udev/rules.d/95-keymap.rules:
+
+ * If you selected an "AT keyboard", add the rule to the section after
+ 'LABEL="keyboard_vendorcheck"'.
+
+ * If you selected a "module", add the rule to the top section where the
+ "ThinkPad Extra Buttons" are.
+
+== Author ==
+
+keymap is written and maintained by Martin Pitt <martin.pitt@ubuntu.com>.
--- /dev/null
+#!/bin/bash
+
+# check that all key names in keymaps/* are known in <linux/input.h>
+KEYLIST=./keys.txt
+RULES=95-keymap.rules
+
+[ -e "$KEYLIST" ] || {
+ echo "need $KEYLIST please build first" >&2
+ exit 1
+}
+
+missing=$(join -v 2 <(awk '{print tolower(substr($1,5))}' $KEYLIST | sort -u) <(awk '{print $2}' keymaps/*|sort -u))
+[ -z "$missing" ] || {
+ echo "ERROR: unknown key names in keymaps/*:" >&2
+ echo "$missing" >&2
+ exit 1
+}
+
+# check that all maps referred to in $RULES exist
+maps=$(sed -rn '/keymap \$name/ { s/^.*\$name ([^"]+).*$/\1/; p }' $RULES)
+for m in $maps; do
+ [ -e keymaps/$m ] || {
+ echo "ERROR: unknown map name in $RULES: $m" >&2
+ exit 1
+ }
+ grep -q "keymaps/$m\>" Makefile.am || {
+ echo "ERROR: map file $m is not added to Makefile.am" >&2
+ exit 1
+ }
+done
--- /dev/null
+#!/bin/sh -e
+# Find "real" keyboard devices and print their device path.
+# Author: Martin Pitt <martin.pitt@ubuntu.com>
+#
+# Copyright (C) 2009, Canonical Ltd.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+
+
+# print a list of input devices which are keyboard-like
+keyboard_devices() {
+ input_devs=`udevadm trigger --dry-run --verbose --subsystem-match=input --attr-match=dev`
+
+ # standard AT keyboard
+ for dev in $input_devs; do
+ info=`udevadm info --attribute-walk --path=$dev`
+
+ if echo "$info" | grep -q 'DRIVERS=="atkbd"'; then
+ echo -n 'AT keyboard: '
+ udevadm info --query=name --path=$dev
+ fi
+ done
+
+ # modules
+ module=`udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='*Extra Buttons'`
+ module="$module
+`udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='Sony Vaio Keys'`"
+ for m in $module; do
+ evdev=`ls -d $m/event* 2>/dev/null`
+ if [ -e "$evdev/dev" ]; then
+ echo -n 'module: '
+ udevadm info --query=name --path=$evdev
+ fi
+ done
+}
+
+keyboard_devices
--- /dev/null
+/*
+ * keymap - dump keymap of an evdev device or set a new keymap from a file
+ *
+ * Based on keyfuzz by Lennart Poettering <mzqrovna@0pointer.net>
+ * Adapted for udev-extras by Martin Pitt <martin.pitt@ubuntu.com>
+ *
+ * Copyright (C) 2006, Lennart Poettering
+ * Copyright (C) 2009, Canonical Ltd.
+ *
+ * keymap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * keymap is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with keymap; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <linux/input.h>
+
+const struct key* lookup_key (const char *str, unsigned int len);
+
+#include "keys-from-name.h"
+#include "keys-to-name.h"
+
+#define MAX_SCANCODES 1024
+
+/* If keymap file is given without a path, assume this one; must end with '/' * */
+#define DEFAULT_PATH "/lib/udev/keymaps/"
+
+static int evdev_open(const char *dev)
+{
+ int fd;
+ char fn[PATH_MAX];
+
+ if (strncmp(dev, "/dev", 4) != 0) {
+ snprintf(fn, sizeof(fn), "/dev/%s", dev);
+ dev = fn;
+ }
+
+ if ((fd = open(dev, O_RDWR)) < 0) {
+ fprintf(stderr, "error open('%s'): %m\n", dev);
+ return -1;
+ }
+ return fd;
+}
+
+static int evdev_get_keycode(int fd, int scancode, int e)
+{
+ int codes[2];
+
+ codes[0] = scancode;
+ if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) {
+ if (e && errno == EINVAL) {
+ return -2;
+ } else {
+ fprintf(stderr, "EVIOCGKEYCODE: %m\n");
+ return -1;
+ }
+ }
+ return codes[1];
+}
+
+static int evdev_set_keycode(int fd, int scancode, int keycode)
+{
+ int codes[2];
+
+ codes[0] = scancode;
+ codes[1] = keycode;
+
+ if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) {
+ fprintf(stderr, "EVIOCSKEYCODE: %m\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int evdev_driver_version(int fd, char *v, size_t l)
+{
+ int version;
+
+ if (ioctl(fd, EVIOCGVERSION, &version)) {
+ fprintf(stderr, "EVIOCGVERSION: %m\n");
+ return -1;
+ }
+
+ snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff);
+ return 0;
+}
+
+static int evdev_device_name(int fd, char *n, size_t l)
+{
+ if (ioctl(fd, EVIOCGNAME(l), n) < 0) {
+ fprintf(stderr, "EVIOCGNAME: %m\n");
+ return -1;
+ }
+ return 0;
+}
+
+/* Return a lower-case string with KEY_ prefix removed */
+static const char* format_keyname(const char* key) {
+ static char result[101];
+ const char* s;
+ int len;
+
+ for (s = key+4, len = 0; *s && len < 100; ++len, ++s)
+ result[len] = tolower(*s);
+ result[len] = '\0';
+ return result;
+}
+
+static int dump_table(int fd) {
+ char version[256], name[256];
+ int scancode, r = -1;
+
+ if (evdev_driver_version(fd, version, sizeof(version)) < 0)
+ goto fail;
+
+ if (evdev_device_name(fd, name, sizeof(name)) < 0)
+ goto fail;
+
+ printf("### evdev %s, driver '%s'\n", version, name);
+
+ r = 0;
+ for (scancode = 0; scancode < MAX_SCANCODES; scancode++) {
+ int keycode;
+
+ if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) {
+ if (keycode != -2)
+ r = -1;
+ break;
+ }
+
+ if (keycode < KEY_MAX && key_names[keycode])
+ printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode]));
+ else
+ printf("0x%03x 0x%03x\n", scancode, keycode);
+ }
+fail:
+ return r;
+}
+
+static int merge_table(int fd, const char *filename) {
+ int r = 0;
+ int line = 0;
+ FILE* f;
+
+ f = fopen(filename, "r");
+ if (!f) {
+ perror(filename);
+ r = -1;
+ goto fail;
+ }
+
+ while (!feof(f)) {
+ char s[256], *p;
+ int scancode, new_keycode, old_keycode;
+
+ if (!fgets(s, sizeof(s), f))
+ break;
+
+ line++;
+ p = s+strspn(s, "\t ");
+ if (*p == '#' || *p == '\n')
+ continue;
+
+ if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) {
+ char t[105] = "KEY_UNKNOWN";
+ const struct key *k;
+
+ if (sscanf(p, "%i %100s", &scancode, t+4) != 2) {
+ fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line);
+ r = -1;
+ continue;
+ }
+
+ if (!(k = lookup_key(t, strlen(t)))) {
+ fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line);
+ r = -1;
+ continue;
+ }
+
+ new_keycode = k->id;
+ }
+
+
+ if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) {
+ r = -1;
+ goto fail;
+ }
+
+ if (evdev_set_keycode(fd, scancode, new_keycode) < 0) {
+ r = -1;
+ goto fail;
+ }
+
+ if (new_keycode != old_keycode)
+ fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n",
+ scancode, new_keycode, old_keycode);
+ }
+fail:
+ return r;
+}
+
+static const char* default_keymap_path(const char* path)
+{
+ static char result[PATH_MAX];
+
+ if (!strchr(path, '/')) {
+ snprintf(result, sizeof(result), "%s%s", DEFAULT_PATH, path);
+ return result;
+ }
+ return path;
+}
+
+static void print_key(struct input_event *event)
+{
+ static int cur_scancode = 0;
+
+ /* save scan code for next EV_KEY event */
+ if (event->type == EV_MSC && event->code == MSC_SCAN)
+ cur_scancode = event->value;
+
+ /* key press */
+ if (event->type == EV_KEY && event->value)
+ printf("scan code: 0x%02X key code: %s\n", cur_scancode,
+ format_keyname(key_names[event->code]));
+}
+
+static void interactive(int fd)
+{
+ struct input_event ev;
+ int run = 1;
+
+ /* grab input device */
+ ioctl(fd, EVIOCGRAB, 1);
+
+ puts("Press ESC to finish");
+ while (run) {
+ switch (read(fd, &ev, sizeof(ev))) {
+ case -1:
+ perror("read");
+ run = 0;
+ break;
+ case 0:
+ run = 0;
+ break;
+ default:
+ print_key(&ev);
+ /* stop on Escape key release */
+ if (ev.type == EV_KEY && ev.code == KEY_ESC && ev.value == 0)
+ run = 0;
+ break;
+ }
+ }
+
+ /* release input device */
+ ioctl(fd, EVIOCGRAB, 0);
+}
+
+int main(int argc, char **argv)
+{
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "interactive", no_argument, NULL, 'i' },
+ {}
+ };
+ int fd = -1;
+ int opt_interactive = 0;
+
+ while (1) {
+ int option;
+
+ option = getopt_long(argc, argv, "hi", options, NULL);
+ if (option == -1)
+ break;
+
+ switch (option) {
+ case 'h':
+ printf("Usage: keymap <event device> [<map file>]\n\n");
+ return 0;
+
+ case 'i':
+ opt_interactive = 1;
+ break;
+ default:
+ return 1;
+ }
+ }
+
+ if (argc < optind+1 || argc > optind+2) {
+ fprintf(stderr, "Usage: keymap <event device> [<map file>]\n\n");
+ return 2;
+ }
+
+ if ((fd = evdev_open(argv[optind])) < 0)
+ return 3;
+
+ if (argc == optind+2)
+ merge_table(fd, default_keymap_path(argv[optind+1]));
+ else {
+ if (opt_interactive)
+ interactive(fd);
+ else
+ dump_table(fd);
+ }
+ return 0;
+}
--- /dev/null
+0xA5 help # Fn+F1
+0xA6 setup # Fn+F2 Acer eSettings
+0xA7 battery # Fn+F3 Power Management
+0xA9 switchvideomode # Fn+F5
+0xB3 euro
+0xB4 dollar
+0xCE brightnessup # Fn+Right
+0xD4 bluetooth # (toggle) off-to-on
+0xD5 wlan # (toggle) on-to-off
+0xD6 wlan # (toggle) off-to-on
+0xD7 bluetooth # (toggle) on-to-off
+0xD8 bluetooth # (toggle) off-to-on
+0xD9 brightnessup # Fn+Right
+0xEE brightnessup # Fn+Right
+0xEF brightnessdown # Fn+Left
+0xF1 f22 # Fn+F7 Touchpad toggle (off-to-on)
+0xF2 f22 # Fn+F7 Touchpad toggle (on-to-off)
+0xF3 prog2 # "P2" programmable button
+0xF4 prog1 # "P1" programmable button
+0xF5 presentation
+0xF8 fn
+0xF9 f23 # Launch NTI shadow
--- /dev/null
+0x8A media
+0xB2 www
+0x92 prog2
+0xD9 bluetooth # (toggle) on-to-off
--- /dev/null
+0xEE screenlock # Windows Lock function
--- /dev/null
+0xD9 bluetooth # (toggle) on-to-off
--- /dev/null
+0x67 f24 # FIXME: rotate screen
+0x68 up
+0x69 down
+0x6B fn
+0x6C screenlock # FIXME: lock tablet device/buttons
--- /dev/null
+0xED volumeup
+0xEE volumedown
+0xEF mute
--- /dev/null
+0x6E wlan # Fn+F1
--- /dev/null
+0xA3 www # I key
+0x9A search
+0x9E email
+0x9F homepage
--- /dev/null
+0x81 playpause # Play/Pause
+0x82 stopcd # Stop
+0x83 previoussong # Previous song
+0x84 nextsong # Next song
+0x85 brightnessdown # Fn+Down arrow Brightness Down
+0x86 brightnessup # Fn+Up arrow Brightness Up
+0x87 battery # Fn+F3 battery icon
+0x88 wlan # Fn+F2 Turn On/Off Wireless
+0x89 ejectclosecd # Fn+F10 Eject CD
+0x8A suspend # Fn+F1 hibernate
+0x8B switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle")
+0x8C f23 # Fn+Right arrow Auto Brightness
+0x8F switchvideomode # Fn+F7 aspect ratio
+0x90 previoussong # Front panel previous song
+0x91 prog1 # Wifi Catcher (DELL Specific)
+0x92 media # MediaDirect button (house icon)
+0x93 f23 # FIXME Fn+Left arrow Auto Brightness
+0x95 camera # Shutter button Takes a picture if optional camera available
+0x97 email # Tablet email button
+0x98 f21 # FIXME: Tablet screen rotatation
+0x99 nextsong # Front panel next song
+0x9A setup # Tablet tools button
+0x9B switchvideomode # Display Toggle button
+0xA2 playpause # Front panel play/pause
+0xA4 stopcd # Front panel stop
+0xD8 screenlock # FIXME: Tablet lock button
+0xED media # MediaDirect button
--- /dev/null
+0xE0 volumedown
+0xE1 volumeup
+0xE5 prog1
--- /dev/null
+0xA5 help # Fn-F1
+0xA9 switchvideomode # Fn-F3
+0xD9 brightnessdown # Fn-F8
+0xE0 brightnessup # Fn-F9
--- /dev/null
+0xF4 f21 # FIXME: silent-mode decrease CPU/GPU clock
+0xF7 switchvideomode # Fn+F3
--- /dev/null
+0xE1 wlan
+0xF3 wlan
+0xEE brightnessdown
+0xE0 brightnessup
+0xE2 bluetooth
+0xF7 video
--- /dev/null
+0xA9 switchvideomode
+0xD9 brightnessdown
+0xDF sleep
+0xEF brightnessup
--- /dev/null
+0xCE brightnessup
+0xEF brightnessdown
--- /dev/null
+0x81 fn_esc
+0x89 battery # FnF8
+0x8A screenlock # FnF6
+0x8B camera
+0x8C media # music
+0x8E dvd
+0xB1 help
+0xB3 f23 # FIXME: Auto brightness
+0xD7 wlan
+0x92 brightnessdown # FnF7 (FnF9 on 6730b)
+0x97 brightnessup # FnF8 (FnF10 on 6730b)
+0xEE switchvideomode # FnF4
--- /dev/null
+0xD8 f22 # touchpad off
+0xD9 f23 # touchpad on
--- /dev/null
+0x88 presentation
+0xD9 help # I key (high keycode: "info")
--- /dev/null
+0x88 media # FIXME: quick play
+0xD8 f22 # touchpad off
+0xD9 f23 # touchpad on
--- /dev/null
+0x82 prog2 # Funny Key
+0x83 prog1 # Q
+0x84 tab
+0x85 esc
+0x86 pageup
+0x87 pagedown
--- /dev/null
+0xC2 media
+0xD8 f22 # Toggle touchpad button on tx2 (OFF)
+0xD9 f22 # Toggle touchpad button on tx2 (ON)
--- /dev/null
+0xF3 prog2
+0xF4 prog1
--- /dev/null
+0x8B switchvideomode # Fn+F7 video
+0x96 wlan # Fn+F5 wireless
+0x97 sleep # Fn+F4 suspend
+0x98 suspend # Fn+F12 hibernate
+0xB4 prog1 # Lenovo Care
--- /dev/null
+0x5D menu
+0x63 fn
+0x66 screenlock
+0x67 cyclewindows # bezel circular arrow
+0x68 setup # bezel setup / menu
+0x6c direction # rotate screen
--- /dev/null
+0x6C f21 # rotate
+0x68 screenlock # screenlock
+0x6B esc # escape
+0x6D right # right on d-pad
+0x6E left # left on d-pad
+0x71 up # up on d-pad
+0x6F down # down on d-pad
+0x69 enter # enter on d-pad
--- /dev/null
+0x97 prog2
+0x9F prog1
+0xA0 mute # Fn-F5
+0x82 www
+0xEC email
+0xAE volumedown # Fn-Down
+0xB0 volumeup # Fn-Up
+0xDF suspend # Fn+F2
+0xF5 help
--- /dev/null
+0x6B channeldown # Thottle Down
+0x6D channelup # Thottle Up
--- /dev/null
+0x63 www # N button
+0x66 prog1 # link 1 button
+0x67 email # envelope button
+0x69 prog2 # link 2 button
--- /dev/null
+0xA0 mute # Fn-F9
+0xAE volumedown # Fn-F7
+0xB0 volumeup # Fn-F8
+0xB2 www # e button
+0xDF sleep # Fn-F12
+0xE2 bluetooth # satellite dish2
+0xE4 f22 # Fn-F3 Touchpad disable
+0xEC email # envelope button
+0xF6 wlan # satellite dish1
+0xF7 brightnessdown # Fn-F4
+0xF8 brightnessup # Fn-F5
+0xF9 search
--- /dev/null
+0x41 nextsong
+0x45 playpause
+0x43 stopcd
+0x40 previoussong
+0x4C ejectclosecd
+0x32 mute
+0x31 volumedown
+0x30 volumeup
+0x5D wlan
+0x7E bluetooth
+0x8A media # high keycode: "tv"
--- /dev/null
+0x01 battery # Fn+F2
+0x02 screenlock # Fn+F3
+0x03 sleep # Fn+F4
+0x04 radio # Fn+F5
+0x06 switchvideomode # Fn+F7
+0x07 zoom # Fn+F8 screen expand
+0x08 f24 # Fn+F9 undock
+0x0B suspend # Fn+F12
+0x0F brightnessup # Fn+Home
+0x10 brightnessdown # Fn+End
+0x11 kbdillumtoggle # Fn+PgUp - ThinkLight
+0x13 zoom # Fn+Space
+0x14 volumeup
+0x15 volumedown
+0x16 mute
+0x17 prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor")
--- /dev/null
+0x1 screenlock # Fn+F2
+0x2 battery # Fn+F3
+0x3 sleep # Fn+F4
+0x4 radio # Fn+F5
+0x6 switchvideomode # Fn+F7
+0x7 f22 # Fn+F8 touchpadtoggle
+0x8 f24 # Fn+F9 undock
+0xB suspend # Fn+F12
+0xF brightnessup # Fn+Home
+0x10 brightnessdown # Fn+End
+0x11 kbdillumtoggle # Fn+PgUp - ThinkLight
+0x13 zoom # Fn+Space
+0x14 volumeup
+0x15 volumedown
+0x16 mute
+0x17 prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor")
--- /dev/null
+0x06 mute # Fn+F2
+0x07 volumedown # Fn+F3
+0x08 volumeup # Fn+F4
+0x09 brightnessdown # Fn+F5
+0x0A brightnessup # Fn+F6
+0x0B switchvideomode # Fn+F7
+0x0E zoom # Fn+F10
+0x10 suspend # Fn+F12
--- /dev/null
+0x06 battery
+0x07 mute
--- /dev/null
+0x8E wlan
+0xF0 switchvideomode
+0xF1 mute
+0xF2 volumedown
+0xF3 volumeup
--- /dev/null
+0x74 prog1 # User key
+0x75 www
+0x78 mail
+0x82 switchvideomode # Fn+F4 CRT/LCD (high keycode: "displaytoggle")
+0x83 battery # Fn+F2
+0x84 prog1 # Fn+F5 backlight on/off
+0x86 wlan # Fn+F9
+0x88 brightnessup # Fn-Up
+0x89 brightnessdown # Fn-Down
+0xB1 prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice)
+0xB3 prog3 # Fn+F8 switch power mode (battery/dynamic/performance)
+0xB4 wlan # Fn+F9 (X60P)
+0xF7 f22 # Fn+F10 Touchpad on
+0xF9 f22 # Fn+F10 Touchpad off
--- /dev/null
+0xD4 menu
+0xD8 f1
+0xD9 f10
+0xD6 f3
+0xD7 f9
+0xE4 f5
+0xEE f11
--- /dev/null
+0x74 mute
+0x75 mute
+0x77 f21 # FIXME: Touchpad on
+0x79 f21 # FIXME: Touchpad off
--- /dev/null
+0xA4 stopcd
+0xB2 www
--- /dev/null
+0x92 stop
+0x93 www
+0x94 media
+0x9E f21 # FIXME: Touchpad on
+0x9F f21 # FIXME: Touchpad off
+0xB9 nextsong
+0xD9 brightnessup
+0xEE screenlock
+0xF4 previoussong
+0xF7 playpause