From: Chris Bagwell <ch...@cnpbagwell.com>

Bamboo P&T/Tablet PC code supports multi-touch but is using
the standard input driver's ABS_X/Y/PRESSURE which filters
duplicate events since it does not know they are unrelated.
Its also using Wacom-specific "serial channels" concept
to inform X driver which finger is currently being
sent.

This patch converts the 2 finger touch events over to this
new multi-touch interface.  Input layer's MT support is backwards
compatible so that older xdrv's will still seeing 1 finger.
xdrvs will need updates to see both fingers again.

Patch has support for both >=2.6.30 and <2.6.30.  Leave
code wrapped in "#if 1" in 2.6.30 kernel drivers and
remove "#if 0" code.  For older kernels, remove "#if 1"
logic and enable the "#if 0" logic.

Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com>
---
 src/2.6.27/wacom.h     |    1 +
 src/2.6.27/wacom_sys.c |   28 +++++
 src/2.6.27/wacom_wac.c |  318 +++++++++++++++++++++++------------------------
 3 files changed, 185 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..da96c6e 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,8 +195,19 @@ 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);
+
+               /* 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);
+
                input_dev->keybit[BIT_WORD(BTN_DIGI)] |= 
BIT_MASK(BTN_TOOL_DOUBLETAP);
+#if 0
                input_dev->keybit[BIT_WORD(BTN_DIGI)] |= 
BIT_MASK(BTN_TOOL_TRIPLETAP);
+#endif
                input_dev->keybit[BIT_WORD(BTN_DIGI)] |= 
BIT_MASK(BTN_TOOL_FINGER);
                input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
                        BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
@@ -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) {
+               /* 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);
+
+#if 0
                input_dev->keybit[BIT_WORD(BTN_DIGI)] |= 
BIT_MASK(BTN_TOOL_TRIPLETAP);
+
+#endif
                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..be67444 100755
--- a/src/2.6.27/wacom_wac.c
+++ b/src/2.6.27/wacom_wac.c
@@ -151,75 +151,73 @@ 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;
+
+       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 1
+       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
+ 
+       wacom_report_key(wcombo, BTN_TOUCH, prox1);
+#if 1
+       wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1 && prox2);
+#else
+       wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1);
+#endif
+ 
+       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_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+       wacom_input_sync(wcombo);
+ 
+#if 0
+       wacom_report_key(wcombo, BTN_TOOL_TRIPLETAP, prox2);
+ 
+       wacom_report_abs(wcombo, ABS_PRESSURE, pressure2);
+       wacom_report_abs(wcombo, ABS_X, x2);
+       wacom_report_abs(wcombo, ABS_Y, y2);
+ 
+       wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 2);
+       wacom_input_sync(wcombo);
+#endif
+ 
 }
 
 static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
@@ -258,17 +256,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 +747,96 @@ 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)
+static void wacom_tpc_touch(struct wacom_wac *wacom, void *wcombo,
+                           int force_out)
 {
-       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)
-{
-       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;
+       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 1
+       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
+
+       wacom_report_key(wcombo, BTN_TOUCH, prox1);
+#if 1
+       wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1 && prox2);
+#else
+       wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1);
+#endif
+
+       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_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+       wacom_input_sync(wcombo);
+
+#if 0
+       wacom_report_key(wcombo, BTN_TOOL_TRIPLETAP, prox2);
+
+       wacom_report_abs(wcombo, ABS_X, x2);
+       wacom_report_abs(wcombo, ABS_Y, y2);
+
+       wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 2);
+       wacom_input_sync(wcombo);
+#endif
+
+       return;
 }
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
@@ -859,23 +863,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


------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to