On Mon, Dec 20, 2010 at 08:15:52PM -0600, ch...@cnpbagwell.com wrote:
> 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>
> ---

merged, thanks.

Cheers,
  Peter

> 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