Serial ISDv4 kernel driver, wacom_w8001.ko, provides both pen and touch events on the same logical port. Filtering touch events when pen is in proximity while allowing pen events (ABS_X/Y, etc) pass.
Making this action configurable would make sense when XInput 2.1 is ready. At that point, we can post MT valuators while pen events are posted. Some code refactoring is needed to add a new channel to store the pen data as well as the 2FGT data. Defering the code refactoring until we support XInput 2.1. Signed-off-by: Ping Cheng <[email protected]> Reviewed-by: Peter Hutterer <[email protected]> Reviewed-by: Chris Bagwell <[email protected]> --- v3 changes: Incorporated Chris' comments. Added Reviewed-by. --- src/wcmUSB.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 9e0f310..82a0195 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -33,6 +33,8 @@ typedef struct { int wcmLastToolSerial; int wcmBTNChannel; + int wcmDeviceType; + Bool wcmPenTouch; Bool wcmUseMT; int wcmMTChannel; int wcmPrevChannel; @@ -571,8 +573,14 @@ int usbWcmGetRanges(InputInfoPtr pInfo) common->wcmMaxDist = absinfo.maximum; if (ISBITSET(abs, ABS_MT_SLOT)) + { private->wcmUseMT = 1; + /* pen and MT on the same logical port */ + if (ISBITSET(common->wcmKeys, BTN_TOOL_PEN)) + private->wcmPenTouch = TRUE; + } + /* A generic protocol device does not report ABS_MISC event */ if (!ISBITSET(abs, ABS_MISC)) common->wcmProtocolLevel = WCM_PROTOCOL_GENERIC; @@ -865,12 +873,29 @@ static int usbFilterEvent(WacomCommonPtr common, struct input_event *event) } else if (event->type == EV_ABS) { - switch(event->code) + if (private->wcmDeviceType == TOUCH_ID) { - case ABS_X: - case ABS_Y: - case ABS_PRESSURE: - return 1; + /* filter ST for MT */ + switch(event->code) + { + case ABS_X: + case ABS_Y: + case ABS_PRESSURE: + return 1; + } + } + else + { + /* filter MT for pen */ + switch(event->code) + { + case ABS_MT_SLOT: + case ABS_MT_TRACKING_ID: + case ABS_MT_POSITION_X: + case ABS_MT_POSITION_Y: + case ABS_MT_PRESSURE: + return 1; + } } } } @@ -1219,6 +1244,59 @@ static int usbParseBTNEvent(WacomCommonPtr common, return change; } +/*** + * Retrieve the tool type from an USB data packet by looking at the event + * codes. Refer to linux/input.h for event codes that define tool types. + * + * @param data A pointer to struct wcmUSBData to access device specific data. + */ +static void usbInitToolType(wcmUSBData *data) +{ + int i; + struct input_event* event; + + /* default to 0 if no pen/touch/eraser event code is in the packet */ + data->wcmDeviceType = 0; + + for (i = 0; (i < data->wcmEventCnt) && !data->wcmDeviceType; ++i) + { + event = data->wcmEvents + i; + + switch (event->code) + { + case BTN_TOOL_PEN: + case BTN_TOOL_PENCIL: + case BTN_TOOL_BRUSH: + case BTN_TOOL_AIRBRUSH: + data->wcmDeviceType = STYLUS_ID; + break; + + case BTN_TOOL_FINGER: + case ABS_MT_SLOT: + case ABS_MT_TRACKING_ID: + data->wcmDeviceType = TOUCH_ID; + break; + + case BTN_TOOL_RUBBER: + data->wcmDeviceType = ERASER_ID; + break; + } + } +} + +/** + * Check if the tool is a stlys/eraser and in-prox or not. + * + * @param ds The tool state stored in wcmChannel + * @return True if stlys/eraser is in-prox; False otherwise. + */ +static Bool usbIsPenInProx(WacomDeviceState ds) +{ + Bool is_pen = (ds.device_type == STYLUS_ID) || + (ds.device_type == ERASER_ID); + return (is_pen && ds.proximity); +} + static void usbDispatchEvents(InputInfoPtr pInfo) { int i; @@ -1228,11 +1306,29 @@ static void usbDispatchEvents(InputInfoPtr pInfo) WacomCommonPtr common = priv->common; int channel; int channel_change = 0, btn_channel_change = 0, mt_channel_change = 0; - WacomDeviceState dslast; + WacomDeviceState dslast = common->wcmChannel[0].valid.state; wcmUSBData* private = common->private; DBG(6, common, "%d events received\n", private->wcmEventCnt); + if (private->wcmPenTouch) + { + usbInitToolType(private); + + /* We get both pen and touch data from the kernel when they + * both are in/down. So, if we were (hence the need of dslast) + * processing pen events, we should ignore touch events. + * + * MT events will be posted to the userland when XInput 2.1 + * is ready. + */ + if ((private->wcmDeviceType == TOUCH_ID) && usbIsPenInProx(dslast)) + { + private->wcmEventCnt = 0; + return; + } + } + channel = usbChooseChannel(common); /* couldn't decide channel? invalid data */ -- 1.7.4 ------------------------------------------------------------------------------ Enable your software for Intel(R) Active Management Technology to meet the growing manageability and security demands of your customers. Businesses are taking advantage of Intel(R) vPro (TM) technology - will your software be a part of the solution? Download the Intel(R) Manageability Checker today! http://p.sf.net/sfu/intel-dev2devmar _______________________________________________ Linuxwacom-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel
