Skip to contentSkip to conversation

Input: wacom - Allow any multi-input Intuos device to set prox

PATCH In review Jason Gerecke 3 participants 9 messages Sep 6, 2012 – Oct 5, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/5 Input: wacom - Allow any multi-input Intuos device to set prox

The ability to set the proximity flag should apply to any device that has both pen and touch input. Rather than listing classes of devices known to meet this criteria, simply filter on the quirk defining all such devices.

---
 drivers/input/tablet/wacom_wac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/input/tablet/wacom_wac.c +2 -2
index 532d067..a8bc6c9 100644
@@ -326,7 +326,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
 	/* Enter report */
 	if ((data[1] & 0xfc) == 0xc0) {
-		if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+		if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
 			wacom->shared->stylus_in_proximity = true;
 
 		/* serial number of the tool */
@@ -414,7 +414,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
 	/* Exit report */
 	if ((data[1] & 0xfe) == 0x80) {
-		if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+		if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
 			wacom->shared->stylus_in_proximity = false;
 
 		/*
Signature · 1 line
1.7.12
#1 lore raw

PATCH 2/5 Input: wacom - handle split-sensor devices with internal hubs

Like our other pen-and-touch products, the Cintiq 24HD touch needs data to be shared between its two sensors to facilitate proximity-based palm rejection.

Unlike other tablets that report sensor data through separate interfaces of the same USB device, the Cintiq 24HD touch has separate USB devices that are connected to an internal USB hub.

This patch makes it possible to designate the USB VID/PID of the other device so that the two may share data. To ensure we don't accidentally link to a sensor from a physically separate device (if several have been plugged in), we limit the search to siblings (i.e., devices directly connected to the same hub).

---
 drivers/input/tablet/wacom_sys.c | 31 ++++++++++++++++++++++++++++++-
 drivers/input/tablet/wacom_wac.c |  3 ++-
 drivers/input/tablet/wacom_wac.h |  2 ++
 3 files changed, 34 insertions(+), 2 deletions(-)
drivers/input/tablet/wacom_sys.c +30 -1
index 0d3219f..d67a996 100644
@@ -546,6 +546,29 @@ struct wacom_usbdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
+static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+{
+	struct usb_device **sibling;
+
+	if (vendor == 0 && product == 0)
+		return dev;
+
+	if (dev->parent == NULL)
+		return NULL;
+
+	sibling = dev->parent->children;
+	while (sibling != NULL && *sibling != NULL) {
+		struct usb_device_descriptor d = (*sibling)->descriptor;
+
+		if (d.idVendor == vendor && d.idProduct == product)
+			return *sibling;
+
+		sibling++;
+	}
+
+	return NULL;
+}
+
 static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
 {
 	struct wacom_usbdev_data *data;
@@ -1190,13 +1213,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
 	if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
+		struct usb_device *other_dev;
+
 		/* Append the device type to the name */
 		strlcat(wacom_wac->name,
 			features->device_type == BTN_TOOL_PEN ?
 				" Pen" : " Finger",
 			sizeof(wacom_wac->name));
 
-		error = wacom_add_shared_data(wacom_wac, dev);
+
+		other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
+		if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
+			other_dev = dev;
+		error = wacom_add_shared_data(wacom_wac, other_dev);
 		if (error)
 			goto fail3;
 	}
drivers/input/tablet/wacom_wac.c +2 -1
index a8bc6c9..9f52ba0 100644
@@ -1327,7 +1327,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
 	/* these device have multiple inputs */
 	if (features->type >= WIRELESS ||
-	    (features->type >= INTUOS5S && features->type <= INTUOS5L))
+	    (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
+	    (features->oVid && features->oPid))
 		features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
 	/* quirk for bamboo touch with 2 low res touches */
drivers/input/tablet/wacom_wac.h +2 -0
index 96c185c..3f926ec 100644
@@ -109,6 +109,8 @@ struct wacom_features {
 	int distance_fuzz;
 	unsigned quirks;
 	unsigned touch_max;
+	int oVid;
+	int oPid;
 };
 
 struct wacom_shared {
Signature · 1 line
1.7.12
#2 lore raw

PATCH 3/5 Input: wacom - Introduce wacom_fix_phy_from_hid

In reply to Jason Gerecke

The Cintiq 24HD touch cannot use wacom_set_phy_from_res to determine the physical size of the touch sensor since the pen and touch are on separate USB devices. The physical size is, however, provided in the HID descriptor, just scaled to a unit we don't use.

This patch introduces the function wacom_fix_phy_from_hid to let us make use of the unit and exponent data provided by HID to set the [xy]_phy variables to an appropriate value. This function relies on a trimmed-down version of hidinput_calc_abs_res from the hid-input.c.

---
 drivers/input/tablet/wacom_sys.c | 69 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
drivers/input/tablet/wacom_sys.c +69 -0
index d67a996..08ab0b0 100644
@@ -172,6 +172,74 @@ static void wacom_close(struct input_dev *dev)
 }
 
 /*
+ * Calculate the resolution of the X or Y axis, given appropriate HID data.
+ * This function is little more than hidinput_calc_abs_res stripped down.
+ */
+static int wacom_calc_hid_res(int logical_extents, int physical_extents,
+                              unsigned char unit, unsigned char exponent)
+{
+	int prev, unit_exponent;
+
+	/* Check if the extents are sane */
+	if (logical_extents <= 0 || physical_extents <= 0)
+		return 0;
+
+	/* Get signed value of nybble-sized twos-compliment exponent */
+	unit_exponent = exponent;
+	if (unit_exponent > 7)
+		unit_exponent -= 16;
+
+	/* Convert physical_extents to millimeters */
+	if (unit == 0x11) {		/* If centimeters */
+		unit_exponent += 1;
+	} else if (unit == 0x13) {	/* If inches */
+		prev = physical_extents;
+		physical_extents *= 254;
+		if (physical_extents < prev)
+			return 0;
+		unit_exponent -= 1;
+	} else {
+		return 0;
+	}
+
+	/* Apply negative unit exponent */
+	for (; unit_exponent < 0; unit_exponent++) {
+		prev = logical_extents;
+		logical_extents *= 10;
+		if (logical_extents < prev)
+			return 0;
+	}
+	/* Apply positive unit exponent */
+	for (; unit_exponent > 0; unit_exponent--) {
+		prev = physical_extents;
+		physical_extents *= 10;
+		if (physical_extents < prev)
+			return 0;
+	}
+
+	/* Calculate resolution */
+	return logical_extents / physical_extents;
+}
+
+/*
+ * The physical dimension specified by the HID descriptor is likely not in
+ * the "100th of a mm" units expected by wacom_calculate_touch_res. This
+ * function adjusts the value of [xy]_phy based on the unit and exponent
+ * provided by the HID descriptor. If an error occurs durring conversion
+ * (e.g. from the unit being left unspecified) [xy]_phy is not modified.
+ */
+static void wacom_fix_phy_from_hid(struct wacom_features *features)
+{
+	int xres = wacom_calc_hid_res(features->x_max, features->x_phy, features->unit, features->unitExpo);
+	int yres = wacom_calc_hid_res(features->y_max, features->y_phy, features->unit, features->unitExpo);
+
+	if (xres > 0 && yres > 0) {
+		features->x_phy = (100 * features->x_max) / xres;
+		features->y_phy = (100 * features->y_max) / yres;
+	}
+}
+
+/*
  * Static values for max X/Y and resolution of Pen interface is stored in
  * features. This mean physical size of active area can be computed.
  * This is useful to do when Pen and Touch have same active area of tablet.
@@ -531,6 +599,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
 	error = wacom_parse_hid(intf, hid_desc, features);
 	if (error)
 		goto out;
+	wacom_fix_phy_from_hid(features);
 
  out:
 	return error;
Signature · 1 line
1.7.12
#3 lore raw

PATCH 4/5 Input: wacom - Clean up wacom_query_tablet_data

In reply to Jason Gerecke

Rewrites this function to be easier to read and understand. The new function 'wacom_set_device_mode' now handles the grunt work of assembling the proper feature report, sending it to the device, and ensuring the setting "sticks".

---
 drivers/input/tablet/wacom_sys.c | 74 +++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 39 deletions(-)
drivers/input/tablet/wacom_sys.c +35 -39
index 08ab0b0..b34a92b 100644
@@ -500,56 +500,52 @@ static int wacom_parse_hid(struct usb_interface *intf,
 	return result;
 }
 
-static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
+static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode)
 {
 	unsigned char *rep_data;
-	int limit = 0, report_id = 2;
-	int error = -ENOMEM;
+	int error = -ENOMEM, limit = 0;
 
-	rep_data = kmalloc(4, GFP_KERNEL);
+	rep_data = kzalloc(length, GFP_KERNEL);
 	if (!rep_data)
 		return error;
 
-	/* ask to report Wacom data */
+	rep_data[0] = report_id;
+	rep_data[1] = mode;
+
+	do {
+		error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+		                         report_id, rep_data, length, 1);
+		if (error >= 0)
+			error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
+			                         report_id, rep_data, length, 1);
+	} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
+
+	kfree(rep_data);
+
+	return error < 0 ? error : 0;
+}
+
+/*
+ * Switch the tablet into its most-capable mode. Wacom tablets are
+ * typically configured to power-up in a mode which sends mouse-like
+ * reports to the OS. To get absolute position, pressure data, etc.
+ * from the tablet, it is necessary to switch the tablet out of this
+ * mode and into one which sends the full range of tablet data.
+ */
+static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
+{
 	if (features->device_type == BTN_TOOL_FINGER) {
-		/* if it is an MT Tablet PC touch */
 		if (features->type > TABLETPC) {
-			do {
-				rep_data[0] = 3;
-				rep_data[1] = 4;
-				rep_data[2] = 0;
-				rep_data[3] = 0;
-				report_id = 3;
-				error = wacom_set_report(intf,
-							 WAC_HID_FEATURE_REPORT,
-							 report_id,
-							 rep_data, 4, 1);
-				if (error >= 0)
-					error = wacom_get_report(intf,
-							WAC_HID_FEATURE_REPORT,
-							report_id,
-							rep_data, 4, 1);
-			} while ((error < 0 || rep_data[1] != 4) &&
-				 limit++ < WAC_MSG_RETRIES);
+			/* MT Tablet PC touch */
+			return wacom_set_device_mode(intf, 3, 4, 4);
+		}
+	} else if (features->device_type == BTN_TOOL_PEN) {
+		if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
+			return wacom_set_device_mode(intf, 2, 2, 2);
 		}
-	} else if (features->type <= BAMBOO_PT &&
-		   features->type != WIRELESS &&
-		   features->device_type == BTN_TOOL_PEN) {
-		do {
-			rep_data[0] = 2;
-			rep_data[1] = 2;
-			error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
-						 report_id, rep_data, 2, 1);
-			if (error >= 0)
-				error = wacom_get_report(intf,
-						WAC_HID_FEATURE_REPORT,
-						report_id, rep_data, 2, 1);
-		} while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
 	}
 
-	kfree(rep_data);
-
-	return error < 0 ? error : 0;
+	return 0;
 }
 
 static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
Signature · 1 line
1.7.12
#4 lore raw

PATCH 5/5 Input: wacom - Add touch sensor support for Cintiq 24HD touch

In reply to Jason Gerecke

Decode multitouch reports from the touch sensor of the Cintiq 24HD touch.

---
 drivers/input/tablet/wacom_sys.c | 19 ++++++++-
 drivers/input/tablet/wacom_wac.c | 84 +++++++++++++++++++++++++++++++++++++++-
 drivers/input/tablet/wacom_wac.h |  3 ++
 3 files changed, 103 insertions(+), 3 deletions(-)
drivers/input/tablet/wacom_sys.c +18 -1
index b34a92b..e99f33f 100644
@@ -389,7 +389,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
 						}
 
-						if (features->type == MTSCREEN)
+						if (features->type == MTSCREEN || WACOM_24HDT)
 							features->pktlen = WACOM_PKGLEN_MTOUCH;
 
 						if (features->type == BAMBOO_PT) {
@@ -400,6 +400,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
 							features->x_max =
 								get_unaligned_le16(&report[i + 8]);
 							i += 15;
+						} else if (features->type == WACOM_24HDT) {
+							features->x_max =
+								get_unaligned_le16(&report[i + 3]);
+							features->x_phy =
+								get_unaligned_le16(&report[i + 8]);
+							features->unit = report[i - 1];
+							features->unitExpo = report[i - 3];
+							i += 12;
 						} else {
 							features->x_max =
 								get_unaligned_le16(&report[i + 3]);
@@ -432,6 +440,12 @@ static int wacom_parse_hid(struct usb_interface *intf,
 							features->y_phy =
 								get_unaligned_le16(&report[i + 6]);
 							i += 7;
+						} else if (type == WACOM_24HDT) {
+							features->y_max =
+								get_unaligned_le16(&report[i + 3]);
+							features->y_phy =
+								get_unaligned_le16(&report[i - 2]);
+							i += 7;
 						} else if (type == BAMBOO_PT) {
 							features->y_phy =
 								get_unaligned_le16(&report[i + 3]);
@@ -539,6 +553,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
 			/* MT Tablet PC touch */
 			return wacom_set_device_mode(intf, 3, 4, 4);
 		}
+		else if (features->type == WACOM_24HDT) {
+			return wacom_set_device_mode(intf, 18, 3, 2);
+		}
 	} else if (features->device_type == BTN_TOOL_PEN) {
 		if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
 			return wacom_set_device_mode(intf, 2, 2, 2);
drivers/input/tablet/wacom_wac.c +82 -2

114 lines not on this page · raw message

drivers/input/tablet/wacom_wac.h +3 -0
index 3f926ec..345f1e7 100644
@@ -29,6 +29,7 @@
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET	11
+#define WACOM_BYTES_PER_24HDT_PACKET	14
 
 /* device IDs */
 #define STYLUS_DEVICE_ID	0x02
@@ -49,6 +50,7 @@
 #define WACOM_REPORT_TPCHID		15
 #define WACOM_REPORT_TPCST		16
 #define WACOM_REPORT_TPC1FGE		18
+#define WACOM_REPORT_24HDT		1
 
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT		0x0001
@@ -81,6 +83,7 @@ enum {
 	WACOM_MO,
 	WIRELESS,
 	BAMBOO_PT,
+	WACOM_24HDT,
 	TABLETPC,   /* add new TPC below */
 	TABLETPCE,
 	TABLETPC2FG,
Signature · 1 line
1.7.12
Tested-by on v1 1/5
#5 lore raw
In reply to Jason Gerecke
Quoted 6 lines · Jason Gerecke

The ability to set the proximity flag should apply to any device that has both pen and touch input. Rather than listing classes of devices known to meet this criteria, simply filter on the quirk defining all such devices.

Dmitry, do you have questions about this patchset and "input: wacom:
Report correct touch contact size for I5/Bamboo"? We hope they can be merged soon since we have more patches coming.

Thank you.

Ping

Quoted 29 lines
---
 drivers/input/tablet/wacom_wac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/input/tablet/wacom_wac.c +2 -3
index 532d067..a8bc6c9 100644
@@ -326,7 +326,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
-               if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+               if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = true;
 
                /* serial number of the tool */
@@ -414,7 +414,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
-               if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+               if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = false;
 
                /*
--

1.7.12

#6 lore raw
Quoted 10 lines · Ping Cheng
Quoted 6 lines · Jason Gerecke

The ability to set the proximity flag should apply to any device that has both pen and touch input. Rather than listing classes of devices known to meet this criteria, simply filter on the quirk defining all such devices.

Quoted 8 lines

Dmitry, do you have questions about this patchset and "input: wacom:
Report correct touch contact size for I5/Bamboo"? We hope they can be merged soon since we have more patches coming.

Thank you.

Ping

The 24HD touch patches from September 6th as well ("Input: wacom - Add touch sensor support for Cintiq 24HD touch"). I was hoping to get them accepted before yesterday's 3.7 merge window opened.

Jason

---
When you're rife with devastation / There's a simple explanation:
You're a toymaker's creation / Trapped inside a crystal ball. And whichever way he tilts it / Know that we must be resilient We won't let them break our spirits / As we sing our silly song.

Quoted 29 lines
Quoted 29 lines
---
 drivers/input/tablet/wacom_wac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/input/tablet/wacom_wac.c +2 -3
index 532d067..a8bc6c9 100644
@@ -326,7 +326,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
-               if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+               if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = true;
 
                /* serial number of the tool */
@@ -414,7 +414,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
-               if (features->type >= INTUOS5S && features->type <= INTUOS5L)
+               if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = false;
 
                /*
--

1.7.12

maintainer
#7 lore raw

Hi Jason,

Quoted 15 lines · Jason Gerecke
Quoted 14 lines · Ping Cheng
Quoted 6 lines · Jason Gerecke

The ability to set the proximity flag should apply to any device that has both pen and touch input. Rather than listing classes of devices known to meet this criteria, simply filter on the quirk defining all such devices.

Dmitry, do you have questions about this patchset and "input: wacom:
Report correct touch contact size for I5/Bamboo"? We hope they can be merged soon since we have more patches coming.

Quoted 8 lines
Quoted 4 lines

Thank you.

Ping

The 24HD touch patches from September 6th as well ("Input: wacom - Add touch sensor support for Cintiq 24HD touch"). I was hoping to get them accepted before yesterday's 3.7 merge window opened.

Could you please take a peek at my 'next' branch and see if anything wacom-related is missing?

Thanks!

Signature · 1 line
Dmitry
#8 lore raw
Quoted 27 lines · Dmitry Torokhov

Hi Jason,

Quoted 15 lines · Jason Gerecke
Quoted 14 lines · Ping Cheng
Quoted 6 lines · Jason Gerecke

The ability to set the proximity flag should apply to any device that has both pen and touch input. Rather than listing classes of devices known to meet this criteria, simply filter on the quirk defining all such devices.

Dmitry, do you have questions about this patchset and "input: wacom:
Report correct touch contact size for I5/Bamboo"? We hope they can be merged soon since we have more patches coming.

Quoted 8 lines
Quoted 4 lines

Thank you.

Ping

The 24HD touch patches from September 6th as well ("Input: wacom - Add touch sensor support for Cintiq 24HD touch"). I was hoping to get them accepted before yesterday's 3.7 merge window opened.

Quoted 7 lines

Could you please take a peek at my 'next' branch and see if anything wacom-related is missing?

Thanks!

--
Dmitry

That appears to be everything I had outstanding. I'll rewrite and resubmit the two Cintiq patches you had to drop due to merge issues.

Jason

---
When you're rife with devastation / There's a simple explanation:
You're a toymaker's creation / Trapped inside a crystal ball. And whichever way he tilts it / Know that we must be resilient We won't let them break our spirits / As we sing our silly song.