Re: 2.6.36/2.6.37: broken compatibility with userspace input-utils ?
From: Mauro Carvalho Chehab <hidden>
Date: 2011-01-26 14:19:11
Also in:
linux-media, lkml
Subsystem:
the rest · Maintainer:
Linus Torvalds
Em 26-01-2011 11:08, Gerd Hoffmann escreveu:
Hi,quoted
Btw, I took some time to take analyse the input-kbd stuff. As said at the README: This is a small collection of input layer utilities. I wrote them mainly for testing and debugging, but maybe others find them useful too :-) ... Gerd Knorr[off-list ref] [SUSE Labs] This is an old testing tool written by Gerd Hoffmann probably used for him to test the V4L early Remote Controller implementations.Indeed.quoted
The last "official" version seems to be this one: http://dl.bytesex.org/cvs-snapshots/input-20081014-101501.tar.gzJust moved the bits to git a few days ago. http://bigendian.kraxel.org/cgit/input/ Code is unchanged since 2008 though.quoted
Gerd, if you're still maintaining it, it is a good idea to apply Dmitry's patch: http://www.spinics.net/lists/linux-input/msg13728.htmlHmm, doesn't apply cleanly ...
I suspect that Dmitry did the patch against the Debian package, based on a 2007 version of it, as it seems that Debian is using an older version of the package. Anyway, I've ported his patch to be applied over your -git tree, and tested on it, with vanilla 2.6.37. That's the incorrect output result of the old version, with an existing NEC extended map: $ sudo /tmp/input/input-kbd 2 /dev/input/event2 bustype : BUS_I2C vendor : 0x0 product : 0x0 version : 0 name : "i2c IR (i2c IR (EM2820 Winfast " phys : "i2c-0/0-0030/ir0" bits ev : EV_SYN EV_KEY EV_MSC EV_REP bits: KEY_1 bits: KEY_2 bits: KEY_3 bits: KEY_4 ... And that's the output after applying the patch: $ sudo ./input-kbd 2 /dev/input/event2 bustype : BUS_I2C vendor : 0x0 product : 0x0 version : 0 name : "i2c IR (i2c IR (EM2820 Winfast " phys : "i2c-0/0-0030/ir0" bits ev : EV_SYN EV_KEY EV_MSC EV_REP map: 31 keys, size: 31/64 0x866b00 = 393 # KEY_VIDEO 0x866b01 = 2 # KEY_1 0x866b02 = 11 # KEY_0 0x866b03 = 386 # KEY_TUNER - [PATCH] input-kbd - switch to using EVIOCGKEYCODE2 when available From: Dmitry Torokhov <dmitry.torokhov@gmail.com> [mchehab@redhat.com: Ported it to the -git version] Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Mauro Carvalho Chehab <redacted>
diff --git a/input-kbd.c b/input-kbd.c
index c432d0d..aaf23b9 100644
--- a/input-kbd.c
+++ b/input-kbd.c@@ -9,9 +9,22 @@ #include "input.h" +struct input_keymap_entry_v2 { +#define KEYMAP_BY_INDEX (1 << 0) + uint8_t flags; + uint8_t len; + uint16_t index; + uint32_t keycode; + uint8_t scancode[32]; +}; + +#ifndef EVIOCGKEYCODE_V2 +#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry_v2) +#endif + struct kbd_entry { - int scancode; - int keycode; + unsigned int scancode; + unsigned int keycode; }; struct kbd_map {
@@ -23,7 +36,7 @@ struct kbd_map { /* ------------------------------------------------------------------ */ -static struct kbd_map* kbd_map_read(int fd) +static struct kbd_map* kbd_map_read(int fd, unsigned int version) { struct kbd_entry entry; struct kbd_map *map;
@@ -32,17 +45,35 @@ static struct kbd_map* kbd_map_read(int fd) map = malloc(sizeof(*map)); memset(map,0,sizeof(*map)); for (map->size = 0; map->size < 65536; map->size++) { - entry.scancode = map->size; - entry.keycode = KEY_RESERVED; - rc = ioctl(fd, EVIOCGKEYCODE, &entry); - if (rc < 0) { - map->size--; - break; + if (version < 0x10001) { + entry.scancode = map->size; + entry.keycode = KEY_RESERVED; + rc = ioctl(fd, EVIOCGKEYCODE, &entry); + if (rc < 0) { + map->size--; + break; + } + } else { + struct input_keymap_entry_v2 ke = { + .index = map->size, + .flags = KEYMAP_BY_INDEX, + .len = sizeof(uint32_t), + .keycode = KEY_RESERVED, + }; + + rc = ioctl(fd, EVIOCGKEYCODE_V2, &ke); + if (rc < 0) + break; + memcpy(&entry.scancode, ke.scancode, + sizeof(entry.scancode)); + entry.keycode = ke.keycode; } + if (map->size >= map->alloc) { map->alloc += 64; map->map = realloc(map->map, map->alloc * sizeof(entry)); } + map->map[map->size] = entry; if (KEY_RESERVED != entry.keycode)
@@ -156,37 +187,25 @@ static void kbd_print_bits(int fd) } } -static void show_kbd(int nr) +static void show_kbd(int fd, unsigned int protocol_version) { struct kbd_map *map; - int fd; - fd = device_open(nr,1); - if (-1 == fd) - return; device_info(fd); - map = kbd_map_read(fd); - if (NULL != map) { - kbd_map_print(stdout,map,0); - } else { + map = kbd_map_read(fd, protocol_version); + if (map) + kbd_map_print(stdout, map, 0); + else kbd_print_bits(fd); - } - - close(fd); } -static int set_kbd(int nr, char *mapfile) +static int set_kbd(int fd, unsigned int protocol_version, char *mapfile) { struct kbd_map *map; FILE *fp; - int fd; - fd = device_open(nr,1); - if (-1 == fd) - return -1; - - map = kbd_map_read(fd); + map = kbd_map_read(fd, protocol_version); if (NULL == map) { fprintf(stderr,"device has no map\n"); close(fd);
@@ -203,14 +222,12 @@ static int set_kbd(int nr, char *mapfile) return -1; } } - + if (0 != kbd_map_parse(fp,map) || 0 != kbd_map_write(fd,map)) { - close(fd); return -1; } - close(fd); return 0; }
@@ -224,8 +241,10 @@ static int usage(char *prog, int error) int main(int argc, char *argv[]) { - int c,devnr; + int c, devnr, fd; char *mapfile = NULL; + unsigned int protocol_version; + int rc = EXIT_FAILURE; for (;;) { if (-1 == (c = getopt(argc, argv, "hf:")))
@@ -245,12 +264,29 @@ int main(int argc, char *argv[]) usage(argv[0],1); devnr = atoi(argv[optind]); - if (mapfile) { - set_kbd(devnr,mapfile); - } else { - show_kbd(devnr); + + fd = device_open(devnr, 1); + if (fd < 0) + goto out; + + if (ioctl(fd, EVIOCGVERSION, &protocol_version) < 0) { + fprintf(stderr, + "Unable to query evdev protocol version: %s\n", + strerror(errno)); + goto out_close; } - return 0; + + if (mapfile) + set_kbd(fd, protocol_version, mapfile); + else + show_kbd(fd, protocol_version); + + rc = EXIT_SUCCESS; + +out_close: + close(fd); +out: + return rc; } /* ---------------------------------------------------------------------
diff --git a/input.c b/input.c
index d57a31e..a9bd5e8 100644
--- a/input.c
+++ b/input.c@@ -101,8 +101,8 @@ int device_open(int nr, int verbose) close(fd); return -1; } - if (EV_VERSION != version) { - fprintf(stderr, "protocol version mismatch (expected %d, got %d)\n", + if (EV_VERSION > version) { + fprintf(stderr, "protocol version mismatch (expected >= %d, got %d)\n", EV_VERSION, version); close(fd); return -1;