From: Chris Bagwell <ch...@cnpbagwell.com> The core of xf86-input-wacom strictly enforces buttons on tools that are out-of-proximity must be cleared except for the special case of the PAD device that is always considered in proximity.
Generic tablets (non-wacom) and touchpads will send button presses associated with tablet itself even if no tools are reported as in proximity. Work around this by forcing all non-styus button presses to be routed to hard coded PAD channel and post multiple channel events per sync window. This is for generic tablets only and wacom tablets continue to process events the same way. MT packets could be implemented using same concept and routing to hard coded channel 0 or 1 based on finger #. Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com> --- src/wcmUSB.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 86 insertions(+), 20 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 5fa3067..eb22d97 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -35,6 +35,7 @@ typedef struct { int wcmLastToolSerial; + int wcmBTNChannel; int wcmEventCnt; struct input_event wcmEvents[MAX_USB_EVENTS]; } wcmUSBData; @@ -752,6 +753,12 @@ static int usbChooseChannel(WacomCommonPtr common) */ channel = 0; serial = 1; + + /* Generic devices need to map stylus buttons to "channel" + * and all other button presses to PAD. Hardcode PAD + * channel here. + */ + private->wcmBTNChannel = MAX_CHANNELS-1; } else if (common->wcmProtocolLevel == WCM_PROTOCOL_4) { @@ -784,6 +791,8 @@ static int usbChooseChannel(WacomCommonPtr common) channel = serial-1; else channel = 0; + /* All events go to same channel for Protocol 4 */ + private->wcmBTNChannel = channel; } else if (serial) /* serial number should never be 0 for V5 devices */ { @@ -834,6 +843,8 @@ static int usbChooseChannel(WacomCommonPtr common) !common->wcmChannel[0].work.proximity ) /* new transducer */ channel = 0; } + /* All events go to same channel for Protocol 5 */ + private->wcmBTNChannel = channel; } /* fresh out of channels */ @@ -1029,17 +1040,18 @@ static struct { PAD_ID, BTN_TOOL_FINGER } }; +#define MOD_BUTTONS(bit, value) do { \ + shift = 1<<bit; \ + ds->buttons = (((value) != 0) ? \ + (ds->buttons | (shift)) : (ds->buttons & ~(shift))); \ + } while (0) + static int usbParseKeyEvent(WacomCommonPtr common, struct input_event *event, WacomDeviceState *ds, WacomDeviceState *dslast) { - int shift, nkeys; + int shift; int change = 1; - #define MOD_BUTTONS(bit, value) do { \ - shift = 1<<bit; \ - ds->buttons = (((value) != 0) ? \ - (ds->buttons | (shift)) : (ds->buttons & ~(shift))); \ - } while (0) /* BTN_TOOL_* are sent to indicate when a specific tool is going * in our out of proximity. When going out of proximity, ds @@ -1051,9 +1063,6 @@ static int usbParseKeyEvent(WacomCommonPtr common, * 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. - * - * Remaining part of case state (after BTN_TOOL_*) handle normal - * button presses. */ switch (event->code) { @@ -1171,26 +1180,64 @@ static int usbParseKeyEvent(WacomCommonPtr common, * combination with the first finger data */ break; + default: + change = 0; + } + + if (change) + return change; + + /* Rest back to non-default value for next switch statement */ + change = 1; + + /* From this point on, all BTN_* will be real button presses. + * Stylus buttons always go with *ds. Handle remaining + * cases upon return. + */ + switch (event->code) + { + case BTN_STYLUS: + MOD_BUTTONS(1, event->value); + break; + + case BTN_STYLUS2: + MOD_BUTTONS(2, event->value); + break; + + default: + change = 0; + } + + return change; +} + +/* Handle all button presses except for stylus buttons */ +static int usbParseBTNEvent(WacomCommonPtr common, + struct input_event *event, WacomDeviceState *ds) +{ + int shift, nkeys; + int change = 1; + + switch (event->code) + { case BTN_LEFT: MOD_BUTTONS(0, event->value); break; - case BTN_STYLUS: case BTN_MIDDLE: MOD_BUTTONS(1, event->value); break; - case BTN_STYLUS2: case BTN_RIGHT: MOD_BUTTONS(2, event->value); break; case BTN_SIDE: - MOD_BUTTONS (3, event->value); + MOD_BUTTONS(3, event->value); break; case BTN_EXTRA: - MOD_BUTTONS (4, event->value); + MOD_BUTTONS(4, event->value); break; default: @@ -1211,12 +1258,12 @@ static int usbParseKeyEvent(WacomCommonPtr common, static void usbDispatchEvents(InputInfoPtr pInfo) { int i; - WacomDeviceState* ds; + WacomDeviceState *ds, *btn_ds; struct input_event* event; WacomDevicePtr priv = (WacomDevicePtr)pInfo->private; WacomCommonPtr common = priv->common; int channel; - int channel_change = 0; + int channel_change = 0, btn_channel_change = 0; WacomChannelPtr pChannel; WacomDeviceState dslast; wcmUSBData* private = common->private; @@ -1290,6 +1337,8 @@ static void usbDispatchEvents(InputInfoPtr pInfo) ds = &common->wcmChannel[channel].work; ds->relwheel = 0; ds->serial_num = private->wcmLastToolSerial; + /* For protocol 4 and 5 devices, ds == btn_ds. */ + btn_ds = &common->wcmChannel[private->wcmBTNChannel].work; /* loop through all events in group */ for (i=0; i<private->wcmEventCnt; ++i) @@ -1315,11 +1364,14 @@ static void usbDispatchEvents(InputInfoPtr pInfo) xf86Msg(X_ERROR, "%s: rel event recv'd (%d)!\n", pInfo->name, event->code); } - else if (event->type == EV_KEY) { - channel_change |= usbParseKeyEvent(common, event, ds, - &dslast); + if (usbParseKeyEvent(common, event, ds, &dslast)) + channel_change |= 1; + else + btn_channel_change |= + usbParseBTNEvent(common, event, + btn_ds); } } /* next event */ @@ -1358,9 +1410,23 @@ static void usbDispatchEvents(InputInfoPtr pInfo) if (!ds->proximity) private->wcmLastToolSerial = 0; - /* dispatch event */ - if (channel_change) + /* dispatch events */ + if (channel_change || + (common->wcmProtocolLevel != WCM_PROTOCOL_GENERIC && + btn_channel_change)) wcmEvent(common, channel, ds); + + /* dispatch pad events on generic tablets */ + if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC && + btn_channel_change) + { + /* Force to in proximity for this special case */ + btn_ds->proximity = 1; + btn_ds->device_type = PAD_ID; + btn_ds->device_id = PAD_DEVICE_ID; + btn_ds->serial_num = 0xf0; + wcmEvent(common, private->wcmBTNChannel, btn_ds); + } } /** -- 1.7.3.1 ------------------------------------------------------------------------------ Nokia and AT&T present the 2010 Calling All Innovators-North America contest Create new apps & games for the Nokia N8 for consumers in U.S. and Canada $10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store http://p.sf.net/sfu/nokia-dev2dev _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel