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

Kernel side input event filtering forces user land to track previous
tools values when switching to new tools.  Sending new-but-duplicate
values for new tool would cause confusion.

At one time, all wacom's sent zero values when going out of proximity
which allowed xf86-input-wacom to take a short cut and memset() values
when entering proximity.  This is not true of all drivers any more.

Change to initialize current tools values based on previous tools value;
which is only needed when tools use a new channel.

In this change, moved a strange force to in proximity to special case
of no tool found.  See deleted comments in patch for background on that.

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

I've tested this lightly on Bamboo only.  Pen/Eraser/Touch all seem
to work fine in random tests I did.  It does fix the cursor jumps
that Favux reported with MT Bamboo driver.

I think this is the right way to go instead of the unreliable memset().
It may expose some bugs but we can always fix those.  

Could people with protocol 5 devices give this a spin?  Those are the
ones that change channels the most.  I'll give it a spin with
protocol 4 version (linuxwacom version) of Bamboo driver first chance.

 src/wcmUSB.c |   90 +++++++++++++++++++--------------------------------------
 1 files changed, 30 insertions(+), 60 deletions(-)

diff --git a/src/wcmUSB.c b/src/wcmUSB.c
index 79c7e31..d6ac6d5 100644
--- a/src/wcmUSB.c
+++ b/src/wcmUSB.c
@@ -35,6 +35,7 @@ typedef struct {
        int wcmBTNChannel;
        Bool wcmUseMT;
        int wcmMTChannel;
+       int wcmPrevChannel;
        int wcmEventCnt;
        struct input_event wcmEvents[MAX_USB_EVENTS];
 } wcmUSBData;
@@ -917,6 +918,12 @@ static int usbParseAbsMTEvent(WacomCommonPtr common, 
struct input_event *event)
                                dsnew = &common->
                                        wcmChannel[private->wcmMTChannel].work;
 
+                               /* Set tool specific data here. Since
+                                * MT slots have fixed mapping to channel,
+                                * the channel will always have previous
+                                * tools values.  Since MT event filtering
+                                * is also per slot, this works as expected.
+                                */
                                dsnew->device_type = TOUCH_ID;
                                dsnew->device_id = TOUCH_DEVICE_ID;
                                dsnew->serial_num = event->value+1;
@@ -980,15 +987,9 @@ static int usbParseKeyEvent(WacomCommonPtr common,
        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
-        * is initialized to zeros elsewere.  When going in proximity,
-        * here we initialize tool specific values.
-        *
-        * This requires tools that map to same channel of an input
-        * device and that share events (ABS_X of PEN and ERASER for
-        * example) not to be in proximity at the same time.  Tools
-        * that map to different channels can be in proximity at same
-        * time with no confusion.
+        * in our out of proximity.  When going in proximity, here we
+        * initialize tool specific values.  Making sure shared values
+        * are correct values during tool change is done elsewhere.
         */
        switch (event->code)
        {
@@ -1175,7 +1176,6 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
        WacomCommonPtr common = priv->common;
        int channel;
        int channel_change = 0, btn_channel_change = 0, mt_channel_change = 0;
-       WacomChannelPtr pChannel;
        WacomDeviceState dslast;
        wcmUSBData* private = common->private;
 
@@ -1189,65 +1189,34 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
                return;
        }
 
-       pChannel = common->wcmChannel + channel;
-       dslast = pChannel->valid.state;
-
-       /* Because of linux input filtering, the kernel driver can not
-        * always force total set of event data when new tool comes into
-        * proximity.  This includes simple case of flipping stylus
-        * from pen to eraser tool. Therefore, when new tool is in-prox
-        * we must initialize all shared event values to same as previous
-        * tool to account for filtered events.
-        *
-        * For Generic and Protocol 4 devices that have fixed channel
-        * mappings, this is no problem.  Protocol 5 devices are difficult
-        * because they dynamically assign channel #'s and even simple
-        * case above can switch from channel 1 to channel 0.
+       /* Because of linux input filtering, each switch to a new
+        * tool is required to have its initial values match values
+        * of previous tool.
         *
-        * To simplify things, we take advantage of fact wacom kernel
-        * drivers force all values to zero when going out of proximity so
-        * we take a short cut and memset() to align when going in-prox
-        * instead of a memcpy().
+        * When tools share a channel then this is no issue.  When
+        * switching channels, it needs to be accounted for here.
         *
-        * TODO: Some non-wacom tablets send X/Y data right before coming
-        * in proximity. The following discards that data.
-        * Adding "&& dslast.proximimty" to check would probably help
-        * this case.
-        * Some non-wacom tablets may also never reset their values
-        * to zero when out-of-prox.  The memset() can loss this data.
-        * Adding a !WCM_PROTOCOL_GENERIC check would probably help this case.
+        * Note: This logic would normally be done where we process
+        * BTN_TOOL_* events but protocol 4/5 devices have always
+        * sent BTN_TOOL_* as last event within a event sync window
+        * instead of as first event when changing tool.  So we must
+        * handle up front to prevent discarding other values set in
+        * same sync window.
         */
-       if (!common->wcmChannel[channel].work.proximity)
+       if (private->wcmPrevChannel != channel)
        {
-               memset(&common->wcmChannel[channel],0,sizeof(WacomChannel));
-
-               /* in case the in-prox event was missing */
-               /* TODO: There are not valid times when in-prox
-                * events are not sent by a driver except:
-                *
-                * 1) Starting X while tool is already in prox.
-                * 2) Non-wacom tablet sends only BTN_TOUCH without
-                * BTN_TOOL_PEN since it only support 1 tool.
-                *
-                * Case 1) should be handled in same location as
-                * below check of (ds->device_type == 0) since its
-                * same reason.  It is better to query for real
-                * value instead of assuming in-prox.
-                * Case 2) should be handled in case statement that
-                * processes BTN_TOUCH for WCM_PROTOCOL_GENERIC devices.
-                *
-                * So we should not be forcing to in-prox here because
-                * it could cause cursor jump from (X,Y)=(0,0) if events
-                * are sent while out-of-prox; which can happen only
-                * with WCM_PROTOCOL_GENERIC devices. Hint: see TODO above.
-                */
-               common->wcmChannel[channel].work.proximity = 1;
+               common->wcmChannel[channel].work =
+                       common->wcmChannel[private->wcmPrevChannel].work;
+               private->wcmPrevChannel = channel;
        }
 
-       /* all USB data operates from previous context except relative values*/
        ds = &common->wcmChannel[channel].work;
+       dslast = common->wcmChannel[channel].valid.state;
+
+       /* all USB data operates from previous context except relative values*/
        ds->relwheel = 0;
        ds->serial_num = private->wcmLastToolSerial;
+
        /* For protocol 4 and 5 devices, ds == btn_ds. */
        btn_ds = &common->wcmChannel[private->wcmBTNChannel].work;
 
@@ -1311,6 +1280,7 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
                        if (ISBITSET(keys, wcmTypeToKey[i].tool_key))
                        {
                                ds->device_type = wcmTypeToKey[i].device_type;
+                               ds->proximity = 1;
                                break;
                        }
                }
-- 
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