[PATCH] hid: 3m: Simplify touchsreen emulation logic

Chase Douglas chase.douglas at canonical.com
Sun Aug 15 17:42:30 UTC 2010


On Sat, 2010-08-14 at 17:29 +0100, Henrik Rydberg wrote:
> The ten-finger 3M screen M2256PW has a kernel driver already
> (hid-3m-pct), but with a couple of glitches:
> 
> 1. The one-touch down/up, which emits BTN_TOUCH events, sometimes does
> not work properly. This results in buttons getting stuck in the
> button-down state in the window manager.
> 
> 2. The action after touch-up in one spot followed by a touch-down in
> another spot sometimes causes a sequence of strange finger-tracing
> events along the perimeter of the rectangle between the two spots. The
> root of the problem lies in how the kernel inteprets the HID hybrid
> event type which is used by the 3M device [1].
> 
> While a proper HID solution is being worked out upstream, this patch
> simplifies the driver logic such that BTN_TOUCH and ABS_X/Y events are
> emitted properly, in effect papering over the worst problems. Suggested
> for inclusion in Maverick.
> 
> [1] Suggested by Stephane Chatty, who also confirms the observed problems.
> 
> Signed-off-by: Henrik Rydberg <rydberg at euromail.se>
> ---
>  drivers/hid/hid-3m-pct.c |   47 +++++++++------------------------------------
>  1 files changed, 10 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
> index 2a0d56b..fc57c0c 100644
> --- a/drivers/hid/hid-3m-pct.c
> +++ b/drivers/hid/hid-3m-pct.c
> @@ -125,9 +125,7 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
>   */
>  static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
>  {
> -	struct mmm_finger *oldest = 0;
> -	bool pressed = false, released = false;
> -	int i;
> +	int i, index = -1;
>  
>  	/*
>  	 * we need to iterate on all fingers to decide if we have a press
> @@ -149,45 +147,20 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
>  			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
>  						wide ? f->h : f->w);
>  			input_mt_sync(input);
> -			/*
> -			 * touchscreen emulation: maintain the age rank
> -			 * of this finger, decide if we have a press
> -			 */
> -			if (f->rank == 0) {
> -				f->rank = ++(md->num);
> -				if (f->rank == 1)
> -					pressed = true;
> -			}
> -			if (f->rank == 1)
> -				oldest = f;
> -		} else {
> -			/* this finger took off the screen */
> -			/* touchscreen emulation: maintain age rank of others */
> -			int j;
> -
> -			for (j = 0; j < 10; ++j) {
> -				struct mmm_finger *g = &md->f[j];
> -				if (g->rank > f->rank) {
> -					g->rank--;
> -					if (g->rank == 1)
> -						oldest = g;
> -				}
> -			}
> -			f->rank = 0;
> -			--(md->num);
> -			if (md->num == 0)
> -				released = true;
> +
> +			if (index < 0)
> +				index = i;
>  		}
>  		f->valid = 0;
>  	}
>  
>  	/* touchscreen emulation */
> -	if (oldest) {
> -		if (pressed)
> -			input_event(input, EV_KEY, BTN_TOUCH, 1);
> -		input_event(input, EV_ABS, ABS_X, oldest->x);
> -		input_event(input, EV_ABS, ABS_Y, oldest->y);
> -	} else if (released) {
> +	if (index >= 0) {
> +		struct mmm_finger *f = &md->f[index];
> +		input_event(input, EV_KEY, BTN_TOUCH, 1);
> +		input_event(input, EV_ABS, ABS_X, f->x);
> +		input_event(input, EV_ABS, ABS_Y, f->y);
> +	} else {
>  		input_event(input, EV_KEY, BTN_TOUCH, 0);
>  	}
>  }
> -- 
> 1.7.1

Won't this emit a button touch down and ABS_{X,Y} event every time any
finger moves? I can think of many ways this could break things,
including the ABS_{X,Y} values flittering back and forth between all
fingers touching the screen. This would make dragging and dropping a
nightmare if you accidentally or intentionally touch more than one
finger to the display at a time.

Is the one-touch button down/up issue caused by driver logic or hardware
issues?

I wonder if a better solution would be single-touch emulation by only
sending BTN_TOUCH and ABS_{X,Y} events on the first touch started and
not sending these events on the second touch started when the first is
released.

-- Chase





More information about the kernel-team mailing list