Bug#562052: Correctly identify touchpads
Dmitry Torokhov
dmitry.torokhov at gmail.com
Wed Jan 6 23:58:51 PST 2010
On Mon, Jan 04, 2010 at 01:18:43AM -0800, Dmitry Torokhov wrote:
> 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?
>
*ping* Any luck with this one? I'd like to get it into .33.
Thanks!
> 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;
>
--
Dmitry
More information about the hal
mailing list