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