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