Bug#562052: Correctly identify touchpads

Dmitry Torokhov dmitry.torokhov at gmail.com
Mon Jan 4 01:18:43 PST 2010


On Wed, Dec 30, 2009 at 01:23:07PM +0100, Martin Pitt wrote:
> Michael Tokarev [2009-12-30 14:01 +0300]:
> > in both cases userspace is 32bit, but kernel bitness is different:
> 
> Ah, thanks.
> 
> > Udev merely collects text attributes from sysfs, 
> 
> No, it also stores properties set in udev rules. I was particularly
> interested in the ID_INPUT_* properties set by
> /lib/udev/rules.d/60-persistent-input.rules, but they are not in your
> dump.
> 
> > This is exactly what happens, to me and to the original bug reporter --
> > we both are running 32bit userspace and 64bit kernel.
> 
> OK, thanks. Then it's quite clear why this happens.
> 
> > > So if we want to support mixed kernel/userspace word lenghts, we need
> > > to change the logic to do a dynamic word size detection based on
> > > uname().
> > 
> > Not uname please.  There should be a better way :)
> 
> I don't like it either, since you have to compare with a lot of fixed
> strings, for each supported architecture. Do you know a better way of
> asking the kernel for its word size?
> 
> > For example, see the number of words shown in "key" attribute:
> > for 32bits it's two times of 64bits...
> 
> Not really. The attribute has as many words as necessary for the
> highest bit set. E. g. many input devices have a single "0" there.
> Check "cat /sys/class/input*/capabilities/key".
> 
> If the kernel would have an architecture independent representation of
> those bits in the sys attribute, that would help a lot indeed. Right
> now, I don't think we can sanely support mixed kernel/userspace
> architectures.
> 

Does the following patch fixes it for you guys?

Thanks.

-- 
Dmitry


Input: add compat support for sysfs and /proc capabilities output

From: Dmitry Torokhov <dmitry.torokhov at gmail.com>

Input core displays capabilities bitmasks in form of one or more longs printed
in hex form and separated by spaces. Unfortunately it does not work well
for 32-bit applications running on 64-bit kernels since applications expect
that number is "worth" only 32 bits when kernel advances by 64 bits.

Fix that by ensuring that output produced for compat tasks uses 32-bit units.

Signed-off-by: Dmitry Torokhov <dtor at mail.ru>
---

 drivers/input/input-compat.h |    2 +
 drivers/input/input.c        |   74 +++++++++++++++++++++++++++++++++---------
 2 files changed, 61 insertions(+), 15 deletions(-)


diff --git a/drivers/input/input-compat.h b/drivers/input/input-compat.h
index 47cd9ea..0ef5dcd 100644
--- a/drivers/input/input-compat.h
+++ b/drivers/input/input-compat.h
@@ -75,6 +75,8 @@ static inline size_t input_event_size(void)
 
 #else
 
+#define INPUT_COMPAT_TEST (0)
+
 static inline size_t input_event_size(void)
 {
 	return sizeof(struct input_event);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 910d7be..13b1d26 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/rcupdate.h>
 #include <linux/smp_lock.h>
+#include "input-compat.h"
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech at suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -831,18 +832,51 @@ static void input_seq_stop(struct seq_file *seq, void *v)
 		mutex_unlock(&input_mutex);
 }
 
+static int input_bits_to_string(char *buf, int buf_size,
+				unsigned long bits, bool skip_empty)
+{
+	int len = 0;
+
+	if (INPUT_COMPAT_TEST) {
+		u32 dword = (bits & 0xffffffff00000000UL) >> 32;
+		if (dword || !skip_empty)
+			len += snprintf(buf, buf_size, "%x ", dword);
+
+		dword = (bits & 0xffffffffUL);
+		if (dword || !skip_empty || len)
+			len += snprintf(buf + len, min(buf_size - len, 0),
+					"%x", dword);
+	} else {
+		if (bits || !skip_empty)
+			len += snprintf(buf, buf_size, "%lx", bits);
+	}
+
+	return len;
+}
+
 static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
 				   unsigned long *bitmap, int max)
 {
 	int i;
-
-	for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
-		if (bitmap[i])
-			break;
+	bool skip_empty = true;
+	char buf[18];
 
 	seq_printf(seq, "B: %s=", name);
-	for (; i >= 0; i--)
-		seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+
+	for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
+		if (input_bits_to_string(buf, sizeof(buf),
+					 bitmap[i], skip_empty)) {
+			skip_empty = false;
+			seq_printf(seq, "%s%s", buf, i > 0 ? " " : "");
+		}
+	}
+
+	/*
+	 * If no output was produced print a single 0.
+	 */
+	if (skip_empty)
+		seq_puts(seq, "0");
+
 	seq_putc(seq, '\n');
 }
 
@@ -1131,14 +1165,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
 {
 	int i;
 	int len = 0;
+	bool skip_empty = true;
+
+	for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
+		len += input_bits_to_string(buf + len, max(buf_size - len, 0),
+					    bitmap[i], skip_empty);
+		if (len) {
+			skip_empty = false;
+			if (i > 0)
+				len += snprintf(buf + len, max(buf_size - len, 0), " ");
+		}
+	}
 
-	for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
-		if (bitmap[i])
-			break;
-
-	for (; i >= 0; i--)
-		len += snprintf(buf + len, max(buf_size - len, 0),
-				"%lx%s", bitmap[i], i > 0 ? " " : "");
+	/*
+	 * If no output was produced print a single 0.
+	 */
+	if (len == 0)
+		len = snprintf(buf, buf_size, "%d", 0);
 
 	if (add_cr)
 		len += snprintf(buf + len, max(buf_size - len, 0), "\n");
@@ -1153,7 +1196,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev,		\
 {									\
 	struct input_dev *input_dev = to_input_dev(dev);		\
 	int len = input_print_bitmap(buf, PAGE_SIZE,			\
-				     input_dev->bm##bit, ev##_MAX, 1);	\
+				     input_dev->bm##bit, ev##_MAX,	\
+				     true);				\
 	return min_t(int, len, PAGE_SIZE);				\
 }									\
 static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
@@ -1217,7 +1261,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
 
 	len = input_print_bitmap(&env->buf[env->buflen - 1],
 				 sizeof(env->buf) - env->buflen,
-				 bitmap, max, 0);
+				 bitmap, max, false);
 	if (len >= (sizeof(env->buf) - env->buflen))
 		return -ENOMEM;
 


More information about the hal mailing list