sorry about the delay, as usual too many things on my slate

On Fri, Dec 31, 2010 at 10:48:47PM -0600, ch...@cnpbagwell.com wrote:
> From: Chris Bagwell <ch...@cnpbagwell.com>
> 
> Kernel side input event filtering forces user land to track previous
> tools values when switching to new tools.  If its not accounted
> for, sending new-but-duplicate values for new tool would cause confusion.
> Most cases of cursor jumps when entering proximity can be traced
> to how its (not) being handled in todays code.
> 
> For generic and protocol 4 devices, its just a matter of removing
> existing memset().  For 2FGT protocol 4 devices, its slightly
> harder because it switches fingers between channels.
> 
> Protocol 5 DUALINPUT devices are harder.  Take example of 2
> stylus in proximity at same time and one has tilt support but
> the other one does not.  Current kernel drivers will always
> report tilt values upon query and require user land to filter
> out as needed.  So we can't just copy previous values between
> tools.  For Protocol 5, this patch contiues to use old approach;
> at least until kernel side changes can be made.
> 
> 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>
> ---
>  src/wcmUSB.c        |  109 
> ++++++++++++++++++++++-----------------------------
>  src/xf86WacomDefs.h |    1 +
>  2 files changed, 48 insertions(+), 62 deletions(-)
> 
> diff --git a/src/wcmUSB.c b/src/wcmUSB.c
> index c25e67c..faeb3c4 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;
> @@ -582,7 +583,7 @@ static int usbChooseChannel(WacomCommonPtr common)
>                * and all other button presses to PAD.  Hardcode PAD
>                * channel here.
>                */
> -             private->wcmBTNChannel = MAX_CHANNELS-1;
> +             private->wcmBTNChannel = PAD_CHANNEL;
>       }
>       else if (common->wcmProtocolLevel == WCM_PROTOCOL_4)
>       {
> @@ -610,7 +611,7 @@ static int usbChooseChannel(WacomCommonPtr common)
>                * pad devices.
>                */
>               if (serial == 0xf0)
> -                     channel = MAX_CHANNELS-1;
> +                     channel = PAD_CHANNEL;
>               else if (serial)
>                       channel = serial-1;
>               else
> @@ -912,6 +913,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;
> @@ -975,15 +982,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)
>       {
> @@ -1170,7 +1171,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;
>  
> @@ -1184,65 +1184,49 @@ 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.
> -      *
> -      * 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().
> -      *
> -      * 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.
> -      */
> -     if (!common->wcmChannel[channel].work.proximity)
> +     if (common->wcmProtocolLevel != WCM_PROTOCOL_5)

tbh, I prefer if you'd reverse this conditions. especially for complex
conditions that require more brain-space, having
    if (foo)
            bar;
    else
            foobar;

seems easier to read, as "everything else" falls into the "else" else
branch. this condition here is the semantic equivalent of
        if (everything else)
                foobar;
        else if (specific case)
                bar;
               


>       {
> -             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.
> +             /* Because of linux input filtering, each switch to a new
> +              * tool is required to have its initial values match values
> +              * of previous 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.
> +              * For normal case, all tools are in channel 0 and so
> +              * no issue.  Protocol 4 2FGT devices split between
> +              * two channels though and so need to copy data between
> +              * channels to prevent loss of events; which could
> +              * lead to cursor jumps.
>                *
> -              * 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.
> +              * PAD device is special.  It shares no events
> +              * with other channels and is always in proximity.
> +              * So it requires no copying of data from other
> +              * channels.
>                */
> -             common->wcmChannel[channel].work.proximity = 1;
> +             if (private->wcmPrevChannel != channel &&
> +                 channel != PAD_CHANNEL &&
> +                 private->wcmPrevChannel != PAD_CHANNEL)
> +             {
> +                     common->wcmChannel[channel].work =
> +                             
> common->wcmChannel[private->wcmPrevChannel].work;
> +                     private->wcmPrevChannel = channel;
> +             }
>       }
> +     /* Protocol 5 devices have some complications related to DUALINPUT
> +      * support and can not use above logic to recover from input
> +      * event filtering.  Instead, just deal with occasional dropped
> +      * event.  Since tools are dynamically assigned a channel #, the
> +      * structure must be initialiized to known starting values
                                ^ typo



> +      * when first entering proximity to discard invalid data.
> +      */
> +     else if (!common->wcmChannel[channel].work.proximity)
> +             memset(&common->wcmChannel[channel],0,sizeof(WacomChannel));
>  
> -     /* 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;
>  
> @@ -1306,6 +1290,7 @@ static void usbDispatchEvents(InputInfoPtr pInfo)
>                       if (ISBITSET(keys, wcmTypeToKey[i].tool_key))
>                       {
>                               ds->device_type = wcmTypeToKey[i].device_type;
> +                             ds->proximity = 1;
>                               break;
>                       }
>               }
> diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h
> index e621f78..4e6b5f9 100644
> --- a/src/xf86WacomDefs.h
> +++ b/src/xf86WacomDefs.h
> @@ -392,6 +392,7 @@ extern WacomDeviceClass gWacomISDV4Device;
>  #define RAW_FILTERING_FLAG      4
>  
>  #define MAX_CHANNELS 3
> +#define PAD_CHANNEL (MAX_CHANNELS-1)
>  #define MAX_FINGERS  2

please split this into a separate patch.

>  
>  typedef struct {
> -- 
> 1.7.3.4

as for the rest of the code, channels are still a grey area for me so if
Ping is happy with the patch (once split up), I'll merge it.
 
Cheers,
  Peter

------------------------------------------------------------------------------
Gaining the trust of online customers is vital for the success of any company
that requires sensitive data to be transmitted over the Web.   Learn how to 
best implement a security strategy that keeps consumers' information secure 
and instills the confidence they need to proceed with transactions.
http://p.sf.net/sfu/oracle-sfdevnl 
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to