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.

Starting with kernel 2.6.30, a multi-touch interface was
added to the kernel input layer to address this issue for all
modern multi-touch input devices.

This patch converts the 2 finger touch events over to this
multi-touch interface.  It is backwards compatible in that
pre-existing wacom X drivers will still see the first finger's
events using standard ABS_X/Y/PRESSURE interface.

Additional updates are needed to xdrv to support processing
these new MT events.

Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com>
---
 src/2.6.27/wacom.h     |    1 +
 src/2.6.27/wacom_sys.c |   34 +++++-
 src/2.6.27/wacom_wac.c |  287 ++++++++++++++++++-----------------------------
 3 files changed, 141 insertions(+), 181 deletions(-)

diff --git a/src/2.6.27/wacom.h b/src/2.6.27/wacom.h
index 5ec8abf..60a5fa2 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 93947b0..8f299f9 100755
--- a/src/2.6.27/wacom_sys.c
+++ b/src/2.6.27/wacom_sys.c
@@ -160,6 +160,12 @@ 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);
@@ -201,12 +207,20 @@ void input_dev_bpt(struct input_dev *input_dev, struct 
wacom_wac *wacom_wac)
 {
        /* 2FGT */
        if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
-               input_set_abs_params(input_dev, ABS_RX, 0,
-                       wacom_wac->features->x_phy, 0, 0);
+               input_set_abs_params(input_dev, ABS_RX, 0, 
+                                    wacom_wac->features->x_phy, 0, 0);
                input_set_abs_params(input_dev, ABS_RY, 0,
-                       wacom_wac->features->y_phy, 0, 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);
-               input_dev->keybit[BIT_WORD(BTN_DIGI)] |= 
BIT_MASK(BTN_TOOL_TRIPLETAP);
                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);
@@ -323,6 +337,18 @@ void input_dev_tpc(struct input_dev *input_dev, struct 
wacom_wac *wacom_wac)
                input_set_abs_params(input_dev, ABS_RX, 0, 
wacom_wac->features->x_phy, 0, 0);
                input_set_abs_params(input_dev, ABS_RY, 0, 
wacom_wac->features->y_phy, 0, 0);
                input_dev->keybit[BIT_WORD(BTN_DIGI)] |= 
BIT_MASK(BTN_TOOL_DOUBLETAP);
+
+               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);
+               }
+
        }
 }
 
diff --git a/src/2.6.27/wacom_wac.c b/src/2.6.27/wacom_wac.c
index 13d441b..7e6f25b 100755
--- a/src/2.6.27/wacom_wac.c
+++ b/src/2.6.27/wacom_wac.c
@@ -150,80 +150,55 @@ 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)
+static void wacom_bpt_touch(struct wacom_wac *wacom, void *wcombo,
+                           int force_out)
 {
-       int x = 0, y = 0, pressure;
-       int finger = idx + 1;
+       char *data = wacom->data;
+       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;
+           }
+       }
 
-       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_MT_TOUCH_MAJOR, prox1 != 0);
+       wacom_report_abs(wcombo, ABS_MT_POSITION_X, x1);
+       wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y1);
 
-       wacom_report_abs(wcombo, ABS_X, x + idx);
-       wacom_report_abs(wcombo, ABS_Y, y + idx);
-       wacom_report_abs(wcombo, ABS_PRESSURE, pressure + idx);
-       wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-       wacom_report_key(wcombo, wacom->tool[idx], 1);
+       wacom_input_mt_sync(wcombo);
 
-       if (!idx)
-               wacom_report_key(wcombo, BTN_TOUCH, 1);
-       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, finger);
-}
+       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);
 
-static void wacom_bpt_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
-{
-       int finger = idx + 1;
+       wacom_input_mt_sync(wcombo);
 
-       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);
+       wacom_report_key(wcombo, BTN_TOUCH, prox1);
+       wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1 && prox2);
 
-       if (!idx)
-               wacom_report_key(wcombo, BTN_TOUCH, 0);
-       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, finger);
-}
+       wacom_report_abs(wcombo, ABS_PRESSURE, pressure1);
+       wacom_report_abs(wcombo, ABS_X, x1);
+       wacom_report_abs(wcombo, ABS_Y, y1);
 
-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; 
-       wacom->tool[1] = BTN_TOOL_TRIPLETAP;
-       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);
-               firstFinger = 1;
-       } else if (firstFinger) {
-               wacom_bpt_touch_out(wacom, wcombo, 0);
-       }
-
-       /* Second finger down */
-       if (data[12] & 0x80) {
-               /* sync first finger data */
-               if (firstFinger)
-                       wacom_input_sync(wcombo);
-
-               wacom_bpt_finger_in(wacom, wcombo, data, 1);
-               secondFinger = 1;
-       } else if (secondFinger) {
-               /* sync first finger data */
-               if (firstFinger)
-                       wacom_input_sync(wcombo);
+       wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1);
+       wacom_input_sync(wcombo);
 
-               wacom_bpt_touch_out(wacom, wcombo, 1);
-               secondFinger = 0;
-       }
-
-       if (!(data[3] & 0x80))
-               firstFinger = 0;
 }
 
 static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo)
@@ -265,28 +240,18 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, void 
*wcombo)
                if (!stylusInProx) {
                        if (prox) {
                                if (touchInProx) {
-                                       wacom_bpt_touch_in(wacom, wcombo);
+                                       wacom_bpt_touch(wacom, wcombo, 0);
                                        touchOut = 1;
                                        retval = 1;
                                }
                        } 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_bpt_touch(wacom, wcombo, 1);
                                touchOut = 0;
                                touchInProx = 1;
                                retval = 1;
                        }
                } else if (touchOut || !prox) { /* force touch out-prox */
-                       wacom_bpt_touch_out(wacom, wcombo, 0);
-                       wacom_bpt_touch_out(wacom, wcombo, 1);
+                       wacom_bpt_touch(wacom, wcombo, 1);
 
                        touchOut = 0;
                        touchInProx = 1;
@@ -785,96 +750,82 @@ 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)
-{
-       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)
+static void wacom_tpc_touch(struct wacom_wac *wacom, void *wcombo,
+                           int force_out)
 {
        char *data = wacom->data;
        struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
-       static int firstFinger = 0;
-       static int secondFinger = 0;
-
-       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:
-                               /* keep this byte to send proper out-prox event 
*/
-                               wacom->id[1] = data[1] & 0x03;
-
-                               if (data[1] & 0x01) {
-                                       wacom_tpc_finger_in(wacom, wcombo, 
data, 0);
-                                       firstFinger = 1;
-                               } else if (firstFinger) {
-                                       wacom_tpc_touch_out(wacom, wcombo, 0);
-                               }
-
-                               if (data[1] & 0x02) {
-                                       /* sync first finger data */
-                                       if (firstFinger)
-                                               wacom_input_sync(wcombo);
-
-                                       wacom_tpc_finger_in(wacom, wcombo, 
data, 1);
-                                       secondFinger = 1;
-                               } else if (secondFinger) {
-                                       /* sync first finger data */
-                                       if (firstFinger)
-                                               wacom_input_sync(wcombo);
+       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]);
+               }
+               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);
+               }
 
-                                       wacom_tpc_touch_out(wacom, wcombo, 1);
-                                       secondFinger = 0;
-                               }
-                               if (!(data[1] & 0x01))
-                                       firstFinger = 0;
-                               break;
+               prox2 = data[1] & 0x01;
+               if (prox2)
+               {
+                   x2 = (data[4] & 0xff) | ((data[5] & 0x7f) << 8);
+                   y2 = (data[8] & 0xff) | ((data[9] & 0x7f) << 8);
                }
-       } 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_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]);
+           }
        }
+
+       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);
+
+       wacom_report_key(wcombo, BTN_TOUCH, prox1);
+       wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1 && prox2);
+
+       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);
+
        return;
 }
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
 {
        char *data = wacom->data;
-       int prox = 0, pressure, idx = -1;
+       int prox = 0, pressure;
        static int stylusInProx, touchInProx = 1, touchOut;
        struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
 
@@ -897,36 +848,18 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void 
*wcombo)
                if (!stylusInProx) { /* stylus not in prox */
                        if (prox) {
                                if (touchInProx) {
-                                       wacom_tpc_touch_in(wacom, wcombo);
+                                       wacom_tpc_touch(wacom, wcombo, 0);
                                        touchOut = 1;
                                        return 1;
                                }
                        } else {
-                               /* 2FGT out-prox */
-                               if (data[0] == WACOM_REPORT_TPC2FG) {
-                                       idx = (wacom->id[1] & 0x01) - 1;
-                                       if (idx == 0) {
-                                               wacom_tpc_touch_out(wacom, 
wcombo, idx);
-                                               /* sync first finger event */
-                                               if (wacom->id[1] & 0x02)
-                                                       
wacom_input_sync(wcombo);
-                                       }
-                                       idx = (wacom->id[1] & 0x02) - 1;
-                                       if (idx == 1)
-                                               wacom_tpc_touch_out(wacom, 
wcombo, idx);
-                               } else /* one finger touch */
-                                       wacom_tpc_touch_out(wacom, wcombo, 0);
+                               wacom_tpc_touch(wacom, wcombo, 1);
                                touchOut = 0;
                                touchInProx = 1;
                                return 1;
                        }
                } else if (touchOut || !prox) { /* force touch out-prox */
-                       wacom_tpc_touch_out(wacom, wcombo, 0);
-                       if (data[0] == WACOM_REPORT_TPC2FG) {
-                               idx = (wacom->id[1] & 0x02) - 1;
-                               if (idx == 1)
-                                       wacom_tpc_touch_out(wacom, wcombo, idx);
-                       }
+                       wacom_tpc_touch(wacom, wcombo, 1);
                        touchOut = 0;
                        touchInProx = 1;
                        return 1;
-- 
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