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

This patch adds support for processing multi-touch (MT) kernel events.
To do this, it must filter out older style single touch (ST) events
to prevent conflicts.

For Bamboo's/Tablet PC, channel 0 == 1st finger and channel 1 == 2nd finger.

In older Bamboo kernel driver, serial #1 == 1st finger and serial #2 ==
2nd finger.  Mapping to channel was serial # - 1 and events had to
come in isolated by separate BTN_TOOL_DOUBLETAP/TRIPLETAP messages.

With newer MT kernel driver, MT slot 0 == 1st finger and MT slot 1 ==
2nd finger.  Take advantage of this straight mapping to channel.
Code will ignore ST-style events then MT packets will write to
either channel 0 or 1 or both.

Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com>
---

This patch contains updates based on comments from Peter.  In mean time,
I also found a bug/typo in filtering logic.  Should have been
EV_KEY for BTN_TOOL_* checks.

v3 addresses spaces-instead-of-tabs issue Peter mentioned.

 src/wcmUSB.c        |  137 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/xf86WacomDefs.h |   28 ++++++++++
 2 files changed, 154 insertions(+), 11 deletions(-)

diff --git a/src/wcmUSB.c b/src/wcmUSB.c
index 1d54b3f..7bd65f4 100644
--- a/src/wcmUSB.c
+++ b/src/wcmUSB.c
@@ -33,6 +33,8 @@
 typedef struct {
        int wcmLastToolSerial;
        int wcmBTNChannel;
+       Bool wcmUseMT;
+       int wcmMTChannel;
        int wcmEventCnt;
        struct input_event wcmEvents[MAX_USB_EVENTS];
 } wcmUSBData;
@@ -410,6 +412,7 @@ int usbWcmGetRanges(InputInfoPtr pInfo)
        unsigned long abs[NBITS(ABS_MAX)] = {0};
        WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
        WacomCommonPtr common = priv->common;
+       wcmUSBData* private = common->private;
        int is_touch = IsTouch(priv);
 
        /* Devices such as Bamboo P&T may have Pad data reported in the same
@@ -509,6 +512,8 @@ int usbWcmGetRanges(InputInfoPtr pInfo)
        if (ioctl(pInfo->fd, EVIOCGABS(ABS_DISTANCE), &absinfo) == 0)
                common->wcmMaxDist = absinfo.maximum;
 
+       if (ISBITSET(common->wcmKeys, ABS_MT_SLOT))
+               private->wcmUseMT = 1;
 
        if ((common->tablet_id >= 0xd0) && (common->tablet_id <= 0xd3))
        {
@@ -788,6 +793,55 @@ skipEvent:
        private->wcmEventCnt = 0;
 }
 
+static int usbFilterEvent(WacomCommonPtr common, struct input_event *event)
+{
+       wcmUSBData* private = common->private;
+
+       /* For devices that report multitouch, the following list is a set of
+        * duplicate data from one slot and needs to be filtered out.
+        */
+       if (private->wcmUseMT)
+       {
+               if (event->type == EV_KEY)
+               {
+                       switch(event->code)
+                       {
+                               case BTN_TOUCH:
+                               case BTN_TOOL_FINGER:
+                                       return 1;
+                       }
+               }
+               else if (event->type == EV_ABS)
+               {
+                       switch(event->code)
+                       {
+                               case ABS_X:
+                               case ABS_Y:
+                               case ABS_PRESSURE:
+                                       return 1;
+                       }
+               }
+       }
+
+       /* For generic devices, filter out doubletap/tripletap that
+        * can be confused with older protocol.
+        */
+       if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC)
+       {
+               if (event->type == EV_KEY)
+               {
+                       switch(event->code)
+                       {
+                               case BTN_TOOL_DOUBLETAP:
+                               case BTN_TOOL_TRIPLETAP:
+                                       return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static int usbParseAbsEvent(WacomCommonPtr common,
                            struct input_event *event, WacomDeviceState *ds)
 {
@@ -844,6 +898,55 @@ static int usbParseAbsEvent(WacomCommonPtr common,
        return change;
 }
 
+static int usbParseAbsMTEvent(WacomCommonPtr common, struct input_event *event)
+{
+       int change = 1;
+       wcmUSBData* private = common->private;
+       WacomDeviceState *ds;
+
+       ds = &common->wcmChannel[private->wcmMTChannel].work;
+
+       switch(event->code)
+       {
+               case ABS_MT_SLOT:
+                       if (event->value >= 0 && event->value < MAX_FINGERS)
+                       {
+                               WacomDeviceState *dsnew;
+
+                               private->wcmMTChannel = event->value;
+                               dsnew = &common->
+                                       wcmChannel[private->wcmMTChannel].work;
+
+                               dsnew->device_type = TOUCH_ID;
+                               dsnew->device_id = TOUCH_DEVICE_ID;
+                               dsnew->serial_num = event->value+1;
+                       }
+                       break;
+
+               case ABS_MT_TRACKING_ID:
+                       ds->proximity = (event->value != -1);
+
+                       ds->sample = (int)GetTimeInMillis();
+                       break;
+
+               case ABS_MT_POSITION_X:
+                       ds->x = event->value;
+                       break;
+
+               case ABS_MT_POSITION_Y:
+                       ds->y = event->value;
+                       break;
+
+               case ABS_MT_PRESSURE:
+                       ds->capacity = event->value;
+                       break;
+
+               default:
+                       change = 0;
+       }
+       return change;
+}
+
 static struct
 {
        unsigned long device_type;
@@ -947,11 +1050,6 @@ static int usbParseKeyEvent(WacomCommonPtr common,
 
                        /* fall through */
                case BTN_TOOL_DOUBLETAP:
-                       /* If a real double tap report, ignore. */
-                       if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC &&
-                           event->code == BTN_TOOL_DOUBLETAP)
-                               break;
-
                        DBG(6, common,
                            "USB Touch detected %x (value=%d)\n",
                            event->code, event->value);
@@ -977,10 +1075,6 @@ static int usbParseKeyEvent(WacomCommonPtr common,
                        break;
 
                case BTN_TOOL_TRIPLETAP:
-                       /* If a real triple tap report, ignore. */
-                       if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC)
-                               break;
-
                        DBG(6, common,
                            "USB Touch second finger detected %x (value=%d)\n",
                            event->code, event->value);
@@ -1080,7 +1174,7 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
        WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
        WacomCommonPtr common = priv->common;
        int channel;
-       int channel_change = 0, btn_channel_change = 0;
+       int channel_change = 0, btn_channel_change = 0, mt_channel_change = 0;
        WacomChannelPtr pChannel;
        WacomDeviceState dslast;
        wcmUSBData* private = common->private;
@@ -1165,10 +1259,22 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
                        "event[%d]->type=%d code=%d value=%d\n",
                        i, event->type, event->code, event->value);
 
+               /* Check for events to be ignored and skip them up front. */
+               if (usbFilterEvent(common, event))
+                       continue;
+
                /* absolute events */
                if (event->type == EV_ABS)
                {
-                       channel_change |= usbParseAbsEvent(common, event, ds);
+                       if (usbParseAbsEvent(common, event, ds))
+                               channel_change |= 1;
+                       else if (usbParseAbsMTEvent(common, event))
+                       {
+                               if (private->wcmMTChannel == 0)
+                                       channel_change |= 1;
+                               else if (private->wcmMTChannel == 1)
+                                       mt_channel_change |= 1;
+                       }
                }
                else if (event->type == EV_REL)
                {
@@ -1232,6 +1338,15 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
            (private->wcmBTNChannel == channel && btn_channel_change))
                wcmEvent(common, channel, ds);
 
+       /* dispatch for second finger.  first finger is handled above. */
+       if (mt_channel_change)
+       {
+               WacomDeviceState *mt_ds;
+
+               mt_ds = &common->wcmChannel[1].work;
+               wcmEvent(common, 1, mt_ds);
+       }
+
        /* dispatch butten events when re-routed */
        if (private->wcmBTNChannel != channel && btn_channel_change)
        {
diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h
index 87d75d5..b8c94b3 100644
--- a/src/xf86WacomDefs.h
+++ b/src/xf86WacomDefs.h
@@ -47,6 +47,8 @@
 #define PROXOUT_INTUOS_DISTANCE                10
 #define PROXOUT_GRAPHIRE_DISTANCE      42
 
+/* 2.6.28 */
+
 #ifndef BTN_TOOL_DOUBLETAP
 #define BTN_TOOL_DOUBLETAP 0x14d
 #endif
@@ -55,6 +57,32 @@
 #define BTN_TOOL_TRIPLETAP 0x14e
 #endif
 
+/* 2.6.30 */
+
+#ifndef ABS_MT_POSITION_X
+#define ABS_MT_POSITION_X 0x35
+#endif
+
+#ifndef ABS_MT_POSITION_Y
+#define ABS_MT_POSITION_Y 0x36
+#endif
+
+#ifndef ABS_MT_TRACKING_ID
+#define ABS_MT_TRACKING_ID 0x39
+#endif
+
+/* 2.6.33 */
+
+#ifndef ABS_MT_PRESSURE
+#define ABS_MT_PRESSURE 0x3a
+#endif
+
+/* 2.6.36 */
+
+#ifndef ABS_MT_SLOT
+#define ABS_MT_SLOT 0x2f
+#endif
+
 /* defines to discriminate second side button and the eraser */
 #define ERASER_PROX     4
 #define OTHER_PROX      1
-- 
1.7.3.3


------------------------------------------------------------------------------
Lotusphere 2011
Register now for Lotusphere 2011 and learn how
to connect the dots, take your collaborative environment
to the next level, and enter the era of Social Business.
http://p.sf.net/sfu/lotusphere-d2d
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to