Thread (94 messages) 94 messages, 6 authors, 2011-02-02

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.gz
Just 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.html
Hmm, 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;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help