On Sun, Dec 19, 2010 at 09:46:39PM -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.
thanks for the patch. I just have a few style comments, but the meat of the patch looks alright. > Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com> > --- > src/wcmUSB.c | 142 > +++++++++++++++++++++++++++++++++++++++++++++++++++++----- > 1 files changed, 131 insertions(+), 11 deletions(-) > > diff --git a/src/wcmUSB.c b/src/wcmUSB.c > index 1d54b3f..854ab03 100644 > --- a/src/wcmUSB.c > +++ b/src/wcmUSB.c > @@ -33,6 +33,8 @@ > typedef struct { > int wcmLastToolSerial; > int wcmBTNChannel; > + int wcmMTMode; wcmMTMode suggests that there is a number of acceptable modes. maybe use "wcmUseMT" to indicates a boolean yes/no instead? also, make it a Bool? > + int wcmMTChannel; > int wcmEventCnt; > struct input_event wcmEvents[MAX_USB_EVENTS]; > } wcmUSBData; > @@ -403,6 +405,9 @@ static void usbInitProtocol4(WacomCommonPtr common, const > char* id, > common->wcmFlags &= ~TILT_ENABLED_FLAG; > } > > +/* FIXME: I'm compiling against 2.6.35 header files in /usr/include/linux */ > +#define ABS_MT_SLOT 0x2f #ifndef? we already have definitions for some new kernel defines in xf86WacomDefs.h, so you could just add this one there. > + > int usbWcmGetRanges(InputInfoPtr pInfo) > { > struct input_absinfo absinfo; > @@ -410,6 +415,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 +515,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->wcmMTMode = 1; > > if ((common->tablet_id >= 0xd0) && (common->tablet_id <= 0xd3)) > { > @@ -788,6 +796,52 @@ skipEvent: > private->wcmEventCnt = 0; > } > > +static int usbFilterEvent(WacomCommonPtr common, struct input_event *event) > +{ > +#ifdef ABS_MT_SLOT if you have the define as above, you don't need the ifdef's here. having this code won't hurt us if wcmMTMode cannot be set anyway. same goes for the next hunk. > + wcmUSBData* private = common->private; > + > + /* For devices that report multitouch, the following list is set of typo, "is _a_ set" > + * duplicate data from one slot and needs to be filtered out. > + */ > + if (private->wcmMTMode) { fwiw, style for {} is { on a newline. > + 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; > + } > + } > + } > + > +#endif > + > + /* For generic devices, filter out doubletap/tripletap that > + * can be confused with older protocol. > + */ > + if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC) { > + if (event->type == EV_ABS) { > + 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,60 @@ static int usbParseAbsEvent(WacomCommonPtr common, > return change; > } > > +static int usbParseAbsMTEvent(WacomCommonPtr common, struct input_event > *event) > +{ > +#ifndef ABS_MT_SLOT > + /* requires Linux 2.6.36 or newer */ > + return 0; > +#else > + 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; > +#endif > +} > + > static struct > { > unsigned long device_type; > @@ -947,11 +1055,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 +1080,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 +1179,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, mt1_channel_change = 0; > WacomChannelPtr pChannel; > WacomDeviceState dslast; > wcmUSBData* private = common->private; > @@ -1165,10 +1264,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) > + mt1_channel_change |= 1; > + } > } > else if (event->type == EV_REL) > { > @@ -1232,6 +1343,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 (mt1_channel_change) I find mt1_ a bit confusing. if the first finger is handled already, maybe just name it mt_channel_change? Cheers, Peter > + { > + WacomDeviceState *mt1_ds; > + > + mt1_ds = &common->wcmChannel[1].work; > + wcmEvent(common, 1, mt1_ds); > + } > + > /* dispatch butten events when re-routed */ > if (private->wcmBTNChannel != channel && btn_channel_change) > { > -- > 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