From 49bfeee91fa2900c616a114717c7022ac09e3a01 Mon Sep 17 00:00:00 2001
From: Chris Bagwell <chris@cnpbagwell.com>
Date: Wed, 10 Feb 2010 19:27:27 -0600
Subject: [PATCH] Fix for lost x/y/pressure data in two finger case.

Previous code couldn't tell x/y/pressure data was unrelated
for each finger and would not send duplicate values.  Result
in either old values or zero values being reported by X.
Work around by storing historical data and resetting before
each send.

Move static variables tracking proximity status to wacom_wac
structure so logic will work with multiple tablets.

Clear proximity tracking variables when both fingers go out
of proximity.  Fixes some unneeded extra proximity out sends
when a single finger comes back into proximity.

Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
---
 src/2.6.27/wacom.h     |    1 +
 src/2.6.27/wacom_sys.c |    7 +++++++
 src/2.6.27/wacom_wac.c |   37 ++++++++++++++++++++++++-------------
 src/2.6.27/wacom_wac.h |    4 ++++
 4 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/src/2.6.27/wacom.h b/src/2.6.27/wacom.h
index 5552b7e..f987f9f 100755
--- a/src/2.6.27/wacom.h
+++ b/src/2.6.27/wacom.h
@@ -127,6 +127,7 @@ struct wacom_combo {
 
 extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
 extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
+extern void wacom_report_abs_hist(void *wcombo, unsigned int abs_type, int abs_data, int abs_hist_data);
 extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
 extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
 extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value);
diff --git a/src/2.6.27/wacom_sys.c b/src/2.6.27/wacom_sys.c
index 7bc7180..5b32673 100755
--- a/src/2.6.27/wacom_sys.c
+++ b/src/2.6.27/wacom_sys.c
@@ -131,6 +131,13 @@ void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
 	input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
 }
 
+void wacom_report_abs_hist(void *wcombo, unsigned int abs_type, int abs_data, int abs_hist_data)
+{
+        struct input_dev *dev = get_input_dev((struct wacom_combo *)wcombo);
+	dev->abs[abs_type] = abs_hist_data;
+	input_report_abs(dev, abs_type, abs_data);
+}
+
 void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
 {
 	input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
diff --git a/src/2.6.27/wacom_wac.c b/src/2.6.27/wacom_wac.c
index 773001d..3d57826 100755
--- a/src/2.6.27/wacom_wac.c
+++ b/src/2.6.27/wacom_wac.c
@@ -159,9 +159,19 @@ static void wacom_bpt_finger_in(struct wacom_wac *wacom, void *wcombo, char *dat
 	x = wacom_be16_to_cpu ((unsigned char *)&data[3 + (idx * 9)]) & 0x7ff;
 	y = wacom_be16_to_cpu ((unsigned char *)&data[5 + (idx * 9)]) & 0x7ff;
 
-	wacom_report_abs(wcombo, ABS_X, x);
-	wacom_report_abs(wcombo, ABS_Y, y);
-	wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
+	/* In context of a single finger send, make use of wacom_report_abs()
+	 * to prevent sending the same value more then once.
+	 * wacom_report_abs() doesn't know difference between fingers
+	 * and will mistakenly filter out values common to 
+	 * multiple fingers.  Use wacom_report_abs_hist() to reset
+	 * historical send each time called.
+	 */
+	wacom_report_abs_hist(wcombo, ABS_X, x, wacom->abs_x[idx]);
+	wacom->abs_x[idx] = x;
+	wacom_report_abs_hist(wcombo, ABS_Y, y, wacom->abs_y[idx]);
+	wacom->abs_y[idx] = y;
+	wacom_report_abs_hist(wcombo, ABS_PRESSURE, pressure, wacom->abs_pressure[idx]);
+	wacom->abs_pressure[idx] = pressure;
 	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 	wacom_report_key(wcombo, wacom->tool[idx], 1);
 
@@ -185,8 +195,6 @@ static void wacom_bpt_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
 static void wacom_bpt_touch_in(struct wacom_wac *wacom, void *wcombo)
 {
 	char *data = wacom->data;
-	static int firstFinger = 0;
-	static int secondFinger = 0;
 
 	wacom->tool[0] = BTN_TOOL_DOUBLETAP; 
 	wacom->id[0] = TOUCH_DEVICE_ID; 
@@ -197,30 +205,30 @@ static void wacom_bpt_touch_in(struct wacom_wac *wacom, void *wcombo)
 	/* First finger down */
 	if (data[3] & 0x80) {
 		wacom_bpt_finger_in(wacom, wcombo, data, 0);
-		firstFinger = 1;
-	} else if (firstFinger) {
+		wacom->prox[0] = 1;
+	} else if (wacom->prox[0]) {
 		wacom_bpt_touch_out(wacom, wcombo, 0);
 	}
 
 	/* Second finger down */
 	if (data[12] & 0x80) {
 		/* sync first finger data */
-		if (firstFinger)
+		if (wacom->prox[0])
 			wacom_input_sync(wcombo);
 
 		wacom_bpt_finger_in(wacom, wcombo, data, 1);
-		secondFinger = 1;
-	} else if (secondFinger) {
+		wacom->prox[1] = 1;
+	} else if (wacom->prox[1]) {
 		/* sync first finger data */
-		if (firstFinger)
+		if (wacom->prox[0])
 			wacom_input_sync(wcombo);
 
 		wacom_bpt_touch_out(wacom, wcombo, 1);
-		secondFinger = 0;
+		wacom->prox[1] = 0;
 	}
 
 	if (!(data[3] & 0x80)) {
-		firstFinger = 0;
+		wacom->prox[0] = 0;
 	}
 }
 
@@ -249,6 +257,7 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
 		wacom_input_sync(wcombo);
 
 		prox = (data[17] & 0x30 >> 4);
+
 		if (!stylusInProx) {
 			if (prox) {
 				if (touchInProx) {
@@ -259,6 +268,7 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
 			} else {
 				if (wacom->id[1] & 0x1) {
 					wacom_bpt_touch_out(wacom, wcombo, 0);
+					wacom->prox[0] = 0;
 					/* sync first finger event */
 					if (wacom->id[1] & 0x2) {
 						wacom_input_sync(wcombo);
@@ -266,6 +276,7 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
 				}
 				if (wacom->id[1] & 0x2) {
 					wacom_bpt_touch_out(wacom, wcombo, 1);
+					wacom->prox[1] = 0;
 				}
 				touchOut = 0;
 				touchInProx = 1;
diff --git a/src/2.6.27/wacom_wac.h b/src/2.6.27/wacom_wac.h
index 8930c26..8091e50 100755
--- a/src/2.6.27/wacom_wac.h
+++ b/src/2.6.27/wacom_wac.h
@@ -83,6 +83,10 @@ struct wacom_wac {
         int tool[2];
         int id[2];
         __u32 serial[2];
+	int abs_x[2];
+	int abs_y[2];
+	int abs_pressure[2];
+	int prox[2];
 	struct wacom_features *features;
 	__u32 config;
 };
-- 
1.6.6

