The usbChooseChannel function is responsible for finding the channel
that should be used to contain a sequence of events for a particular
tool/contact. If a tool/contact is already using a particular channel
(i.e., the last event in the channel has the correct device type, serial
number, and is in proximity) then usbChooseChannel will return that
channel. Otherwise, usbChooseChannel will try to find a free channel
(i.e., one which is out of proximity) to be used to store the tool's
sequence of events.

The existing logic has a subtle bug that may result in a malfunction
when a specific condition occurs. In particular, if a multitouch report
from the kernel contains an existing contact going up followed by a
brand new contact, then usbChooseChannel will see the channel associated
with the former contact as free and begin using it to store data for the
new contact. As a result, the "up" event is never sent and can lead to
further strange touch behavior (including the effective disabling of
touch input).

To fix this, we modify usbChooseChannel to consider the "valid" state as
well as the working state when finding a new channel. A channel should
not be considered free if its valid state is still in prox, since this
indicates that the channel has *just* left prox. Note that we cannot
rely on only checking the valid state since this fails in the opposite
way: usbChooseChannel would not notice when a channel has *just* entered
prox and would overwrite its contents.

It isn't obvious wether it is also necessary to check the valid state
for the other two cases in this function (finding an existing channel
and forcefully clearing channels when out of space). The existing code
seems to work, however, so we will leave it as-is.

Signed-off-by: Jason Gerecke <>
 src/wcmUSB.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/wcmUSB.c b/src/wcmUSB.c
index ca63e6d..8ded958 100644
--- a/src/wcmUSB.c
+++ b/src/wcmUSB.c
@@ -932,7 +932,8 @@ static int usbChooseChannel(WacomCommonPtr common, int 
device_type, unsigned int
                        if (i == PAD_CHANNEL)
-                       if (!common->wcmChannel[i].work.proximity)
+                       if (!common->wcmChannel[i].work.proximity &&
+                           !common->wcmChannel[i].valid.state.proximity)
                                channel = i;

Check out the vibrant tech community on one of the world's most
engaging tech sites,!
Linuxwacom-devel mailing list

Reply via email to