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

Henrik Rydberg rydberg at euromail.se
Sat Aug 14 16:29:27 UTC 2010


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





More information about the kernel-team mailing list