From 5113d18300bfae2dbffc78c67aef0760d612d995 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 23 Sep 2019 14:29:09 -0700 Subject: Ignore ABS_MISC as a source of device type information for AES pens AES sensors use protocol 5 since they send ABS_MISC events which contain information about the tool type in use. The tool type information sent by AES sensors does not match that used by EMR sensors, however. In particular, it is not possible to extract stylus/eraser/puck information from the ID. The driver would normally never try to extract this information, but the problem was highlighed when a bug in the kernel would cause the device ID to be reported twice: once in a packet alongside a BTN_TOOL_* event (fine) and a second time in a packet without such an event (causing the driver to try to figure it out from the ID instead). This commit adds detection for AES pen IDs and does not try to extract such information if an AES pen is in use. We assume that any protocol 5 device which predates the use of Intuos5-era technology uses the legacy IDs. Ref: https://github.com/linuxwacom/input-wacom/issues/134 Fixes: https://github.com/linuxwacom/xf86-input-wacom/issues/74 Signed-off-by: Jason Gerecke --- src/wcmUSB.c | 64 +++++++++++++++++++++++++++++++++++++++++++---------- src/xf86WacomDefs.h | 1 + 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 0e781ac..bb9ea23 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -464,6 +464,21 @@ static Bool usbWcmInit(InputInfoPtr pInfo, char* id, size_t id_len, float *versi common->wcmResolX = common->wcmResolY = 1016; } + /* Mark protocol 5 devices which predate the use of Intuos5 tech + * as using legacy IDs. These legacy IDs do not conform to the + * current format, in particular with respect to the use of the + * 0th device ID bit signalling EMR/AES. + */ + if (common->wcmModel == &usbIntuos || common->wcmModel == &usbIntuos2 || + common->wcmModel == &usbIntuos3 || common->wcmModel == &usbIntuos4 || + (sID.vendor == WACOM_VENDOR_ID && sID.product == 0x3F) || // Cintiq 21UX (Intuos3-era) + (sID.vendor == WACOM_VENDOR_ID && sID.product == 0xC5) || // Cintiq 20WSX (Intuos3-era) + (sID.vendor == WACOM_VENDOR_ID && sID.product == 0xC6) || // Cintiq 12WX (Intuos3-era) + (sID.vendor == WACOM_VENDOR_ID && sID.product == 0xCC)) // Cintiq 21UX2 (Intuos4-era) + { + TabletSetFeature(common, WCM_LEGACY_IDS); + } + /* Find out supported button codes. */ usbdata->npadkeys = 0; for (i = 0; i < ARRAY_SIZE(padkey_codes); i++) @@ -1161,30 +1176,54 @@ static int usbFilterEvent(WacomCommonPtr common, struct input_event *event) return 0; } +/** + * Determine if this is an AES tool or not from the tool ID. Bit 0 + * of the device ID is currently defined to be such a flag, but + * older tablet pens used this bit for other purposes. + * + * @param common A reference to the device's common structure + * @param id The tool id received from the kernel. + * @return 'true' if the tool uses AES, 'false' otherwise. + */ +static Bool toolIdIsAes(WacomCommonPtr common, int id) +{ + if (TabletHasFeature(common, WCM_LEGACY_IDS)) + return FALSE; + + return id & 0x01; +} + #define ERASER_BIT 0x008 #define PUCK_BITS 0xf00 #define PUCK_EXCEPTION 0x806 /** * Decide the tool type by its id for protocol 5 devices * + * @param common A reference to the device's common structure * @param id The tool id received from the kernel. * @return The tool type associated with the tool id. */ -static int usbIdToType(int id) +static int usbIdToType(WacomCommonPtr common, int id) { int type = STYLUS_ID; if (!id) return 0; - /* The existing tool ids have the following patten: all pucks, except - * one, have the third byte set to zero; all erasers have the fourth - * bit set. The rest are styli. - */ - if (id & ERASER_BIT) - type = ERASER_ID; - else if (!(id & PUCK_BITS) || (id == PUCK_EXCEPTION)) - type = CURSOR_ID; + if (toolIdIsAes(common, id)) { + /* Type information is not available from the ID for AES */ + return 0; + } + else { + /* The existing EMR tool ids have the following patten: all + * pucks, except one, have the third byte set to zero; all + * erasers have the fourth bit set. The rest are styli. + */ + if (id & ERASER_BIT) + type = ERASER_ID; + else if (!(id & PUCK_BITS) || (id == PUCK_EXCEPTION)) + type = CURSOR_ID; + } return type; } @@ -1195,10 +1234,11 @@ static int usbIdToType(int id) * Protocol 5 devices report different IDs for different styli and pucks, * Protocol 4 devices simply report STYLUS_DEVICE_ID, etc. * + * @param common A reference to the device's common structure * @param device_id id of the device * @return device type */ -static int usbFindDeviceTypeById(int device_id) +static int usbFindDeviceTypeById(WacomCommonPtr common, int device_id) { switch (device_id) { @@ -1213,7 +1253,7 @@ static int usbFindDeviceTypeById(int device_id) case PAD_DEVICE_ID: return PAD_ID; default: /* protocol 5 */ - return usbIdToType(device_id); + return usbIdToType(common, device_id); } } @@ -1671,7 +1711,7 @@ static int deviceTypeFromEvent(WacomCommonPtr common, int type, int code, int va return TOUCH_ID; case ABS_MISC: if (common->wcmProtocolLevel != WCM_PROTOCOL_GENERIC) - return usbFindDeviceTypeById(value); + return usbFindDeviceTypeById(common, value); } } diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h index 3305740..25ea1fd 100644 --- a/src/xf86WacomDefs.h +++ b/src/xf86WacomDefs.h @@ -169,6 +169,7 @@ struct _WacomModel always an LCD) */ #define WCM_PENTOUCH 0x00000400 /* Tablet supports pen and touch */ #define WCM_DUALRING 0x00000800 /* Tablet has two touch rings */ +#define WCM_LEGACY_IDS 0x00001000 /* Tablet uses legacy device IDs */ #define TabletHasFeature(common, feature) MaskIsSet((common)->tablet_type, (feature)) #define TabletSetFeature(common, feature) MaskSet((common)->tablet_type, (feature)) -- cgit v1.2.1