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

The core of xf86-input-wacom strictly enforces buttons
on tools that are out-of-proximity must be cleared except
for the special case of the PAD device that is always
considered in proximity.

Simple/Generic tablets (non-wacom) and touchpads will send
button presses associated with tablet itself even though no
tools are reported as in proximity.

Work around this by forcing all non-styus button presses
to be routed to hard coded PAD channel and post multiple
channel events per sync window.

MT packets could be implemented using same concept and
routing to hard coded channel 0 or 1 based on finger #.

Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com>
Reviewed-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/wcmUSB.c |  110 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 89 insertions(+), 21 deletions(-)

diff --git a/src/wcmUSB.c b/src/wcmUSB.c
index eed755e..973e358 100644
--- a/src/wcmUSB.c
+++ b/src/wcmUSB.c
@@ -35,6 +35,7 @@
 
 typedef struct {
        int wcmLastToolSerial;
+       int wcmPadChannel;
        int wcmEventCnt;
        struct input_event wcmEvents[MAX_USB_EVENTS];
 } wcmUSBData;
@@ -752,6 +753,13 @@ static int usbChooseChannel(WacomCommonPtr common)
                 */
                channel = 0;
                serial = 1;
+
+               /* Generic devices are only ones that will send
+                * pad buttons without a PAD serial # so hardcode
+                * the reserved channel here.  The rest can protocols
+                * can rely on normal channel logic.
+                */
+               private->wcmPadChannel = MAX_CHANNELS-1;
        }
        else if (common->wcmProtocolLevel == WCM_PROTOCOL_4)
        {
@@ -784,6 +792,7 @@ static int usbChooseChannel(WacomCommonPtr common)
                        channel = serial-1;
                else
                        channel = 0;
+               private->wcmPadChannel = channel;
        }
        else if (serial) /* serial number should never be 0 for V5 devices */
        {
@@ -834,6 +843,7 @@ static int usbChooseChannel(WacomCommonPtr common)
                                        !common->wcmChannel[0].work.proximity ) 
/* new transducer */
                                channel = 0;
                }
+               private->wcmPadChannel = channel;
        }
 
        /* fresh out of channels */
@@ -950,9 +960,11 @@ skipEvent:
        private->wcmEventCnt = 0;
 }
 
-static void usbParseAbsEvent(WacomCommonPtr common,
-                            struct input_event *event, WacomDeviceState *ds)
+static int usbParseAbsEvent(WacomCommonPtr common,
+                           struct input_event *event, WacomDeviceState *ds)
 {
+       int change = 1;
+
        switch(event->code)
        {
                case ABS_X:
@@ -1003,7 +1015,10 @@ static void usbParseAbsEvent(WacomCommonPtr common,
                        if (event->value)
                                ds->device_id = event->value;
                        break;
+               default:
+                       change = 0;
        }
+       return change;
 }
 
 static struct
@@ -1024,16 +1039,18 @@ static struct
        { PAD_ID,    BTN_TOOL_FINGER    }
 };
 
-static void usbParseKeyEvent(WacomCommonPtr common,
-                            struct input_event *event, WacomDeviceState *ds,
-                            WacomDeviceState *dslast)
+#define MOD_BUTTONS(bit, value) do { \
+       shift = 1<<bit; \
+       ds->buttons = (((value) != 0) ? \
+       (ds->buttons | (shift)) : (ds->buttons & ~(shift))); \
+       } while (0)
+
+static int usbParseKeyEvent(WacomCommonPtr common,
+                           struct input_event *event, WacomDeviceState *ds,
+                           WacomDeviceState *dslast)
 {
-       int shift, nkeys;
-       #define MOD_BUTTONS(bit, value) do { \
-               shift = 1<<bit; \
-               ds->buttons = (((value) != 0) ? \
-               (ds->buttons | (shift)) : (ds->buttons & ~(shift))); \
-               } while (0)
+       int shift;
+       int change = 1;
 
        /* BTN_TOOL_* are sent to indicate when a specific tool is going
         * in our out of proximity.  When going out of proximity, ds
@@ -1046,8 +1063,9 @@ static void usbParseKeyEvent(WacomCommonPtr common,
         * that map to different channels can be in proximity at same
         * time with no confusion.
         *
-        * Remaining part of case state (after BTN_TOOL_*) handle normal
-        * button presses.
+        * Remaining part of case state (after BTN_TOOL_*) handle buttons
+        * on stylus that validaty depends on its tool being in
+        * proximity.
         */
        switch (event->code)
        {
@@ -1165,16 +1183,38 @@ static void usbParseKeyEvent(WacomCommonPtr common,
                         * combination with the first finger data */
                        break;
 
+               case BTN_STYLUS:
+                       MOD_BUTTONS(1, event->value);
+                       break;
+
+               case BTN_STYLUS2:
+                       MOD_BUTTONS(2, event->value);
+                       break;
+               default:
+                       change = 0;
+       }
+       return change;
+}
+
+/* Track buttons associated with always in proximity PAD device. These
+ * are buttons located on tablet itself.
+ */
+static int usbParsePadKeyEvent(WacomCommonPtr common,
+                              struct input_event *event, WacomDeviceState *ds)
+{
+       int shift, nkeys;
+       int change = 1;
+
+       switch (event->code)
+       {
                case BTN_LEFT:
                        MOD_BUTTONS(0, event->value);
                        break;
 
-               case BTN_STYLUS:
                case BTN_MIDDLE:
                        MOD_BUTTONS(1, event->value);
                        break;
 
-               case BTN_STYLUS2:
                case BTN_RIGHT:
                        MOD_BUTTONS(2, event->value);
                        break;
@@ -1196,17 +1236,21 @@ static void usbParseKeyEvent(WacomCommonPtr common,
                                        break;
                                }
                        }
+                       if (nkeys >= common->npadkeys)
+                               change = 0;
        }
+       return change;
 }
 
 static void usbDispatchEvents(InputInfoPtr pInfo)
 {
        int i;
-       WacomDeviceState* ds;
+       WacomDeviceState *ds, *pad_ds;
        struct input_event* event;
        WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
        WacomCommonPtr common = priv->common;
        int channel;
+       int channel_change = 0, pad_channel_change = 0;
        WacomChannelPtr pChannel;
        WacomDeviceState dslast;
        wcmUSBData* private = common->private;
@@ -1280,6 +1324,7 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
        ds = &common->wcmChannel[channel].work;
        ds->relwheel = 0;
        ds->serial_num = private->wcmLastToolSerial;
+       pad_ds = &common->wcmChannel[private->wcmPadChannel].work;
 
        /* loop through all events in group */
        for (i=0; i<private->wcmEventCnt; ++i)
@@ -1292,19 +1337,28 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
                /* absolute events */
                if (event->type == EV_ABS)
                {
-                       usbParseAbsEvent(common, event, ds);
+                       channel_change |= usbParseAbsEvent(common, event, ds);
                }
                else if (event->type == EV_REL)
                {
                        if (event->code == REL_WHEEL)
+                       {
                                ds->relwheel = -event->value;
+                               channel_change |= 1;
+                       }
                        else
                                xf86Msg(X_ERROR, "%s: rel event recv'd (%d)!\n",
                                        pInfo->name, event->code);
                }
-
                else if (event->type == EV_KEY)
-                       usbParseKeyEvent(common, event, ds, &dslast);
+               {
+                       if (usbParseKeyEvent(common, event, ds, &dslast))
+                               channel_change |= 1;
+                       else
+                               pad_channel_change |=
+                                       usbParsePadKeyEvent(common, event,
+                                                           pad_ds);
+               }
        } /* next event */
 
        /* device type unknown? Tool may be on the tablet when X starts. */
@@ -1342,8 +1396,22 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
        if (!ds->proximity)
                private->wcmLastToolSerial = 0;
 
-       /* dispatch event */
-       wcmEvent(common, channel, ds);
+       /* dispatch tool event */
+       if (channel_change)
+               wcmEvent(common, channel, ds);
+       /* dispatch pad event */
+       if (pad_channel_change)
+       {
+               /* Force to in proximity for special case */
+               if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC)
+               {
+                       pad_ds->proximity = 1;
+                       pad_ds->device_type = PAD_ID;
+                       pad_ds->device_id = PAD_DEVICE_ID;
+                       pad_ds->serial_num = 0xf0;
+               }
+               wcmEvent(common, private->wcmPadChannel, pad_ds);
+       }
 }
 
 /**
-- 
1.7.3.1


------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in  U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store 
http://p.sf.net/sfu/nokia-dev2dev
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to