From 7958d05c254cbca6e59f7e0d5b16215ff47448b6 Mon Sep 17 00:00:00 2001
From: Chris Bagwell <chris@cnpbagwell.com>
Date: Wed, 10 Mar 2010 22:25:32 -0600
Subject: [PATCH 1/2] Refactor multi-touch event logic

This should have same behavior as before but with improved
readability.

Code was needlessly complex by detecting which _*in() or
*_out() to call per finger. Change to use a singe function
for both in and out of proximity events and compute
values to send inside single function.

Although current CVS doesn't have it, older old code had some buggy
work around logic related to out-of-prox being filtered out so easily.
It also wasn't documenting why it was doing this hard-to-read logic.  Added
extreme detail for aid to others debugging lost events.

Added ABS_X/ABS_Y filter work-around from BPT to tablet PC.

Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
---
 src/2.6.27/wacom.h     |    1 +
 src/2.6.27/wacom_sys.c |   28 ++++
 src/2.6.27/wacom_wac.c |  400 ++++++++++++++++++++++++++++-------------------
 3 files changed, 267 insertions(+), 162 deletions(-)

diff --git a/src/2.6.27/wacom.h b/src/2.6.27/wacom.h
index dc17d51..697dbf6 100755
--- a/src/2.6.27/wacom.h
+++ b/src/2.6.27/wacom.h
@@ -134,6 +134,7 @@ 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);
 extern void wacom_input_sync(void *wcombo);
+extern void wacom_input_mt_sync(void *wcombo);
 extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
diff --git a/src/2.6.27/wacom_sys.c b/src/2.6.27/wacom_sys.c
index 96a40b5..87b9b2a 100755
--- a/src/2.6.27/wacom_sys.c
+++ b/src/2.6.27/wacom_sys.c
@@ -145,6 +145,11 @@ void wacom_input_sync(void *wcombo)
 	input_sync(get_input_dev((struct wacom_combo *)wcombo));
 }
 
+void wacom_input_mt_sync(void *wcombo)
+{
+	input_mt_sync(get_input_dev((struct wacom_combo *)wcombo));
+}
+
 static int wacom_open(struct input_dev *dev)
 {
 	struct wacom *wacom = input_get_drvdata(dev);
@@ -190,6 +195,17 @@ void input_dev_bpt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 			wacom_wac->features.x_phy, 0, 0);
 		input_set_abs_params(input_dev, ABS_RY, 0,
 			wacom_wac->features.y_phy, 0, 0);
+
+#if 0
+		/* finger position */
+		input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+	     			     wacom_wac->features.x_max, 0, 0);
+		input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+	     			     wacom_wac->features.y_max, 0, 0);
+		input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
+	     			     wacom_wac->features.pressure_max, 0, 0);
+#endif
+
 		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
 		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP);
 		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
@@ -314,7 +330,19 @@ void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) {
+#if 0
+	        /* finger position */
+	        input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+				     wacom_wac->features.x_max, 0, 0);
+		input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+				     wacom_wac->features.y_max, 0, 0);
+		input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
+				     wacom_wac->features.pressure_max, 
+				     0, 0);
+#endif
+
 		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP);
+
 		input_dev->evbit[0] |= BIT_MASK(EV_MSC);
 		input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
 	}
diff --git a/src/2.6.27/wacom_wac.c b/src/2.6.27/wacom_wac.c
index 2a93788..5eb24a9 100755
--- a/src/2.6.27/wacom_wac.c
+++ b/src/2.6.27/wacom_wac.c
@@ -151,75 +151,137 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
 	return 1;
 }
 
-static void wacom_bpt_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx)
-{
-	int x = 0, y = 0, pressure;
-	int finger = idx + 1;
-
-	pressure = (data[2 + (idx * 9)] & 0xff);
-	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 + finger*3);
-	wacom_report_abs(wcombo, ABS_Y, y + finger*3);
-	wacom_report_abs(wcombo, ABS_PRESSURE, pressure + finger*3);
-	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-	wacom_report_key(wcombo, wacom->tool[idx], 1);
-
-	if (!idx)
-		wacom_report_key(wcombo, BTN_TOUCH, 1);
-	wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, finger);
-}
-
-static void wacom_bpt_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
-{
-	int finger = idx + 1;
-
-	wacom_report_abs(wcombo, ABS_X, 0);
-	wacom_report_abs(wcombo, ABS_Y, 0);
-	wacom_report_abs(wcombo, ABS_PRESSURE, 0);
-	wacom_report_abs(wcombo, ABS_MISC, 0);
-	wacom_report_key(wcombo, wacom->tool[idx], 0);
-
-	if (!idx)
-		wacom_report_key(wcombo, BTN_TOUCH, 0);
-	wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, finger);
-}
-
-static void wacom_bpt_touch_in(struct wacom_wac *wacom, void *wcombo)
+static void wacom_bpt_touch(struct wacom_wac *wacom, void *wcombo,
+			    int force_out)
 {
 	char *data = wacom->data;
-
-	wacom->id[1] = (((data[3] & 0x80) >> 7) & 0x1) |
-	      (((data[12] & 0x80) >> 6) & 0x2);
-
-	/* First finger down */
-	if (data[3] & 0x80) {
-		wacom_bpt_finger_in(wacom, wcombo, data, 0);
-		wacom->tool[0] = BTN_TOOL_DOUBLETAP; 
-		wacom->id[0] = TOUCH_DEVICE_ID; 
-	} else if (wacom->tool[0])
-		wacom_bpt_touch_out(wacom, wcombo, 0);
-
-	/* Second finger down */
-	if (data[12] & 0x80) {
-		/* sync first finger data */
-		if (wacom->tool[0])
-			wacom_input_sync(wcombo);
-
-		wacom_bpt_finger_in(wacom, wcombo, data, 1);
-		wacom->tool[1] = BTN_TOOL_TRIPLETAP;
-	} else if (wacom->tool[1]) {
-		/* sync first finger data */
-		if (wacom->tool[0])
-			wacom_input_sync(wcombo);
-
-		wacom_bpt_touch_out(wacom, wcombo, 1);
-		wacom->tool[1] = 0;
+	int pressure1 = 0, x1 = 0, y1 = 0, pressure2 = 0, x2 = 0, y2 = 0;
+	int prox1 = 0, prox2 = 0;
+	static int old_prox1 = 1, old_prox2 = 1;
+
+	if (!force_out)
+	{
+	    prox1 = data[3] & 0x80;
+	    if (prox1)
+	    {
+	        pressure1 = (data[2] & 0xff);
+		x1 = wacom_be16_to_cpu ((unsigned char *)&data[3]) & 0x7ff;
+		y1 = wacom_be16_to_cpu ((unsigned char *)&data[5]) & 0x7ff;
+	    }
+
+	    prox2 = data[12] & 0x80;
+	    if (prox2)
+	    {
+	        pressure2 = (data[11] & 0xff);
+		x2 = wacom_be16_to_cpu ((unsigned char *)&data[12]) & 0x7ff;
+		y2 = wacom_be16_to_cpu ((unsigned char *)&data[14]) & 0x7ff;
+	    }
 	}
-
-	if (!(data[3] & 0x80))
-		wacom->tool[0] = 0;
+ 
+#if 0
+	wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox1 != 0);
+	wacom_report_abs(wcombo, ABS_MT_POSITION_X, x1);
+	wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y1);
+ 
+	wacom_input_mt_sync(wcombo);
+ 
+	wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox2 != 0);
+	wacom_report_abs(wcombo, ABS_MT_POSITION_X, x2);
+	wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y2);
+ 
+	wacom_input_mt_sync(wcombo);
+#endif
+
+	/* Normally, we send both fingers data on any finger change.
+	 * Since input layer thinks its the same finger, its
+	 * filtering can cause problems.  
+	 *
+	 * The follow are things to address.  When it says
+	 * complete event will not be sent, it means
+	 * that ABS_X/ABS_Y/ABS_PRESSURE as well as
+	 * BTN_TOOL_DOUBLETAP/BTN_TOOL_TRIPLETAP may not
+	 * be sent.  ABS_MISC is almost never sent except
+	 * for first finger event.
+	 *
+	 * Loss of finger events is especially noticeable when going
+	 * out-of-prox and especially for finger 2.
+	 * Its common for enough unwanted filtering
+	 * to occur that X will only receive 2 events per-SYNC
+	 * and discard the message.
+	 *
+	 * 1. Finger 1 in prox & Finger 2 out prox - No filtering
+	 * issues but application must filter out duplicate
+	 * out-of-prox events since input layer can not.
+	 * 1.1 Finger 1 in prox & Finger 2 out prox - If
+	 * previous interrupt had Finger 2 values same as
+	 * new finger 1 values then finger 1 complete event will not
+	 * be sent.
+	 * 2. Finger 1 in prox & Finger 2 in prox - Filtering
+	 * will not allow sending complete event data for finger 2
+	 * when both fingers have same values.
+	 * 2.1 Finger 1 in prox & Finger 2 in prox - If
+	 * previous interrupt had Finger 2 values same as
+	 * new finger 1 values then finger 1 complete event will not
+	 * be sent.
+	 * 3. Finger 1 out prox & Finger 2 in prox - No filtering
+	 * issues but application must filter out duplicate
+	 * out-of-prox events since input layer can not.
+	 * 4. Finger 1 out prox & Finger 2 out prox - Second
+	 * finger data would never send ABS_* events.
+	 * Since only two events will be sent, X would discard always.
+	 * 4.1 Finger 1 out prox & Finger 2 out prox - If
+	 * previous interrupt was case #3 then complete event
+	 * for finger 1 will not be sent but at least X doesn't
+	 * discard this one.
+	 *
+	 * Since going out-of-prox causes so much unwanted
+	 * filtering, special logic exists to catch case
+	 * #4 and #4.1 and prevent sending out-of-prox if we already
+	 * sent it in the past.
+	 */
+	if (prox1 || old_prox1 != prox1)
+	{
+	    wacom_report_abs(wcombo, ABS_PRESSURE, pressure1);
+	    wacom_report_abs(wcombo, ABS_X, x1);
+	    wacom_report_abs(wcombo, ABS_Y, y1);
+
+	    wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+	    wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1);
+  	    wacom_report_key(wcombo, BTN_TOUCH, prox1);
+
+	    wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+	    wacom_input_sync(wcombo);
+	}
+#if 0
+	else
+	{
+	    /* MT docs require always sending a sync */
+	    wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+	    wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+	    wacom_input_sync(wcombo);
+	}
+#endif
+	old_prox1 = prox1;
+
+	if (prox2 || old_prox2 != prox2)
+	{
+	    /* Two finger scrolls tend to have fingers on
+	     * same X or Y axis or same pressure.  That
+	     * will get filtered out.  Notice the +3 has
+	     * work around.  Of course, this just leads
+	     * to other cases were its filtered out
+	     * but gives preference to two finger scrolls.
+	     */
+	    wacom_report_abs(wcombo, ABS_PRESSURE, pressure2+3);
+	    wacom_report_abs(wcombo, ABS_X, x2+3);
+	    wacom_report_abs(wcombo, ABS_Y, y2+3);
+
+	    wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+	    wacom_report_key(wcombo, BTN_TOOL_TRIPLETAP, prox2);
+	    wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 2);
+	    wacom_input_sync(wcombo);
+	}
+	old_prox2 = prox2;
 }
 
 static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
@@ -258,17 +320,9 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
 
 		prox = (data[17] & 0x30 >> 4);
 		if (prox)
-			wacom_bpt_touch_in(wacom, wcombo);
+			wacom_bpt_touch(wacom, wcombo, 0);
 		else {
-			if (wacom->id[1] & 0x1) {
-				wacom_bpt_touch_out(wacom, wcombo, 0);
-				/* sync first finger event */
-				if (wacom->id[1] & 0x2) 
-					wacom_input_sync(wcombo);
-			}
-			if (wacom->id[1] & 0x2)
-				wacom_bpt_touch_out(wacom, wcombo, 1);
-			wacom->id[0] = 0;
+		        wacom_bpt_touch(wacom, wcombo, 1);
 		}
 		retval = 1;
 	} else if (urb->actual_length == WACOM_PKGLEN_BBFUN) { /* Penabled */
@@ -757,82 +811,114 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
 	return 1;
 }
 
-static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx)
-{
-	wacom_report_abs(wcombo, ABS_X, 
-		(data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8));
-	wacom_report_abs(wcombo, ABS_Y, 
-		(data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8));
-	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-	wacom_report_key(wcombo, wacom->tool[idx], 1);
-	if (!idx) 
-		wacom_report_key(wcombo, BTN_TOUCH, 1);
-	wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, idx + 1);
-}
-
-static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
+static void wacom_tpc_touch(struct wacom_wac *wacom, void *wcombo,
+			    int force_out)
 {
-	wacom_report_abs(wcombo, ABS_X, 0);
-	wacom_report_abs(wcombo, ABS_Y, 0);
-	wacom_report_abs(wcombo, ABS_MISC, 0);
-	wacom_report_key(wcombo, wacom->tool[idx], 0);
-	if (!idx) 
-		wacom_report_key(wcombo, BTN_TOUCH, 0);
-	wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, idx + 1);
-	return;
-}
-
-static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo)
-{
-	char *data = wacom->data;
-	struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
-
-	wacom->tool[0] = BTN_TOOL_DOUBLETAP;  
-	wacom->id[0] = TOUCH_DEVICE_ID; 
-	wacom->tool[1] = BTN_TOOL_TRIPLETAP;
-
-	if (urb->actual_length != WACOM_PKGLEN_TPC1FG) {
-		switch (data[0]) {
-			case WACOM_REPORT_TPC1FG:
-				wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
-				wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
-				wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
-				wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
-				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-				wacom_report_key(wcombo, wacom->tool[0], 1);
-				break;
-			case WACOM_REPORT_TPC2FG:
-				if (data[1] & 0x01) {
-					wacom_tpc_finger_in(wacom, wcombo, data, 0);
-				} else if (wacom->id[1] & 0x01) {
-					wacom_tpc_touch_out(wacom, wcombo, 0);
-				}
-
-				if (data[1] & 0x02) {
-					/* sync first finger data */
-					if (wacom->id[1] & 0x01)
-						wacom_input_sync(wcombo);
-
-					wacom_tpc_finger_in(wacom, wcombo, data, 1);
-				} else if (wacom->id[1] & 0x02) {
-					/* sync first finger data */
-					if (wacom->id[1] & 0x01)
-						wacom_input_sync(wcombo);
-
-					wacom_tpc_touch_out(wacom, wcombo, 1);
-				}
-				/* keep this byte to send proper out-prox event */
-				wacom->id[1] = data[1] & 0x03;
-				break;
+ 	char *data = wacom->data;
+ 	struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
+	int pressure1 = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	int prox1 = 0, prox2 = 0;
+	static int old_prox1 = 1, old_prox2 = 1;
+	int send_multi = 0, send_pressure = 0;
+
+	if (!force_out && urb->actual_length != WACOM_PKGLEN_TPC1FG) {
+	    if (data[0] == WACOM_REPORT_TPC1FG) {
+	        prox1 = data[1] & 0x01;
+		if (prox1)
+		{
+		    x1 = wacom_le16_to_cpu(&data[2]);
+		    y1 = wacom_le16_to_cpu(&data[4]);
+		    pressure1 = wacom_le16_to_cpu(&data[6]);
 		}
-	} else {
-		wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
-		wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
-		wacom_report_key(wcombo, BTN_TOUCH, 1);
-		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-		wacom_report_key(wcombo, wacom->tool[0], 1);
+		send_pressure = 1;
+	    } else if (data[0] == WACOM_REPORT_TPC2FG) {
+	        prox1 = data[1] & 0x01;
+		if (prox1)
+		{
+	            x1 = (data[2] & 0xff) | ((data[3] & 0x7f) << 8);
+		    y1 = (data[6] & 0xff) | ((data[7] & 0x7f) << 8);
+		}
+ 
+	        prox2 = data[1] & 0x01;
+		if (prox2)
+		{
+		    x2 = (data[4] & 0xff) | ((data[5] & 0x7f) << 8);
+		    y2 = (data[8] & 0xff) | ((data[9] & 0x7f) << 8);
+		}
+ 
+		send_multi = 1;
+	    }
+	} else if (!force_out) {
+	    prox1 = data[0] & 0x01;
+	    if (prox1)
+	    {
+	        x1 = wacom_le16_to_cpu(&data[1]);
+		y1 = wacom_le16_to_cpu(&data[3]);
+	    }
 	}
-	return;
+ 
+#if 0
+	if (send_multi)
+	{
+	    wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox1 != 0);
+	    wacom_report_abs(wcombo, ABS_MT_POSITION_X, x1);
+	    wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y1);
+
+	    wacom_input_mt_sync(wcombo);
+
+	    wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox2 != 0);
+	    wacom_report_abs(wcombo, ABS_MT_POSITION_X, x2);
+	    wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y2);
+
+	    wacom_input_mt_sync(wcombo);
+ 	}
+#endif
+
+	/* See Bamboo P&T comments on why this is needed */
+	if (prox1 || old_prox1 != prox1)
+	{
+	    if (send_pressure)
+	        wacom_report_abs(wcombo, ABS_PRESSURE, pressure1);
+	    wacom_report_abs(wcombo, ABS_X, x1);
+	    wacom_report_abs(wcombo, ABS_Y, y1);
+
+	    wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+	    wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1);
+	    wacom_report_key(wcombo, BTN_TOUCH, prox1);
+	    wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+	    wacom_input_sync(wcombo);
+	}
+#if 0
+	else
+	{
+	    /* MT docs require always sending a sync */
+	    wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+	    wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+	    wacom_input_sync(wcombo);
+	}
+#endif
+	old_prox1 = prox1;
+
+	if (prox2 || old_prox2 != prox2)
+	{
+	    /* Two finger scrolls tend to have fingers on
+	     * same X or Y axis or same pressure.  That
+	     * will get filtered out.  Notice the +3 has
+	     * work around.  Of course, this just leads
+	     * to other cases were its filtered out
+	     * but gives preference to two finger scrolls.
+	     */
+	    wacom_report_abs(wcombo, ABS_X, x2+3);
+	    wacom_report_abs(wcombo, ABS_Y, y2+3);
+
+	    wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+	    wacom_report_key(wcombo, BTN_TOOL_TRIPLETAP, prox2);
+	    wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 2);
+	    wacom_input_sync(wcombo);
+	}
+	old_prox2 = prox2;
+
+ 	return;
 }
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
@@ -859,23 +945,13 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
 
 		if (!wacom->shared->stylus_in_proximity) {
 			if (prox) {
-				wacom_tpc_touch_in(wacom, wcombo);
+				wacom_tpc_touch(wacom, wcombo, 0);
 				return 1;
 			}
 		}
 
-		/* 2FGT out-prox */
-		if (data[0] == WACOM_REPORT_TPC2FG) {
-			if (wacom->id[1] & 0x01) {
-				wacom_tpc_touch_out(wacom, wcombo, 0);
-				/* sync first finger event */
-				if (wacom->id[1] & 0x02)
-					wacom_input_sync(wcombo);
-			}
-			if (wacom->id[1] & 0x02)
-				wacom_tpc_touch_out(wacom, wcombo, 1);
-		} else /* one finger touch */
-			wacom_tpc_touch_out(wacom, wcombo, 0);
+		/* force out-of-prox */
+  	        wacom_tpc_touch(wacom, wcombo, 1);
 
 		/* don't reset id when pen is in prox */
 		if (!wacom->shared->stylus_in_proximity)
-- 
1.6.6.1

