All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro
@ 2016-10-06 21:22 Jason Gerecke
  2016-10-06 21:22 ` [PATCH 01/19] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                   ` (21 more replies)
  0 siblings, 22 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom announced two new "MobileStudio Pro" tablets yesterday, a third
iteration of the Cintiq Companion line of mobile PCs which can double
as external pen displays.

Unlike Wacom's prior professional-grade devices, the HID descriptor for
the MobileStudio Pro includes a rudimentary (but standard!) "Digitizer"
application collection that is usable by the existing HID_GENERIC codepath.
Additionally, a second vendor-defined application collection exists which
fully defines reports that enable full tablet functionality. The numerous
vendor-defined usages are planned to be used in future professional devices
as well, allowing us to finally gain some of the same forward compatibility
benefits we've had for ISDv4 devices since 3.17.

 * Patches 1-3 perform some basic cleanups.

 * Patches 4-6 work on the operation of the driver for all HID_GENERIC
   devices, correcting minor issues and adding some missing features.

 * Patches 7-19 implement support for the vendor defined usages that
   are used in the MobileStudio Pro, and which are planned to be used
   in future professional devices as well.


Jiri: Could you let me know whether it would be possible to schedule
these for the currently-open 4.9 merge window?


Jason Gerecke (19):
  HID: wacom: Update vendor-defined usage names to better match
    standards
  HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more
    fields
  HID: wacom: Refactor button-to-key translation into function
  HID: wacom: Detect and correct descriptors missing
    HID_DG_BARRELSWITCH2
  HID: wacom: generic: Strip off excessive name prefixing
  HID: wacom: generic: Add support for height, tilt, and twist usages
  HID: wacom: generic: Support and use 'Custom HID' mode and usages
  HID: wacom: generic: Add support for vendor-defined "Distance" usage
  HID: wacom: generic: Add support for vendor-defined "Fingerwheel"
    usage
  HID: wacom: generic: Add support for vendor-defined "Sense" usage
  HID: wacom: Read and internally use corrected Intuos tool IDs
  HID: wacom: generic: Support tool ID and additional tool types
  HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
  HID: wacom: Fix sensor outbounds and redefine as offsets from each
    edge
  HID: wacom: generic: Add support for sensor offsets
  HID: wacom: generic: Introduce pad support
  HID: wacom: generic: Add support for battery status on pen and pad
    interfaces
  HID: wacom: generic: Extend pad support
  HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res

 drivers/hid/hid-input.c |   1 +
 drivers/hid/wacom_sys.c |  92 ++++++--
 drivers/hid/wacom_wac.c | 544 +++++++++++++++++++++++++++++++++++++++---------
 drivers/hid/wacom_wac.h |  73 ++++++-
 include/linux/hid.h     |   4 +
 5 files changed, 595 insertions(+), 119 deletions(-)

-- 
2.10.0


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 01/19] HID: wacom: Update vendor-defined usage names to better match standards
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 02/19] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Our loose use of "pen" and "digitizer" in the naming of several of our
vendor-defined usages may be a source of confusion given that the terms
have specific meaning within the HID specification. "Pen" specifically
refers to "an integrated display that allows the use of a stylus" (e.g.
something like a tablet PC or Cintiq) wheras "Digitizer" is a better
fit for opaque tablets like an Intuos.

While we're at it, go ahead and rename the definitions to make them more
distinct and better match up with the convention used by HID (e.g. the use
of '_UP_' for usage pages) and make them more distinct.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_sys.c | 12 ++++++------
 drivers/hid/wacom_wac.c |  2 +-
 drivers/hid/wacom_wac.h | 17 +++++++++--------
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 5e7a564..773fa11 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 
 	case HID_UP_DIGITIZER:
 		if (field->report->id == 0x0B &&
-		    (field->application == WACOM_G9_DIGITIZER ||
-		     field->application == WACOM_G11_DIGITIZER)) {
+		    (field->application == WACOM_HID_G9_PEN ||
+		     field->application == WACOM_HID_G11_PEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
 
-	case WACOM_G9_PAGE:
-	case WACOM_G11_PAGE:
+	case WACOM_HID_UP_G9:
+	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
-		    (field->application == WACOM_G9_TOUCHSCREEN ||
-		     field->application == WACOM_G11_TOUCHSCREEN)) {
+		    (field->application == WACOM_HID_G9_TOUCHSCREEN ||
+		     field->application == WACOM_HID_G11_TOUCHSCREEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index a48ed4e..e09830c 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2458,7 +2458,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 	/*
 	 * Raw Wacom-mode pen and touch events both come from interface
 	 * 0, whose HID descriptor has an application usage of 0xFF0D
-	 * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
+	 * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back
 	 * out through the HID_GENERIC device created for interface 1,
 	 * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
 	 */
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index de5d1ad..3592186 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -84,20 +84,21 @@
 #define WACOM_DEVICETYPE_WL_MONITOR     0x0008
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
-#define WACOM_VENDORDEFINED_PEN		0xff0d0001
-#define WACOM_G9_PAGE			0xff090000
-#define WACOM_G9_DIGITIZER		(WACOM_G9_PAGE | 0x02)
-#define WACOM_G9_TOUCHSCREEN		(WACOM_G9_PAGE | 0x11)
-#define WACOM_G11_PAGE			0xff110000
-#define WACOM_G11_DIGITIZER		(WACOM_G11_PAGE | 0x02)
-#define WACOM_G11_TOUCHSCREEN		(WACOM_G11_PAGE | 0x11)
+#define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_UP_G9                 0xff090000
+#define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
+#define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
+#define WACOM_HID_UP_G11                0xff110000
+#define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
+#define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
 
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_VENDORDEFINED_PEN))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
 				 ((f)->application == HID_DG_TOUCHSCREEN))
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 02/19] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
  2016-10-06 21:22 ` [PATCH 01/19] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 03/19] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

We've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN)
which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but
probably should be.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 3592186..472b0a7 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -98,10 +98,14 @@
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_HID_WD_DIGITIZER))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER) || \
+				 ((f)->application == WACOM_HID_G9_PEN) || \
+				 ((f)->application == WACOM_HID_G11_PEN))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
-				 ((f)->application == HID_DG_TOUCHSCREEN))
+				 ((f)->application == HID_DG_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G11_TOUCHSCREEN))
 
 enum {
 	PENPARTNER = 0,
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 03/19] HID: wacom: Refactor button-to-key translation into function
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
  2016-10-06 21:22 ` [PATCH 01/19] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  2016-10-06 21:22 ` [PATCH 02/19] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 04/19] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

This just centralizes the logic used in both wacom_setup_numbered_buttons
and wacom_report_numbered_buttons so that they don't drift out of sync.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index e09830c..a9f6d11 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2779,17 +2779,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
 	return 0;
 }
 
+static int wacom_numbered_button_to_key(int n)
+{
+	if (n < 10)
+		return BTN_0 + n;
+	else if (n < 16)
+		return BTN_A + (n-10);
+	else if (n < 18)
+		return BTN_BASE + (n-16);
+	else
+		return 0;
+}
+
 static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
 				int button_count)
 {
 	int i;
 
-	for (i = 0; i < button_count && i < 10; i++)
-		__set_bit(BTN_0 + i, input_dev->keybit);
-	for (i = 10; i < button_count && i < 16; i++)
-		__set_bit(BTN_A + (i-10), input_dev->keybit);
-	for (i = 16; i < button_count && i < 18; i++)
-		__set_bit(BTN_BASE + (i-16), input_dev->keybit);
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			__set_bit(key, input_dev->keybit);
+	}
 }
 
 static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group)
@@ -2891,12 +2903,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 	for (i = 0; i < wacom->led.count; i++)
 		wacom_update_led(wacom,  button_count, mask, i);
 
-	for (i = 0; i < button_count && i < 10; i++)
-		input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
-	for (i = 10; i < button_count && i < 16; i++)
-		input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
-	for (i = 16; i < button_count && i < 18; i++)
-		input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			input_report_key(input_dev, key, mask & (1 << i));
+	}
 }
 
 int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 04/19] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (2 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 03/19] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 05/19] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

ISDv4 devices have long supported reporting data from each of two barrel
switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized.
Prior to its adoption, ISDv4 devices would associate the bit indicating
the state of the second barrel switch with the "Undefined" 0x000D0000
usage. Although most such devices have explicit support, a few use the
HID_GENERIC codepath which ignores the "Undefined" usage.

This patch adds code which detects the presence of a pre-standard second
barrel switch and corrects the usage value so that the HID_GENERIC code
will declare its presence and report its state.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 773fa11..033cc03 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev,
 			features->touch_max = 1;
 	}
 
+	/*
+	 * ISDv4 devices which predate HID's adoption of the
+	 * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
+	 * position instead. We can accurately detect if a
+	 * usage with that value should be HID_DG_BARRELSWITCH2
+	 * based on the surrounding usages, which have remained
+	 * constant across generations.
+	 */
+	if (features->type == HID_GENERIC &&
+	    usage->hid == 0x000D0000 &&
+	    field->application == HID_DG_PEN &&
+	    field->physical == HID_DG_STYLUS) {
+		int i = usage->usage_index;
+
+		if (i-4 >= 0 && i+1 < field->maxusage &&
+		    field->usage[i-4].hid == HID_DG_TIPSWITCH &&
+		    field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
+		    field->usage[i-2].hid == HID_DG_ERASER &&
+		    field->usage[i-1].hid == HID_DG_INVERT &&
+		    field->usage[i+1].hid == HID_DG_INRANGE) {
+			usage->hid = HID_DG_BARRELSWITCH2;
+		}
+	}
+
 	switch (usage->hid) {
 	case HID_GD_X:
 		features->x_max = field->logical_maximum;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 05/19] HID: wacom: generic: Strip off excessive name prefixing
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (3 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 04/19] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 06/19] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The product name received from the string descriptor in the new MobileStudio
Pro line of tablets begins with "Wacom", which leads to unnecessary visual
noise in the device name when appended to the vendor name which also includes
"Wacom". Look for and fix cases like this.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_sys.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 033cc03..7b9bff2 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
 				/* shift everything including the terminator */
 				memmove(gap, gap+1, strlen(gap));
 			}
+
+			/* strip off excessive prefixing */
+			if (strstr(name, "Wacom Co.,Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co.,Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+			if (strstr(name, "Wacom Co., Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co., Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+
 			/* get rid of trailing whitespace */
 			if (name[strlen(name)-1] == ' ')
 				name[strlen(name)-1] = '\0';
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 06/19] HID: wacom: generic: Add support for height, tilt, and twist usages
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (4 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 05/19] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 07/19] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The HID standard defines usages that allow digitizers to report the pen's
height, tilt, and rotation and which are used by Wacom's new "MobileStudio
Pro" devices.

Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our
driver to report twist) to have linear units. To ensure it calculates a
resolution with the actually-angular units provided in the HID descriptor
we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ
axis instead.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++--
 include/linux/hid.h     |  3 +++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index a9f6d11..e2eae91 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 {
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	int resolution_code = code;
+
+	if (usage->hid == HID_DG_TWIST) {
+		resolution_code = ABS_RZ;
+	}
 
 	usage->type = type;
 	usage->code = code;
@@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	case EV_ABS:
 		input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
 		input_abs_set_res(input, code,
-				  hidinput_calc_abs_res(field, code));
+				  hidinput_calc_abs_res(field, resolution_code));
 		break;
 	case EV_KEY:
 		input_set_capability(input, EV_KEY, code);
@@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case HID_GD_Z:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
+		break;
 	case HID_DG_TIPPRESSURE:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
 		break;
@@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		wacom_map_usage(input, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
 		break;
+	case HID_DG_TILT_X:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
+		break;
+	case HID_DG_TILT_Y:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
+		break;
+	case HID_DG_TWIST:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		break;
 	case HID_DG_ERASER:
 	case HID_DG_TIPSWITCH:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
@@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 
-	/* checking which Tool / tip switch to send */
 	switch (usage->hid) {
+	case HID_GD_Z:
+		/*
+		 * HID_GD_Z "should increase as the control's position is
+		 * moved from high to low", while ABS_DISTANCE instead
+		 * increases in value as the tool moves from low to high.
+		 */
+		value = field->logical_maximum - value;
+		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
 		return 0;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 75b66ec..0c05b27 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -232,6 +232,9 @@ struct hid_item {
 #define HID_DG_TABLETFUNCTIONKEY	0x000d0039
 #define HID_DG_PROGRAMCHANGEKEY	0x000d003a
 #define HID_DG_INVERT		0x000d003c
+#define HID_DG_TILT_X		0x000d003d
+#define HID_DG_TILT_Y		0x000d003e
+#define HID_DG_TWIST		0x000d0041
 #define HID_DG_TIPSWITCH	0x000d0042
 #define HID_DG_TIPSWITCH2	0x000d0043
 #define HID_DG_BARRELSWITCH	0x000d0044
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 07/19] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (5 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 06/19] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 08/19] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom's new "MobileStudio Pro" tablets are the first devices in their
branded product line-up to include a usable HID descriptor for the pen
interface. Like prior branded products, the device can operate in one
of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the
first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is
subject to some restrictions -- most notably pressure being limited
to 2048 levels instead of 8192. To ensure tablets that include support
for Custom HID mode work optimally, we add support for its usages and
switch the device to Custom HID mode if possible.

The usages defined for Custom HID mode are often numerically similar to
their standard HID equivalents, allowing us to write a simple translation
function that takes arbitrary HID usages as input and which returns
the corresponding standard HID usage as output (if one exists). Switching
on this translated usage instead of the actual usage allows the existing
cases to apply to both modes of operation without having to explicitly
define every Custom HID usage.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_sys.c |  5 +++++
 drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------
 drivers/hid/wacom_wac.h |  3 +++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 7b9bff2..b2e2471 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 		}
 		break;
 
+	case WACOM_HID_WD_DATAMODE:
+		wacom->wacom_wac.mode_report = field->report->id;
+		wacom->wacom_wac.mode_value = 2;
+		break;
+
 	case WACOM_HID_UP_G9:
 	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index e2eae91..edc2c14 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 	return 0;
 }
 
+static int wacom_equivalent_usage(int usage)
+{
+	if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) {
+		int subpage = (usage & 0xFF00) << 8;
+		int subusage = (usage & 0xFF);
+
+		if (subpage == WACOM_HID_SP_DIGITIZER ||
+		    subpage == WACOM_HID_SP_DIGITIZERINFO) {
+			return usage;
+		}
+
+		if (subpage == HID_UP_UNDEFINED)
+			subpage = HID_UP_DIGITIZER;
+
+		return subpage | subusage;
+	}
+
+	return usage;
+}
+
 static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		struct hid_field *field, __u8 type, __u16 code, int fuzz)
 {
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
 	int resolution_code = code;
 
-	if (usage->hid == HID_DG_TWIST) {
+	if (equivalent_usage == HID_DG_TWIST) {
 		resolution_code = ABS_RZ;
 	}
 
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
 		break;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_Z:
 		/*
 		 * HID_GD_Z "should increase as the control's position is
@@ -1598,8 +1621,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
 	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->touch_input;
 	unsigned touch_max = wacom_wac->features.touch_max;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		features->last_slot_field = usage->hid;
 		if (touch_max == 1)
@@ -1687,8 +1711,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_wac->hid_data.x = value;
 		break;
@@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
 
 
 	if (usage->usage_index + 1 == field->report_count) {
-		if (usage->hid == wacom_wac->features.last_slot_field)
+		if (equivalent_usage == wacom_wac->features.last_slot_field)
 			wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
 	}
 
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 472b0a7..c82233d 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -85,7 +85,10 @@
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
 #define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_DIGITIZER          0x000d0000
+#define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
 #define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 08/19] HID: wacom: generic: Add support for vendor-defined "Distance" usage
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (6 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 07/19] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 09/19] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to
HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which
increases in value as the pen-to-surface distance is decreased, this usage
decreases. Treat this usage as a special case to ensure we don't invert the
scale to be ABS_DISTANCE compatible like we do for HID_GD_Z.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 4 +++-
 drivers/hid/wacom_wac.h | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index edc2c14..aa51684 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage)
 		int subusage = (usage & 0xFF);
 
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
-		    subpage == WACOM_HID_SP_DIGITIZERINFO) {
+		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
 
@@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case WACOM_HID_WD_DISTANCE:
 	case HID_GD_Z:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
 		break;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index c82233d..1ced6e4 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -88,6 +88,7 @@
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 09/19] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (7 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 08/19] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 10/19] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The airbrush fingerwheel does not have a usage that corresponds cleanly
with a standard HID usage, so we add explicit support for it via its
vendor-defined usage.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 3 +++
 drivers/hid/wacom_wac.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index aa51684..009c25d 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_FINGERWHEEL:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
 	}
 }
 
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 1ced6e4..18cae38 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -89,6 +89,7 @@
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 10/19] HID: wacom: generic: Add support for vendor-defined "Sense" usage
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (8 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 09/19] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 11/19] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom's professional tablets beginning with the Intuos4 are capable of
reporting an intermediate degree of proximity where the pen is no longer
close enough to communicate with ("in prox"), but still close enough to
be sensed ("in range"). This additional state is particularly useful for
performing palm rejection as it allows the driver to disable the touch
sensor while the pen is a greater distance from the tablet.

Like other professional tablets, the new MobileStudio Pro also reports
this intermeidate "in range" proximity state. Its descriptor assigns
usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would
translate this to the standard HID "Quality" usage, but since this has
a different meaning we have it explicitly ignore the usage and define
it ourselves as "Sense" (since "In Range" is already defined by the
HID standard and interpreted by our driver as meaning "in prox").

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++---
 drivers/hid/wacom_wac.h |  3 +++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 009c25d..0e8c99a 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)
 
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_SENSE ||
 		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
@@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
@@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_SENSE:
+		features->quirks |= WACOM_QUIRK_SENSE;
+		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+		break;
 	case WACOM_HID_WD_FINGERWHEEL:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
@@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
@@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
+		if (!(features->quirks & WACOM_QUIRK_SENSE))
+			wacom_wac->hid_data.sense_state = value;
 		return 0;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
@@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
 		return 0;
+	case WACOM_HID_WD_SENSE:
+		wacom_wac->hid_data.sense_state = value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
@@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	if (!usage->type || delay_pen_events(wacom_wac))
 		return 0;
 
+	/* send pen events only when the pen is in/entering/leaving proximity */
+	if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
+		return 0;
+
 	input_event(input, usage->type, usage->code, value);
 
 	return 0;
@@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 	bool prox = wacom_wac->hid_data.inrange_state;
+	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) /* first in prox */
 		/* Going into proximity select tool */
 		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
 						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
 	/* keep pen state for touch events */
-	wacom_wac->shared->stylus_in_proximity = prox;
+	wacom_wac->shared->stylus_in_proximity = range;
 
-	if (!delay_pen_events(wacom_wac)) {
+	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
@@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 
 		input_sync(input);
 	}
+
+	if (!prox)
+		wacom_wac->tool[0] = 0;
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 18cae38..e8779c7 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -74,6 +74,7 @@
 
 /* device quirks */
 #define WACOM_QUIRK_BBTOUCH_LOWRES	0x0001
+#define WACOM_QUIRK_SENSE		0x0002
 #define WACOM_QUIRK_BATTERY		0x0008
 
 /* device types */
@@ -88,6 +89,7 @@
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -213,6 +215,7 @@ struct wacom_shared {
 struct hid_data {
 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
+	bool sense_state;
 	bool inrange_state;
 	bool invert_state;
 	bool tipswitch;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 11/19] HID: wacom: Read and internally use corrected Intuos tool IDs
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (9 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 10/19] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 12/19] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the
proximity report, shifting the higher values of the ID four bits farther
than intended. This problem was not detected until too late, but has not
caused any issues since the incorrect IDs still fit in a 32-bit integer
and userspace programs have not required the value to match the hardware
(just that the values are unique and constant).

The tool IDs reported by the new MobileStudio Pro (or any future
HID_GENERIC device that supports them) do not suffer from the same
assembly issue, however. In order for 'wacom_intuos_get_tool_type' to
work for with both codepaths, we correct this issue internally and
have 'wacom_intuos_general' only mangle the ID when it is posted to
userspace.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 0e8c99a..60f065b 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
 	return 1;
 }
 
+static int wacom_intuos_id_mangle(int tool_id)
+{
+	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
+}
+
 static int wacom_intuos_get_tool_type(int tool_id)
 {
 	int tool_type;
@@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	switch (tool_id) {
 	case 0x812: /* Inking pen */
 	case 0x801: /* Intuos3 Inking pen */
-	case 0x120802: /* Intuos4/5 Inking Pen */
+	case 0x12802: /* Intuos4/5 Inking Pen */
 	case 0x012:
 		tool_type = BTN_TOOL_PENCIL;
 		break;
@@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
 	case 0x8e2: /* IntuosHT2 pen */
 	case 0x022:
-	case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
-	case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
-	case 0x160802: /* Cintiq 13HD Pro Pen */
-	case 0x180802: /* DTH2242 Pen */
-	case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
+	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+	case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
+	case 0x16802: /* Cintiq 13HD Pro Pen */
+	case 0x18802: /* DTH2242 Pen */
+	case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
 		tool_type = BTN_TOOL_PEN;
 		break;
 
@@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
 	case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 	case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
-	case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
-	case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
-	case 0x18080a: /* DTH2242 Eraser */
-	case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
+	case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
+	case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
+	case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
+	case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
+	case 0x1880a: /* DTH2242 Eraser */
+	case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 		tool_type = BTN_TOOL_RUBBER;
 		break;
 
@@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x112:
 	case 0x913: /* Intuos3 Airbrush */
 	case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
-	case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
+	case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
 		tool_type = BTN_TOOL_AIRBRUSH;
 		break;
 
@@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 			(data[6] << 4) + (data[7] >> 4);
 
 		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
-			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
+		     ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8);
 
 		wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);
 
@@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
 	 * don't report events for invalid data
 	 */
 	/* older I4 styli don't work with new Cintiqs */
-	if ((!((wacom->id[idx] >> 20) & 0x01) &&
+	if ((!((wacom->id[idx] >> 16) & 0x01) &&
 			(features->type == WACOM_21UX2)) ||
 	    /* Only large Intuos support Lense Cursor */
 	    (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
 		break;
 	}
 
-	input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
+	input_report_abs(input, ABS_MISC,
+			 wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */
 	input_report_key(input, wacom->tool[idx], 1);
 	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 	wacom->reporting_data = true;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 12/19] HID: wacom: generic: Support tool ID and additional tool types
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (10 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 11/19] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage' Jason Gerecke
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Devices following the new Custom HID mode specification (as well as even
some recent component sensors which use the same standard HID usage)
are capable of reporting tool ID information that we need to relay to
userspace. This patch adds support for reading and relaying the tool
type information, which is (unfortunately) split across two usages.
We also advertise the existence of tool types beyond BTN_TOOL_PEN
that might be available.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++---
 drivers/hid/wacom_wac.h |  4 ++-
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 60f065b..f2aadc4 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage)
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
 		    usage == WACOM_HID_WD_SENSE ||
+		    usage == WACOM_HID_WD_SERIALHI ||
+		    usage == WACOM_HID_WD_TOOLTYPE ||
 		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
@@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		features->quirks |= WACOM_QUIRK_SENSE;
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
+		set_bit(EV_KEY, input->evbit);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
+		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
+		input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
+		input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
+		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
+		break;
 	case WACOM_HID_WD_FINGERWHEEL:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
@@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
 		return 0;
+	case HID_DG_TOOLSERIALNUMBER:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFF);
+		wacom_wac->serial[0] |= value;
+		return 0;
 	case WACOM_HID_WD_SENSE:
 		wacom_wac->hid_data.sense_state = value;
 		return 0;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
+		wacom_wac->serial[0] |= ((__u64)value) << 32;
+		/*
+		 * Non-USI EMR devices may contain additional tool type
+		 * information here. See WACOM_HID_WD_TOOLTYPE case for
+		 * more details.
+		 */
+		if (value >> 20 == 1) {
+			wacom_wac->id[0] |= value & 0xFFFFF;
+		}
+		return 0;
+	case WACOM_HID_WD_TOOLTYPE:
+		/*
+		 * Some devices (MobileStudio Pro, and possibly later
+		 * devices as well) do not return the complete tool
+		 * type in their WACOM_HID_WD_TOOLTYPE usage. Use a
+		 * bitwise OR so the complete value can be built
+		 * up over time :(
+		 */
+		wacom_wac->id[0] |= value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
@@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 	bool prox = wacom_wac->hid_data.inrange_state;
 	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->tool[0] && prox) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) { /* first in prox */
 		/* Going into proximity select tool */
-		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
-						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		if (wacom_wac->hid_data.invert_state)
+			wacom_wac->tool[0] = BTN_TOOL_RUBBER;
+		else if (wacom_wac->id[0])
+			wacom_wac->tool[0] = wacom_intuos_get_tool_type(wacom_wac->id[0]);
+		else
+			wacom_wac->tool[0] = BTN_TOOL_PEN;
+	}
 
 	/* keep pen state for touch events */
 	wacom_wac->shared->stylus_in_proximity = range;
 
 	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
+		int id = wacom_wac->id[0];
+
+		/*
+		 * Non-USI EMR tools should have their IDs mangled to
+		 * match the legacy behavior of wacom_intuos_general
+		 */
+		if (wacom_wac->serial[0] >> 52 == 1)
+			id = wacom_intuos_id_mangle(id);
+
+		/*
+		 * To ensure compatibility with xf86-input-wacom, we should
+		 * report the BTN_TOOL_* event prior to the ABS_MISC or
+		 * MSC_SERIAL events.
+		 */
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
+		if (wacom_wac->serial[0]) {
+			input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+			input_report_abs(input, ABS_MISC, id);
+		}
 
 		wacom_wac->hid_data.tipswitch = false;
 
 		input_sync(input);
 	}
 
-	if (!prox)
+	if (!prox) {
 		wacom_wac->tool[0] = 0;
+		wacom_wac->id[0] = 0;
+	}
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index e8779c7..3926ff4 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -90,6 +90,8 @@
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
+#define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -247,7 +249,7 @@ struct wacom_wac {
 	unsigned char data[WACOM_PKGLEN_MAX];
 	int tool[2];
 	int id[2];
-	__u32 serial[2];
+	__u64 serial[2];
 	bool reporting_data;
 	struct wacom_features features;
 	struct wacom_shared *shared;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (11 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 12/19] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-07 15:46   ` Benjamin Tissoires
  2016-10-06 21:22 ` [PATCH 14/19] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

In the following "Add support for sensor offsets" patch we'll need access
to the 'features' struct within 'wacom_map_usage', so update the function
signature and calls to include a reference to the HID device so this can
be done.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 53 ++++++++++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 25 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index f2aadc4..8f493cc 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1465,9 +1465,12 @@ static int wacom_equivalent_usage(int usage)
 	return usage;
 }
 
-static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
-		struct hid_field *field, __u8 type, __u16 code, int fuzz)
+static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
+		struct hid_usage *usage, struct hid_field *field, __u8 type,
+		__u16 code, int fuzz)
 {
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
 	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
@@ -1508,53 +1511,53 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 
 	switch (equivalent_usage) {
 	case HID_GD_X:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 4);
 		break;
 	case HID_GD_Y:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 4);
 		break;
 	case WACOM_HID_WD_DISTANCE:
 	case HID_GD_Z:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_DISTANCE, 0);
 		break;
 	case HID_DG_TIPPRESSURE:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_PRESSURE, 0);
 		break;
 	case HID_DG_INRANGE:
-		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
 	case HID_DG_INVERT:
-		wacom_map_usage(input, usage, field, EV_KEY,
+		wacom_map_usage(input, hdev, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
 		break;
 	case HID_DG_TILT_X:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_TILT_X, 0);
 		break;
 	case HID_DG_TILT_Y:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_TILT_Y, 0);
 		break;
 	case HID_DG_TWIST:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Z, 0);
 		break;
 	case HID_DG_ERASER:
 	case HID_DG_TIPSWITCH:
-		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOUCH, 0);
 		break;
 	case HID_DG_BARRELSWITCH:
-		wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_STYLUS, 0);
 		break;
 	case HID_DG_BARRELSWITCH2:
-		wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_STYLUS2, 0);
 		break;
 	case HID_DG_TOOLSERIALNUMBER:
-		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
 	case WACOM_HID_WD_SENSE:
 		features->quirks |= WACOM_QUIRK_SENSE;
-		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
 	case WACOM_HID_WD_SERIALHI:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MISC, 0);
 		set_bit(EV_KEY, input->evbit);
 		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
 		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
@@ -1565,7 +1568,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
 		break;
 	case WACOM_HID_WD_FINGERWHEEL:
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
 	}
 }
@@ -1722,24 +1725,24 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
 	case HID_GD_X:
 		features->last_slot_field = usage->hid;
 		if (touch_max == 1)
-			wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
+			wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 4);
 		else
-			wacom_map_usage(input, usage, field, EV_ABS,
+			wacom_map_usage(input, hdev, usage, field, EV_ABS,
 					ABS_MT_POSITION_X, 4);
 		break;
 	case HID_GD_Y:
 		features->last_slot_field = usage->hid;
 		if (touch_max == 1)
-			wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
+			wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 4);
 		else
-			wacom_map_usage(input, usage, field, EV_ABS,
+			wacom_map_usage(input, hdev, usage, field, EV_ABS,
 					ABS_MT_POSITION_Y, 4);
 		break;
 	case HID_DG_WIDTH:
 	case HID_DG_HEIGHT:
 		features->last_slot_field = usage->hid;
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
-		wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
 		input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
 		break;
 	case HID_DG_CONTACTID:
@@ -1753,7 +1756,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
 		break;
 	case HID_DG_TIPSWITCH:
 		features->last_slot_field = usage->hid;
-		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
+		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOUCH, 0);
 		break;
 	case HID_DG_CONTACTCOUNT:
 		wacom_wac->hid_data.cc_report = field->report->id;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 14/19] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (12 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage' Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 15/19] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Many of Wacom's display tablets include an "outbound" area where pen
digitizing is possible but outside of the display area. To ensure that
pen coordinates are mapped to the correct on-screen location, the driver
sets the minimum and maximum axis values of X and Y to those coordinates
which coincide with the screen edge. These values are simply the
hardware minimum/maximum plus/minus the outbound size for a particular
edge.

When outbound support was added/updated in ac414da, fa77034, and
ecd618d, we decided to have the wacom_features structs store the desired
minimum and maximum values directly. In hindsight, this was perhaps not
the best choice since it has allowed minor errors to crop up unnoticed.
Some tablets have had their coordinates over-corrected (e.g. most of the
devices "fixed" in ecd618d were already adjusted in ac414da), while
others never had a correction applied (e.g. the ISDv5 325, whose
declared maximum the hardware maximum instead of the outbound maximum).

A less error-prone method of handling the outbound is to let the driver
calculate the correct minimum/maximum values by providing it with both
the actual hardware maximums and the size of the outbound on each edge.
These values are more easy to verify as correct since the values can be
trivially compared against specifications.

This patch reverts the declared maximum values to the actual hardware
maximums, e.g. as declared prior to ac414da (values for these and other
display tablets that were subsuquently introduced have been verified
against specs). Per-edge outbound sizes are stored in the wacom_features
struct as offset_{left,right,top,bottom} and used in combination with
the hardware ranges to calculate effective axis ranges for ABS_X and
ABS_Y.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++-----------------
 drivers/hid/wacom_wac.h |  6 +++--
 2 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 8f493cc..c8b5bb9 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2687,10 +2687,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(ABS_MISC, input_dev->absbit);
 
-	input_set_abs_params(input_dev, ABS_X, features->x_min,
-			     features->x_max, features->x_fuzz, 0);
-	input_set_abs_params(input_dev, ABS_Y, features->y_min,
-			     features->y_max, features->y_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_X, 0 + features->offset_left,
+			     features->x_max - features->offset_right,
+			     features->x_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0 + features->offset_top,
+			     features->y_max - features->offset_bottom,
+			     features->y_fuzz, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0,
 		features->pressure_max, features->pressure_fuzz, 0);
 
@@ -3402,26 +3404,30 @@ static const struct wacom_features wacom_features_0x317 =
 	  INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xF4 =
-	{ "Wacom Cintiq 24HD", 104080, 65200, 2047, 63,
+	{ "Wacom Cintiq 24HD", 104480, 65600, 2047, 63,
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xF8 =
-	{ "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */
+	{ "Wacom Cintiq 24HD touch", 104480, 65600, 2047, 63, /* Pen */
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
 static const struct wacom_features wacom_features_0xF6 =
 	{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x32A =
-	{ "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x32B =
-	{ "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD touch", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
 static const struct wacom_features wacom_features_0x32C =
 	{ "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT,
@@ -3436,13 +3442,15 @@ static const struct wacom_features wacom_features_0xC6 =
 	{ "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
 	  WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
 static const struct wacom_features wacom_features_0x304 =
-	{ "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
+	{ "Wacom Cintiq 13HD", 59552, 33848, 1023, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x333 =
-	{ "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
+	{ "Wacom Cintiq 13HD touch", 59552, 33848, 2047, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
 static const struct wacom_features wacom_features_0x335 =
 	{ "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3459,42 +3467,50 @@ static const struct wacom_features wacom_features_0xF0 =
 	{ "Wacom DTU1631", 34623, 19553, 511, 0,
 	  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xFB =
-	{ "Wacom DTU1031", 21896, 13760, 511, 0,
+	{ "Wacom DTU1031", 22096, 13960, 511, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x32F =
-	{ "Wacom DTU1031X", 22472, 12728, 511, 0,
+	{ "Wacom DTU1031X", 22672, 12928, 511, 0,
 	  DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x336 =
-	{ "Wacom DTU1141", 23472, 13203, 1023, 0,
+	{ "Wacom DTU1141", 23672, 13403, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x57 =
-	{ "Wacom DTK2241", 95640, 54060, 2047, 63,
+	{ "Wacom DTK2241", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x59 = /* Pen */
-	{ "Wacom DTH2242", 95640, 54060, 2047, 63,
+	{ "Wacom DTH2242", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
 static const struct wacom_features wacom_features_0x5D = /* Touch */
 	{ "Wacom DTH2242",       .type = WACOM_24HDT,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xCC =
-	{ "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63,
+	{ "Wacom Cintiq 21UX2", 87200, 65600, 2047, 63,
 	  WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xFA =
-	{ "Wacom Cintiq 22HD", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HD", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x5B =
-	{ "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HDT", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
 static const struct wacom_features wacom_features_0x5E =
 	{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3638,18 +3654,20 @@ static const struct wacom_features wacom_features_0x6004 =
 	{ "ISD-V4", 12800, 8000, 255, 0,
 	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x307 =
-	{ "Wacom ISDv5 307", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 307", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
 static const struct wacom_features wacom_features_0x309 =
 	{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x30A =
-	{ "Wacom ISDv5 30A", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 30A", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
 static const struct wacom_features wacom_features_0x30C =
 	{ "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3665,6 +3683,7 @@ static const struct wacom_features wacom_features_0x325 =
 	{ "Wacom ISDv5 325", 59552, 33848, 2047, 63,
 	  CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };
 static const struct wacom_features wacom_features_0x326 = /* Touch */
 	{ "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3694,8 +3713,9 @@ static const struct wacom_features wacom_features_0x33E =
 	  INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x343 =
-	{ "Wacom DTK1651", 34616, 19559, 1023, 0,
+	{ "Wacom DTK1651", 34816, 19759, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 3926ff4..81ae478 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -181,8 +181,10 @@ struct wacom_features {
 	int x_resolution;
 	int y_resolution;
 	int numbered_buttons;
-	int x_min;
-	int y_min;
+	int offset_left;
+	int offset_right;
+	int offset_top;
+	int offset_bottom;
 	int device_type;
 	int x_phy;
 	int y_phy;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 15/19] HID: wacom: generic: Add support for sensor offsets
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (13 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 14/19] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 16/19] HID: wacom: generic: Introduce pad support Jason Gerecke
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Many of Wacom's display tablets include an "outbound" area where pen
digitizing is possible but outside of the display area. To accommodate
such sensors in the HID_GENERIC codepath, we add support for the
necessary vendor-defined HID feature usages and adjust the min/max
values of the X and Y axes accordingly, similar to what is done in
the non-generic codepath.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++--------
 drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/hid/wacom_wac.h |  4 ++++
 3 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index b2e2471..b9779bc 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 	struct hid_data *hid_data = &wacom->wacom_wac.hid_data;
 	u8 *data;
 	int ret;
+	int n;
 
 	switch (usage->hid) {
 	case HID_DG_CONTACTMAX:
@@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
+	case WACOM_HID_WD_OFFSETLEFT:
+	case WACOM_HID_WD_OFFSETTOP:
+	case WACOM_HID_WD_OFFSETRIGHT:
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		/* read manually */
+		n = hid_report_len(field->report);
+		data = hid_alloc_report_buf(field->report, GFP_KERNEL);
+		if (!data)
+			break;
+		data[0] = field->report->id;
+		ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
+					data, n, WAC_CMD_RETRIES);
+		if (ret == n) {
+			ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+						   data, n, 0);
+		} else {
+			hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+				 __func__);
+		}
+		kfree(data);
+		break;
 	}
 }
 
@@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)
 		return retval;
 	}
 
-	if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
-		wacom_wac->shared->touch = hdev;
-	else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
-		wacom_wac->shared->pen = hdev;
-
 out:
 	mutex_unlock(&wacom_udev_list_lock);
 	return retval;
@@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 	if (error)
 		goto fail;
 
+	error = wacom_add_shared_data(hdev);
+	if (error)
+		goto fail;
+
 	/*
 	 * Bamboo Pad has a generic hid handling for the Pen, and we switch it
 	 * into debug mode for the touch part.
@@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 
 	wacom_update_name(wacom, wireless ? " (WL)" : "");
 
-	error = wacom_add_shared_data(hdev);
-	if (error)
-		goto fail;
+	if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
+		wacom_wac->shared->touch = hdev;
+	else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
+		wacom_wac->shared->pen = hdev;
 
 	if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
 	     (features->quirks & WACOM_QUIRK_BATTERY)) {
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index c8b5bb9..1baa8b9 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1471,6 +1471,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
 	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
@@ -1480,6 +1481,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
 		resolution_code = ABS_RZ;
 	}
 
+	if (equivalent_usage == HID_GD_X) {
+		fmin += features->offset_left;
+		fmax -= features->offset_right;
+	}
+	if (equivalent_usage == HID_GD_Y) {
+		fmin += features->offset_top;
+		fmax -= features->offset_bottom;
+	}
+
 	usage->type = type;
 	usage->code = code;
 
@@ -1632,6 +1642,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		 */
 		wacom_wac->id[0] |= value;
 		return 0;
+	case WACOM_HID_WD_OFFSETLEFT:
+		if (features->offset_left && value != features->offset_left)
+			hid_warn(hdev, "%s: overriding exising left offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_left);
+		features->offset_left = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETRIGHT:
+		if (features->offset_right && value != features->offset_right)
+			hid_warn(hdev, "%s: overriding exising right offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_right);
+		features->offset_right = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETTOP:
+		if (features->offset_top && value != features->offset_top)
+			hid_warn(hdev, "%s: overriding exising top offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_top);
+		features->offset_top = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		if (features->offset_bottom && value != features->offset_bottom)
+			hid_warn(hdev, "%s: overriding exising bottom offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_bottom);
+		features->offset_bottom = value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 81ae478..93df1de 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -94,6 +94,10 @@
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
+#define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
+#define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
+#define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
+#define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 16/19] HID: wacom: generic: Introduce pad support
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (14 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 15/19] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 17/19] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

As with usages for the pen, the Custom HID specificiation includes
usages for the pad. Here we add functions to map and handle most
of the pad usages present on the MobileStudio Pro.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------
 drivers/hid/wacom_wac.h |  19 +++++++
 2 files changed, 146 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 1baa8b9..81b4b99 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");
 static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 				int button_count, int mask);
 
+static int wacom_numbered_button_to_key(int n);
+
 /*
  * Percent of battery capacity for Graphire.
  * 8th value means AC online and show 100% capacity.
@@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage)
 		int subpage = (usage & 0xFF00) << 8;
 		int subusage = (usage & 0xFF);
 
-		if (subpage == WACOM_HID_SP_DIGITIZER ||
+		if (subpage == WACOM_HID_SP_PAD ||
+		    subpage == WACOM_HID_SP_BUTTON ||
+		    subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
 		    usage == WACOM_HID_WD_SENSE ||
 		    usage == WACOM_HID_WD_SERIALHI ||
 		    usage == WACOM_HID_WD_TOOLTYPE ||
-		    usage == WACOM_HID_WD_DISTANCE) {
+		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHRING ||
+		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
 			return usage;
 		}
 
@@ -1510,6 +1516,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
 	}
 }
 
+static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_ACCELEROMETER_X:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 0);
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Y:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 0);
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Z:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Z, 0);
+		break;
+	case WACOM_HID_WD_BUTTONHOME:
+	case WACOM_HID_WD_BUTTONUP:
+	case WACOM_HID_WD_BUTTONDOWN:
+	case WACOM_HID_WD_BUTTONLEFT:
+	case WACOM_HID_WD_BUTTONRIGHT:
+		wacom_map_usage(input, hdev, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		break;
+	case WACOM_HID_WD_TOUCHRING:
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
+	}
+
+	switch (equivalent_usage & 0xfffffff0) {
+	case WACOM_HID_WD_EXPRESSKEY00:
+		wacom_map_usage(input, hdev, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		break;
+	}
+}
+
+static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) {
+		wacom_wac->hid_data.inrange_state |= value;
+	}
+
+	if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS)
+		input_event(input, usage->type, usage->code, value);
+
+	return 0;
+}
+
+static void wacom_wac_pad_pre_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+	wacom_wac->hid_data.inrange_state = 0;
+}
+
+static void wacom_wac_pad_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	bool active = wacom_wac->hid_data.inrange_state != 0;
+
+	/*
+	 * don't report prox for events like accelerometer
+	 * or battery status
+	 */
+	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY)
+		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
+
+	input_sync(input);
+}
+
 static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
@@ -1957,10 +2055,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,
 	/* currently, only direct devices have proper hid report descriptors */
 	features->device_type |= WACOM_DEVICETYPE_DIRECT;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_usage_mapping(hdev, field, usage);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_usage_mapping(hdev, field, usage);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_usage_mapping(hdev, field, usage);
 }
 
@@ -1972,10 +2071,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
 	if (wacom->wacom_wac.features.type != HID_GENERIC)
 		return 0;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_event(hdev, field, usage, value);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_event(hdev, field, usage, value);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_event(hdev, field, usage, value);
 
 	return 0;
@@ -2009,18 +2109,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
 	if (wacom_wac->features.type != HID_GENERIC)
 		return;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		wacom_wac_pad_pre_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field))
 		wacom_wac_pen_pre_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		wacom_wac_finger_pre_report(hdev, report);
 
 	wacom_report_events(hdev, report);
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_report(hdev, report);
 }
 
@@ -2594,6 +2696,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 	struct wacom_features *features = &wacom->wacom_wac.features;
 
 	/* The pen and pad share the same interface on most devices */
+	if (features->numbered_buttons > 0)
+		features->device_type |= WACOM_DEVICETYPE_PAD;
 	if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 ||
 	    features->type == DTUS ||
 	    (features->type >= INTUOS3S && features->type <= WACOM_MO)) {
@@ -3115,8 +3219,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 	__set_bit(ABS_MISC, input_dev->absbit);
 
 	/* kept for making legacy xf86-input-wacom accepting the pad */
-	input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum ||
+	      input_dev->absinfo[ABS_X].maximum)))
+		input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum ||
+	      input_dev->absinfo[ABS_Y].maximum)))
+		input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
 
 	/* kept for making udev and libwacom accepting the pad */
 	__set_bit(BTN_STYLUS, input_dev->keybit);
@@ -3236,6 +3344,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
 		break;
 
+	case HID_GENERIC:
+		break;
+
 	default:
 		/* no pad supported */
 		return -ENODEV;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 93df1de..0c69c1f 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -86,19 +86,34 @@
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
 #define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_PAD                0x00040000
+#define WACOM_HID_SP_BUTTON             0x00090000
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_DIGITIZERFNKEYS    (WACOM_HID_UP_WACOMDIGITIZER | 0x39)
 #define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
+#define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
+#define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
+#define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
+#define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
+#define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
+#define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
+#define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
+#define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
 #define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
 #define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
 #define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
+#define WACOM_HID_WD_DIGITIZERINFO      (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
 #define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
@@ -106,6 +121,10 @@
 #define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
 #define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
 
+#define WACOM_PAD_FIELD(f)	(((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERINFO))
+
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 17/19] HID: wacom: generic: Add support for battery status on pen and pad interfaces
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (15 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 16/19] HID: wacom: generic: Introduce pad support Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 18/19] HID: wacom: generic: Extend pad support Jason Gerecke
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Adds support for usages that may appear on the pen or pad interface which
report the state of the tablet battery.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 drivers/hid/wacom_wac.h |  6 ++++++
 include/linux/hid.h     |  1 +
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 81b4b99..f75ffae 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1526,6 +1526,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
 	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case WACOM_HID_WD_ACCELEROMETER_X:
 		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
 		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 0);
@@ -1575,8 +1579,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
 		wacom_wac->hid_data.inrange_state |= value;
 	}
 
-	if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS)
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		return 0;
+
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		wacom_wac->hid_data.bat_charging = value;
+		wacom_wac->hid_data.ps_connected = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		return 0;
+
+	case WACOM_HID_WD_TOUCHRINGSTATUS:
+		return 0;
+
+	default:
 		input_event(input, usage->type, usage->code, value);
+		break;
+	}
 
 	return 0;
 }
@@ -1595,6 +1616,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pad_input;
 	bool active = wacom_wac->hid_data.inrange_state != 0;
 
@@ -1605,6 +1627,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
 	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY)
 		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
 
+	if (features->quirks & WACOM_QUIRK_BATTERY) {
+		int capacity = wacom_wac->hid_data.battery_capacity;
+		bool charging = wacom_wac->hid_data.bat_charging;
+		bool connected = wacom_wac->hid_data.bat_connected;
+		bool powered = wacom_wac->hid_data.ps_connected;
+
+		wacom_notify_battery(wacom_wac, capacity, charging,
+				     connected, powered);
+	}
+
 	input_sync(input);
 }
 
@@ -1634,6 +1666,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_INRANGE:
 		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case HID_DG_BATTERYSTRENGTH:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case HID_DG_INVERT:
 		wacom_map_usage(input, hdev, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
@@ -1704,6 +1739,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		if (!(features->quirks & WACOM_QUIRK_SENSE))
 			wacom_wac->hid_data.sense_state = value;
 		return 0;
+	case HID_DG_BATTERYSTRENGTH:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		break;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
 		return 0;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 0c69c1f..fa5b772 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -101,6 +101,8 @@
 #define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
 #define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
 #define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
+#define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
 #define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
 #define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
@@ -257,6 +259,10 @@ struct hid_data {
 	int cc_value_index;
 	int num_expected;
 	int num_received;
+	int battery_capacity;
+	int bat_charging;
+	int bat_connected;
+	int ps_connected;
 };
 
 struct wacom_remote_data {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0c05b27..021da44 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -231,6 +231,7 @@ struct hid_item {
 #define HID_DG_TAP		0x000d0035
 #define HID_DG_TABLETFUNCTIONKEY	0x000d0039
 #define HID_DG_PROGRAMCHANGEKEY	0x000d003a
+#define HID_DG_BATTERYSTRENGTH	0x000d003b
 #define HID_DG_INVERT		0x000d003c
 #define HID_DG_TILT_X		0x000d003d
 #define HID_DG_TILT_Y		0x000d003e
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 18/19] HID: wacom: generic: Extend pad support
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (16 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 17/19] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-06 21:22 ` [PATCH 19/19] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The HID specification that the MobileStudio Pro follows includes usages
for several values that would be good to support so that future devices
"just work" out of the box. Extend the HID_GENERIC pad codepath to handle
these usages.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 15 +++++++++++++++
 drivers/hid/wacom_wac.h |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index f75ffae..4f449a0 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage)
 		    usage == WACOM_HID_WD_SERIALHI ||
 		    usage == WACOM_HID_WD_TOOLTYPE ||
 		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP2 ||
 		    usage == WACOM_HID_WD_TOUCHRING ||
 		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
 			return usage;
@@ -1513,6 +1515,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
 	case EV_MSC:
 		input_set_capability(input, EV_MSC, code);
 		break;
+	case EV_SW:
+		input_set_capability(input, EV_SW, code);
+		break;
 	}
 }
 
@@ -1547,11 +1552,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 	case WACOM_HID_WD_BUTTONDOWN:
 	case WACOM_HID_WD_BUTTONLEFT:
 	case WACOM_HID_WD_BUTTONRIGHT:
+	case WACOM_HID_WD_BUTTONCENTER:
 		wacom_map_usage(input, hdev, usage, field, EV_KEY,
 				wacom_numbered_button_to_key(features->numbered_buttons),
 				0);
 		features->numbered_buttons++;
 		break;
+	case WACOM_HID_WD_TOUCHONOFF:
+		wacom_map_usage(input, hdev, usage, field, EV_SW, SW_MUTE_DEVICE, 0);
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP:
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_RX, 0);
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP2:
+		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_RY, 0);
+		break;
 	case WACOM_HID_WD_TOUCHRING:
 		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index fa5b772..f70f7fd 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -96,6 +96,8 @@
 #define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHSTRIP         (WACOM_HID_UP_WACOMDIGITIZER | 0x0136)
+#define WACOM_HID_WD_TOUCHSTRIP2        (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)
 #define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
 #define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
 #define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
@@ -104,11 +106,14 @@
 #define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
 #define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_EXPRESSKEYCAP00    (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
 #define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
 #define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
 #define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
 #define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
 #define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
+#define WACOM_HID_WD_BUTTONCENTER       (WACOM_HID_UP_WACOMDIGITIZER | 0x0995)
+#define WACOM_HID_WD_TOUCHONOFF         (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
 #define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 19/19] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (17 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 18/19] HID: wacom: generic: Extend pad support Jason Gerecke
@ 2016-10-06 21:22 ` Jason Gerecke
  2016-10-07 15:41 ` [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Benjamin Tissoires
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-06 21:22 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as
follows:

"A steering wheel is a single degree-of-freedom device that rotates about
an axis. The zero position is always the neutral or 'straight ahead'
position, with positive values turning clockwise and negative values
turning counterclockwise. If the Coordinate Values Wrap attribute is
set, the steering wheel can be turned past 360 degrees."

The hidinput_configure_usage function canonically maps this usage to the
ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis
as one for which it can calculate a resolution. This effectively prevents
wheels from being assigned a proper resolution that userspace can use
to determine the precise angle of input.

This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/hid-input.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index bcfaf32..81d35e9 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 	case ABS_RX:
 	case ABS_RY:
 	case ABS_RZ:
+	case ABS_WHEEL:
 	case ABS_TILT_X:
 	case ABS_TILT_Y:
 		if (field->unit == 0x14) {		/* If degrees */
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (18 preceding siblings ...)
  2016-10-06 21:22 ` [PATCH 19/19] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
@ 2016-10-07 15:41 ` Benjamin Tissoires
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  21 siblings, 0 replies; 64+ messages in thread
From: Benjamin Tissoires @ 2016-10-07 15:41 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: linux-input, Jiri Kosina, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke

On Oct 06 2016 or thereabouts, Jason Gerecke wrote:
> Wacom announced two new "MobileStudio Pro" tablets yesterday, a third
> iteration of the Cintiq Companion line of mobile PCs which can double
> as external pen displays.
> 
> Unlike Wacom's prior professional-grade devices, the HID descriptor for
> the MobileStudio Pro includes a rudimentary (but standard!) "Digitizer"
> application collection that is usable by the existing HID_GENERIC codepath.
> Additionally, a second vendor-defined application collection exists which
> fully defines reports that enable full tablet functionality. The numerous
> vendor-defined usages are planned to be used in future professional devices
> as well, allowing us to finally gain some of the same forward compatibility
> benefits we've had for ISDv4 devices since 3.17.
> 
>  * Patches 1-3 perform some basic cleanups.
> 
>  * Patches 4-6 work on the operation of the driver for all HID_GENERIC
>    devices, correcting minor issues and adding some missing features.
> 
>  * Patches 7-19 implement support for the vendor defined usages that
>    are used in the MobileStudio Pro, and which are planned to be used
>    in future professional devices as well.
> 
> 
> Jiri: Could you let me know whether it would be possible to schedule
> these for the currently-open 4.9 merge window?

Jiri, FYI, I have already made 2 (or 3) internal reviews of this series.
I just have one/two nitpicks here and there (I noticed few if statements
with braces while only one statement was done after), but nothing
preventing from pulling the series IMO.

I have been staring the series for too long now, and I can't find
anything useful (besides in patch 13, but not a biggy).

>From what I can tell, the series has little impact on existing devices
(patches 1, 3, 11, 14), and I assume Jason and the other Wacom engineers
made extensive tests for these patches.

Patch 19 for hid-input should also be safe :)

The series is:
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Cheers,
Benjamin

> 
> 
> Jason Gerecke (19):
>   HID: wacom: Update vendor-defined usage names to better match
>     standards
>   HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more
>     fields
>   HID: wacom: Refactor button-to-key translation into function
>   HID: wacom: Detect and correct descriptors missing
>     HID_DG_BARRELSWITCH2
>   HID: wacom: generic: Strip off excessive name prefixing
>   HID: wacom: generic: Add support for height, tilt, and twist usages
>   HID: wacom: generic: Support and use 'Custom HID' mode and usages
>   HID: wacom: generic: Add support for vendor-defined "Distance" usage
>   HID: wacom: generic: Add support for vendor-defined "Fingerwheel"
>     usage
>   HID: wacom: generic: Add support for vendor-defined "Sense" usage
>   HID: wacom: Read and internally use corrected Intuos tool IDs
>   HID: wacom: generic: Support tool ID and additional tool types
>   HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
>   HID: wacom: Fix sensor outbounds and redefine as offsets from each
>     edge
>   HID: wacom: generic: Add support for sensor offsets
>   HID: wacom: generic: Introduce pad support
>   HID: wacom: generic: Add support for battery status on pen and pad
>     interfaces
>   HID: wacom: generic: Extend pad support
>   HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
> 
>  drivers/hid/hid-input.c |   1 +
>  drivers/hid/wacom_sys.c |  92 ++++++--
>  drivers/hid/wacom_wac.c | 544 +++++++++++++++++++++++++++++++++++++++---------
>  drivers/hid/wacom_wac.h |  73 ++++++-
>  include/linux/hid.h     |   4 +
>  5 files changed, 595 insertions(+), 119 deletions(-)
> 
> -- 
> 2.10.0
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
  2016-10-06 21:22 ` [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage' Jason Gerecke
@ 2016-10-07 15:46   ` Benjamin Tissoires
  2016-10-07 20:53     ` Jason Gerecke
  0 siblings, 1 reply; 64+ messages in thread
From: Benjamin Tissoires @ 2016-10-07 15:46 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: linux-input, Jiri Kosina, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke

On Oct 06 2016 or thereabouts, Jason Gerecke wrote:
> In the following "Add support for sensor offsets" patch we'll need access
> to the 'features' struct within 'wacom_map_usage', so update the function
> signature and calls to include a reference to the HID device so this can
> be done.
> 
> Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
> ---
>  drivers/hid/wacom_wac.c | 53 ++++++++++++++++++++++++++-----------------------
>  1 file changed, 28 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index f2aadc4..8f493cc 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -1465,9 +1465,12 @@ static int wacom_equivalent_usage(int usage)
>  	return usage;
>  }
>  
> -static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
> -		struct hid_field *field, __u8 type, __u16 code, int fuzz)
> +static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
> +		struct hid_usage *usage, struct hid_field *field, __u8 type,
> +		__u16 code, int fuzz)
>  {
> +	struct wacom *wacom = hid_get_drvdata(hdev);

This might not be entirely relevant, but given the inputs are created
through wacom_allocate_input() and struct wacom * being stored in the
driver data, a simple call to input_get_drvdata(input) would provide the
struct wacom. Then from here, the hid_device can be retrieved from
struct wacom directly.

So I don't know if it's worth resending the series just for this and if
this has caveats... (my rev-by still applies).

Cheers,
Benjamin

> +	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
>  	int fmin = field->logical_minimum;
>  	int fmax = field->logical_maximum;
>  	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
> @@ -1508,53 +1511,53 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
>  
>  	switch (equivalent_usage) {
>  	case HID_GD_X:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 4);
>  		break;
>  	case HID_GD_Y:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 4);
>  		break;
>  	case WACOM_HID_WD_DISTANCE:
>  	case HID_GD_Z:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_DISTANCE, 0);
>  		break;
>  	case HID_DG_TIPPRESSURE:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_PRESSURE, 0);
>  		break;
>  	case HID_DG_INRANGE:
> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
>  		break;
>  	case HID_DG_INVERT:
> -		wacom_map_usage(input, usage, field, EV_KEY,
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY,
>  				BTN_TOOL_RUBBER, 0);
>  		break;
>  	case HID_DG_TILT_X:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_TILT_X, 0);
>  		break;
>  	case HID_DG_TILT_Y:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_TILT_Y, 0);
>  		break;
>  	case HID_DG_TWIST:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Z, 0);
>  		break;
>  	case HID_DG_ERASER:
>  	case HID_DG_TIPSWITCH:
> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOUCH, 0);
>  		break;
>  	case HID_DG_BARRELSWITCH:
> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_STYLUS, 0);
>  		break;
>  	case HID_DG_BARRELSWITCH2:
> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_STYLUS2, 0);
>  		break;
>  	case HID_DG_TOOLSERIALNUMBER:
> -		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_MSC, MSC_SERIAL, 0);
>  		break;
>  	case WACOM_HID_WD_SENSE:
>  		features->quirks |= WACOM_QUIRK_SENSE;
> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
>  		break;
>  	case WACOM_HID_WD_SERIALHI:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MISC, 0);
>  		set_bit(EV_KEY, input->evbit);
>  		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
>  		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
> @@ -1565,7 +1568,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
>  		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
>  		break;
>  	case WACOM_HID_WD_FINGERWHEEL:
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_WHEEL, 0);
>  		break;
>  	}
>  }
> @@ -1722,24 +1725,24 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
>  	case HID_GD_X:
>  		features->last_slot_field = usage->hid;
>  		if (touch_max == 1)
> -			wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
> +			wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 4);
>  		else
> -			wacom_map_usage(input, usage, field, EV_ABS,
> +			wacom_map_usage(input, hdev, usage, field, EV_ABS,
>  					ABS_MT_POSITION_X, 4);
>  		break;
>  	case HID_GD_Y:
>  		features->last_slot_field = usage->hid;
>  		if (touch_max == 1)
> -			wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
> +			wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 4);
>  		else
> -			wacom_map_usage(input, usage, field, EV_ABS,
> +			wacom_map_usage(input, hdev, usage, field, EV_ABS,
>  					ABS_MT_POSITION_Y, 4);
>  		break;
>  	case HID_DG_WIDTH:
>  	case HID_DG_HEIGHT:
>  		features->last_slot_field = usage->hid;
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
>  		input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
>  		break;
>  	case HID_DG_CONTACTID:
> @@ -1753,7 +1756,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
>  		break;
>  	case HID_DG_TIPSWITCH:
>  		features->last_slot_field = usage->hid;
> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOUCH, 0);
>  		break;
>  	case HID_DG_CONTACTCOUNT:
>  		wacom_wac->hid_data.cc_report = field->report->id;
> -- 
> 2.10.0
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage'
  2016-10-07 15:46   ` Benjamin Tissoires
@ 2016-10-07 20:53     ` Jason Gerecke
  0 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 20:53 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: linux-input, Jiri Kosina, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke

On 10/07/2016 08:46 AM, Benjamin Tissoires wrote:
> On Oct 06 2016 or thereabouts, Jason Gerecke wrote:
>> In the following "Add support for sensor offsets" patch we'll need access
>> to the 'features' struct within 'wacom_map_usage', so update the function
>> signature and calls to include a reference to the HID device so this can
>> be done.
>>
>> Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
>> ---
>>  drivers/hid/wacom_wac.c | 53 ++++++++++++++++++++++++++-----------------------
>>  1 file changed, 28 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
>> index f2aadc4..8f493cc 100644
>> --- a/drivers/hid/wacom_wac.c
>> +++ b/drivers/hid/wacom_wac.c
>> @@ -1465,9 +1465,12 @@ static int wacom_equivalent_usage(int usage)
>>  	return usage;
>>  }
>>  
>> -static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
>> -		struct hid_field *field, __u8 type, __u16 code, int fuzz)
>> +static void wacom_map_usage(struct input_dev *input, struct hid_device *hdev,
>> +		struct hid_usage *usage, struct hid_field *field, __u8 type,
>> +		__u16 code, int fuzz)
>>  {
>> +	struct wacom *wacom = hid_get_drvdata(hdev);
> 
> This might not be entirely relevant, but given the inputs are created
> through wacom_allocate_input() and struct wacom * being stored in the
> driver data, a simple call to input_get_drvdata(input) would provide the
> struct wacom. Then from here, the hid_device can be retrieved from
> struct wacom directly.
> 
> So I don't know if it's worth resending the series just for this and if
> this has caveats... (my rev-by still applies).
> 
> Cheers,
> Benjamin
> 

I'd be happy with dropping this patch and using input_get_drvdata
instead. I hadn't remotely considered that we could access the wacom
structure from there as well. As noisy as it might be, I'll send a V2
with your rev-by and the change.

Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....

>> +	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
>>  	int fmin = field->logical_minimum;
>>  	int fmax = field->logical_maximum;
>>  	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
>> @@ -1508,53 +1511,53 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
>>  
>>  	switch (equivalent_usage) {
>>  	case HID_GD_X:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 4);
>>  		break;
>>  	case HID_GD_Y:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 4);
>>  		break;
>>  	case WACOM_HID_WD_DISTANCE:
>>  	case HID_GD_Z:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_DISTANCE, 0);
>>  		break;
>>  	case HID_DG_TIPPRESSURE:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_PRESSURE, 0);
>>  		break;
>>  	case HID_DG_INRANGE:
>> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
>>  		break;
>>  	case HID_DG_INVERT:
>> -		wacom_map_usage(input, usage, field, EV_KEY,
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY,
>>  				BTN_TOOL_RUBBER, 0);
>>  		break;
>>  	case HID_DG_TILT_X:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_TILT_X, 0);
>>  		break;
>>  	case HID_DG_TILT_Y:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_TILT_Y, 0);
>>  		break;
>>  	case HID_DG_TWIST:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Z, 0);
>>  		break;
>>  	case HID_DG_ERASER:
>>  	case HID_DG_TIPSWITCH:
>> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOUCH, 0);
>>  		break;
>>  	case HID_DG_BARRELSWITCH:
>> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_STYLUS, 0);
>>  		break;
>>  	case HID_DG_BARRELSWITCH2:
>> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_STYLUS2, 0);
>>  		break;
>>  	case HID_DG_TOOLSERIALNUMBER:
>> -		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_MSC, MSC_SERIAL, 0);
>>  		break;
>>  	case WACOM_HID_WD_SENSE:
>>  		features->quirks |= WACOM_QUIRK_SENSE;
>> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
>>  		break;
>>  	case WACOM_HID_WD_SERIALHI:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MISC, 0);
>>  		set_bit(EV_KEY, input->evbit);
>>  		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
>>  		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
>> @@ -1565,7 +1568,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
>>  		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
>>  		break;
>>  	case WACOM_HID_WD_FINGERWHEEL:
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_WHEEL, 0);
>>  		break;
>>  	}
>>  }
>> @@ -1722,24 +1725,24 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
>>  	case HID_GD_X:
>>  		features->last_slot_field = usage->hid;
>>  		if (touch_max == 1)
>> -			wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
>> +			wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_X, 4);
>>  		else
>> -			wacom_map_usage(input, usage, field, EV_ABS,
>> +			wacom_map_usage(input, hdev, usage, field, EV_ABS,
>>  					ABS_MT_POSITION_X, 4);
>>  		break;
>>  	case HID_GD_Y:
>>  		features->last_slot_field = usage->hid;
>>  		if (touch_max == 1)
>> -			wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
>> +			wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_Y, 4);
>>  		else
>> -			wacom_map_usage(input, usage, field, EV_ABS,
>> +			wacom_map_usage(input, hdev, usage, field, EV_ABS,
>>  					ABS_MT_POSITION_Y, 4);
>>  		break;
>>  	case HID_DG_WIDTH:
>>  	case HID_DG_HEIGHT:
>>  		features->last_slot_field = usage->hid;
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
>> -		wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
>>  		input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
>>  		break;
>>  	case HID_DG_CONTACTID:
>> @@ -1753,7 +1756,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
>>  		break;
>>  	case HID_DG_TIPSWITCH:
>>  		features->last_slot_field = usage->hid;
>> -		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
>> +		wacom_map_usage(input, hdev, usage, field, EV_KEY, BTN_TOUCH, 0);
>>  		break;
>>  	case HID_DG_CONTACTCOUNT:
>>  		wacom_wac->hid_data.cc_report = field->report->id;
>> -- 
>> 2.10.0
>>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (19 preceding siblings ...)
  2016-10-07 15:41 ` [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Benjamin Tissoires
@ 2016-10-07 22:16 ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
                     ` (16 more replies)
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  21 siblings, 17 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Our loose use of "pen" and "digitizer" in the naming of several of our
vendor-defined usages may be a source of confusion given that the terms
have specific meaning within the HID specification. "Pen" specifically
refers to "an integrated display that allows the use of a stylus" (e.g.
something like a tablet PC or Cintiq) wheras "Digitizer" is a better
fit for opaque tablets like an Intuos.

While we're at it, go ahead and rename the definitions to make them more
distinct and better match up with the convention used by HID (e.g. the use
of '_UP_' for usage pages) and make them more distinct.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 12 ++++++------
 drivers/hid/wacom_wac.c |  2 +-
 drivers/hid/wacom_wac.h | 17 +++++++++--------
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 5e7a564..773fa11 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 
 	case HID_UP_DIGITIZER:
 		if (field->report->id == 0x0B &&
-		    (field->application == WACOM_G9_DIGITIZER ||
-		     field->application == WACOM_G11_DIGITIZER)) {
+		    (field->application == WACOM_HID_G9_PEN ||
+		     field->application == WACOM_HID_G11_PEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
 
-	case WACOM_G9_PAGE:
-	case WACOM_G11_PAGE:
+	case WACOM_HID_UP_G9:
+	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
-		    (field->application == WACOM_G9_TOUCHSCREEN ||
-		     field->application == WACOM_G11_TOUCHSCREEN)) {
+		    (field->application == WACOM_HID_G9_TOUCHSCREEN ||
+		     field->application == WACOM_HID_G11_TOUCHSCREEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index a48ed4e..e09830c 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2458,7 +2458,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 	/*
 	 * Raw Wacom-mode pen and touch events both come from interface
 	 * 0, whose HID descriptor has an application usage of 0xFF0D
-	 * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
+	 * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back
 	 * out through the HID_GENERIC device created for interface 1,
 	 * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
 	 */
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index de5d1ad..3592186 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -84,20 +84,21 @@
 #define WACOM_DEVICETYPE_WL_MONITOR     0x0008
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
-#define WACOM_VENDORDEFINED_PEN		0xff0d0001
-#define WACOM_G9_PAGE			0xff090000
-#define WACOM_G9_DIGITIZER		(WACOM_G9_PAGE | 0x02)
-#define WACOM_G9_TOUCHSCREEN		(WACOM_G9_PAGE | 0x11)
-#define WACOM_G11_PAGE			0xff110000
-#define WACOM_G11_DIGITIZER		(WACOM_G11_PAGE | 0x02)
-#define WACOM_G11_TOUCHSCREEN		(WACOM_G11_PAGE | 0x11)
+#define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_UP_G9                 0xff090000
+#define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
+#define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
+#define WACOM_HID_UP_G11                0xff110000
+#define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
+#define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
 
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_VENDORDEFINED_PEN))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
 				 ((f)->application == HID_DG_TOUCHSCREEN))
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 03/18] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
                     ` (15 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

We've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN)
which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but
probably should be.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 3592186..472b0a7 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -98,10 +98,14 @@
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_HID_WD_DIGITIZER))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER) || \
+				 ((f)->application == WACOM_HID_G9_PEN) || \
+				 ((f)->application == WACOM_HID_G11_PEN))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
-				 ((f)->application == HID_DG_TOUCHSCREEN))
+				 ((f)->application == HID_DG_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G11_TOUCHSCREEN))
 
 enum {
 	PENPARTNER = 0,
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 03/18] HID: wacom: Refactor button-to-key translation into function
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
                     ` (14 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

This just centralizes the logic used in both wacom_setup_numbered_buttons
and wacom_report_numbered_buttons so that they don't drift out of sync.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index e09830c..a9f6d11 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2779,17 +2779,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
 	return 0;
 }
 
+static int wacom_numbered_button_to_key(int n)
+{
+	if (n < 10)
+		return BTN_0 + n;
+	else if (n < 16)
+		return BTN_A + (n-10);
+	else if (n < 18)
+		return BTN_BASE + (n-16);
+	else
+		return 0;
+}
+
 static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
 				int button_count)
 {
 	int i;
 
-	for (i = 0; i < button_count && i < 10; i++)
-		__set_bit(BTN_0 + i, input_dev->keybit);
-	for (i = 10; i < button_count && i < 16; i++)
-		__set_bit(BTN_A + (i-10), input_dev->keybit);
-	for (i = 16; i < button_count && i < 18; i++)
-		__set_bit(BTN_BASE + (i-16), input_dev->keybit);
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			__set_bit(key, input_dev->keybit);
+	}
 }
 
 static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group)
@@ -2891,12 +2903,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 	for (i = 0; i < wacom->led.count; i++)
 		wacom_update_led(wacom,  button_count, mask, i);
 
-	for (i = 0; i < button_count && i < 10; i++)
-		input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
-	for (i = 10; i < button_count && i < 16; i++)
-		input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
-	for (i = 16; i < button_count && i < 18; i++)
-		input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			input_report_key(input_dev, key, mask & (1 << i));
+	}
 }
 
 int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 03/18] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 05/18] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
                     ` (13 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

ISDv4 devices have long supported reporting data from each of two barrel
switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized.
Prior to its adoption, ISDv4 devices would associate the bit indicating
the state of the second barrel switch with the "Undefined" 0x000D0000
usage. Although most such devices have explicit support, a few use the
HID_GENERIC codepath which ignores the "Undefined" usage.

This patch adds code which detects the presence of a pre-standard second
barrel switch and corrects the usage value so that the HID_GENERIC code
will declare its presence and report its state.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 773fa11..033cc03 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev,
 			features->touch_max = 1;
 	}
 
+	/*
+	 * ISDv4 devices which predate HID's adoption of the
+	 * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
+	 * position instead. We can accurately detect if a
+	 * usage with that value should be HID_DG_BARRELSWITCH2
+	 * based on the surrounding usages, which have remained
+	 * constant across generations.
+	 */
+	if (features->type == HID_GENERIC &&
+	    usage->hid == 0x000D0000 &&
+	    field->application == HID_DG_PEN &&
+	    field->physical == HID_DG_STYLUS) {
+		int i = usage->usage_index;
+
+		if (i-4 >= 0 && i+1 < field->maxusage &&
+		    field->usage[i-4].hid == HID_DG_TIPSWITCH &&
+		    field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
+		    field->usage[i-2].hid == HID_DG_ERASER &&
+		    field->usage[i-1].hid == HID_DG_INVERT &&
+		    field->usage[i+1].hid == HID_DG_INRANGE) {
+			usage->hid = HID_DG_BARRELSWITCH2;
+		}
+	}
+
 	switch (usage->hid) {
 	case HID_GD_X:
 		features->x_max = field->logical_maximum;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 05/18] HID: wacom: generic: Strip off excessive name prefixing
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (2 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
                     ` (12 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The product name received from the string descriptor in the new MobileStudio
Pro line of tablets begins with "Wacom", which leads to unnecessary visual
noise in the device name when appended to the vendor name which also includes
"Wacom". Look for and fix cases like this.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 033cc03..7b9bff2 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
 				/* shift everything including the terminator */
 				memmove(gap, gap+1, strlen(gap));
 			}
+
+			/* strip off excessive prefixing */
+			if (strstr(name, "Wacom Co.,Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co.,Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+			if (strstr(name, "Wacom Co., Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co., Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+
 			/* get rid of trailing whitespace */
 			if (name[strlen(name)-1] == ' ')
 				name[strlen(name)-1] = '\0';
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (3 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 05/18] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
                     ` (11 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The HID standard defines usages that allow digitizers to report the pen's
height, tilt, and rotation and which are used by Wacom's new "MobileStudio
Pro" devices.

Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our
driver to report twist) to have linear units. To ensure it calculates a
resolution with the actually-angular units provided in the HID descriptor
we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ
axis instead.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++--
 include/linux/hid.h     |  3 +++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index a9f6d11..e2eae91 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 {
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	int resolution_code = code;
+
+	if (usage->hid == HID_DG_TWIST) {
+		resolution_code = ABS_RZ;
+	}
 
 	usage->type = type;
 	usage->code = code;
@@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	case EV_ABS:
 		input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
 		input_abs_set_res(input, code,
-				  hidinput_calc_abs_res(field, code));
+				  hidinput_calc_abs_res(field, resolution_code));
 		break;
 	case EV_KEY:
 		input_set_capability(input, EV_KEY, code);
@@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case HID_GD_Z:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
+		break;
 	case HID_DG_TIPPRESSURE:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
 		break;
@@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		wacom_map_usage(input, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
 		break;
+	case HID_DG_TILT_X:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
+		break;
+	case HID_DG_TILT_Y:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
+		break;
+	case HID_DG_TWIST:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		break;
 	case HID_DG_ERASER:
 	case HID_DG_TIPSWITCH:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
@@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 
-	/* checking which Tool / tip switch to send */
 	switch (usage->hid) {
+	case HID_GD_Z:
+		/*
+		 * HID_GD_Z "should increase as the control's position is
+		 * moved from high to low", while ABS_DISTANCE instead
+		 * increases in value as the tool moves from low to high.
+		 */
+		value = field->logical_maximum - value;
+		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
 		return 0;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 75b66ec..0c05b27 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -232,6 +232,9 @@ struct hid_item {
 #define HID_DG_TABLETFUNCTIONKEY	0x000d0039
 #define HID_DG_PROGRAMCHANGEKEY	0x000d003a
 #define HID_DG_INVERT		0x000d003c
+#define HID_DG_TILT_X		0x000d003d
+#define HID_DG_TILT_Y		0x000d003e
+#define HID_DG_TWIST		0x000d0041
 #define HID_DG_TIPSWITCH	0x000d0042
 #define HID_DG_TIPSWITCH2	0x000d0043
 #define HID_DG_BARRELSWITCH	0x000d0044
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (4 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-18 15:26     ` Jiri Kosina
  2016-10-07 22:16   ` [PATCH v2 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
                     ` (10 subsequent siblings)
  16 siblings, 1 reply; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom's new "MobileStudio Pro" tablets are the first devices in their
branded product line-up to include a usable HID descriptor for the pen
interface. Like prior branded products, the device can operate in one
of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the
first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is
subject to some restrictions -- most notably pressure being limited
to 2048 levels instead of 8192. To ensure tablets that include support
for Custom HID mode work optimally, we add support for its usages and
switch the device to Custom HID mode if possible.

The usages defined for Custom HID mode are often numerically similar to
their standard HID equivalents, allowing us to write a simple translation
function that takes arbitrary HID usages as input and which returns
the corresponding standard HID usage as output (if one exists). Switching
on this translated usage instead of the actual usage allows the existing
cases to apply to both modes of operation without having to explicitly
define every Custom HID usage.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c |  5 +++++
 drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------
 drivers/hid/wacom_wac.h |  3 +++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 7b9bff2..b2e2471 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 		}
 		break;
 
+	case WACOM_HID_WD_DATAMODE:
+		wacom->wacom_wac.mode_report = field->report->id;
+		wacom->wacom_wac.mode_value = 2;
+		break;
+
 	case WACOM_HID_UP_G9:
 	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index e2eae91..edc2c14 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 	return 0;
 }
 
+static int wacom_equivalent_usage(int usage)
+{
+	if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) {
+		int subpage = (usage & 0xFF00) << 8;
+		int subusage = (usage & 0xFF);
+
+		if (subpage == WACOM_HID_SP_DIGITIZER ||
+		    subpage == WACOM_HID_SP_DIGITIZERINFO) {
+			return usage;
+		}
+
+		if (subpage == HID_UP_UNDEFINED)
+			subpage = HID_UP_DIGITIZER;
+
+		return subpage | subusage;
+	}
+
+	return usage;
+}
+
 static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		struct hid_field *field, __u8 type, __u16 code, int fuzz)
 {
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
 	int resolution_code = code;
 
-	if (usage->hid == HID_DG_TWIST) {
+	if (equivalent_usage == HID_DG_TWIST) {
 		resolution_code = ABS_RZ;
 	}
 
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
 		break;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_Z:
 		/*
 		 * HID_GD_Z "should increase as the control's position is
@@ -1598,8 +1621,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
 	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->touch_input;
 	unsigned touch_max = wacom_wac->features.touch_max;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		features->last_slot_field = usage->hid;
 		if (touch_max == 1)
@@ -1687,8 +1711,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_wac->hid_data.x = value;
 		break;
@@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
 
 
 	if (usage->usage_index + 1 == field->report_count) {
-		if (usage->hid == wacom_wac->features.last_slot_field)
+		if (equivalent_usage == wacom_wac->features.last_slot_field)
 			wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
 	}
 
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 472b0a7..c82233d 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -85,7 +85,10 @@
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
 #define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_DIGITIZER          0x000d0000
+#define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
 #define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (5 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
                     ` (9 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to
HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which
increases in value as the pen-to-surface distance is decreased, this usage
decreases. Treat this usage as a special case to ensure we don't invert the
scale to be ABS_DISTANCE compatible like we do for HID_GD_Z.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 4 +++-
 drivers/hid/wacom_wac.h | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index edc2c14..aa51684 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage)
 		int subusage = (usage & 0xFF);
 
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
-		    subpage == WACOM_HID_SP_DIGITIZERINFO) {
+		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
 
@@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case WACOM_HID_WD_DISTANCE:
 	case HID_GD_Z:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
 		break;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index c82233d..1ced6e4 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -88,6 +88,7 @@
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (6 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
                     ` (8 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The airbrush fingerwheel does not have a usage that corresponds cleanly
with a standard HID usage, so we add explicit support for it via its
vendor-defined usage.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 3 +++
 drivers/hid/wacom_wac.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index aa51684..009c25d 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_FINGERWHEEL:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
 	}
 }
 
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 1ced6e4..18cae38 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -89,6 +89,7 @@
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (7 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
                     ` (7 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom's professional tablets beginning with the Intuos4 are capable of
reporting an intermediate degree of proximity where the pen is no longer
close enough to communicate with ("in prox"), but still close enough to
be sensed ("in range"). This additional state is particularly useful for
performing palm rejection as it allows the driver to disable the touch
sensor while the pen is a greater distance from the tablet.

Like other professional tablets, the new MobileStudio Pro also reports
this intermeidate "in range" proximity state. Its descriptor assigns
usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would
translate this to the standard HID "Quality" usage, but since this has
a different meaning we have it explicitly ignore the usage and define
it ourselves as "Sense" (since "In Range" is already defined by the
HID standard and interpreted by our driver as meaning "in prox").

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++---
 drivers/hid/wacom_wac.h |  3 +++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 009c25d..0e8c99a 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)
 
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_SENSE ||
 		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
@@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
@@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_SENSE:
+		features->quirks |= WACOM_QUIRK_SENSE;
+		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+		break;
 	case WACOM_HID_WD_FINGERWHEEL:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
@@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
@@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
+		if (!(features->quirks & WACOM_QUIRK_SENSE))
+			wacom_wac->hid_data.sense_state = value;
 		return 0;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
@@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
 		return 0;
+	case WACOM_HID_WD_SENSE:
+		wacom_wac->hid_data.sense_state = value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
@@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	if (!usage->type || delay_pen_events(wacom_wac))
 		return 0;
 
+	/* send pen events only when the pen is in/entering/leaving proximity */
+	if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
+		return 0;
+
 	input_event(input, usage->type, usage->code, value);
 
 	return 0;
@@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 	bool prox = wacom_wac->hid_data.inrange_state;
+	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) /* first in prox */
 		/* Going into proximity select tool */
 		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
 						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
 	/* keep pen state for touch events */
-	wacom_wac->shared->stylus_in_proximity = prox;
+	wacom_wac->shared->stylus_in_proximity = range;
 
-	if (!delay_pen_events(wacom_wac)) {
+	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
@@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 
 		input_sync(input);
 	}
+
+	if (!prox)
+		wacom_wac->tool[0] = 0;
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 18cae38..e8779c7 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -74,6 +74,7 @@
 
 /* device quirks */
 #define WACOM_QUIRK_BBTOUCH_LOWRES	0x0001
+#define WACOM_QUIRK_SENSE		0x0002
 #define WACOM_QUIRK_BATTERY		0x0008
 
 /* device types */
@@ -88,6 +89,7 @@
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -213,6 +215,7 @@ struct wacom_shared {
 struct hid_data {
 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
+	bool sense_state;
 	bool inrange_state;
 	bool invert_state;
 	bool tipswitch;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (8 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 12/18] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
                     ` (6 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the
proximity report, shifting the higher values of the ID four bits farther
than intended. This problem was not detected until too late, but has not
caused any issues since the incorrect IDs still fit in a 32-bit integer
and userspace programs have not required the value to match the hardware
(just that the values are unique and constant).

The tool IDs reported by the new MobileStudio Pro (or any future
HID_GENERIC device that supports them) do not suffer from the same
assembly issue, however. In order for 'wacom_intuos_get_tool_type' to
work for with both codepaths, we correct this issue internally and
have 'wacom_intuos_general' only mangle the ID when it is posted to
userspace.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 0e8c99a..60f065b 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
 	return 1;
 }
 
+static int wacom_intuos_id_mangle(int tool_id)
+{
+	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
+}
+
 static int wacom_intuos_get_tool_type(int tool_id)
 {
 	int tool_type;
@@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	switch (tool_id) {
 	case 0x812: /* Inking pen */
 	case 0x801: /* Intuos3 Inking pen */
-	case 0x120802: /* Intuos4/5 Inking Pen */
+	case 0x12802: /* Intuos4/5 Inking Pen */
 	case 0x012:
 		tool_type = BTN_TOOL_PENCIL;
 		break;
@@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
 	case 0x8e2: /* IntuosHT2 pen */
 	case 0x022:
-	case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
-	case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
-	case 0x160802: /* Cintiq 13HD Pro Pen */
-	case 0x180802: /* DTH2242 Pen */
-	case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
+	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+	case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
+	case 0x16802: /* Cintiq 13HD Pro Pen */
+	case 0x18802: /* DTH2242 Pen */
+	case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
 		tool_type = BTN_TOOL_PEN;
 		break;
 
@@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
 	case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 	case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
-	case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
-	case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
-	case 0x18080a: /* DTH2242 Eraser */
-	case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
+	case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
+	case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
+	case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
+	case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
+	case 0x1880a: /* DTH2242 Eraser */
+	case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 		tool_type = BTN_TOOL_RUBBER;
 		break;
 
@@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x112:
 	case 0x913: /* Intuos3 Airbrush */
 	case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
-	case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
+	case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
 		tool_type = BTN_TOOL_AIRBRUSH;
 		break;
 
@@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 			(data[6] << 4) + (data[7] >> 4);
 
 		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
-			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
+		     ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8);
 
 		wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);
 
@@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
 	 * don't report events for invalid data
 	 */
 	/* older I4 styli don't work with new Cintiqs */
-	if ((!((wacom->id[idx] >> 20) & 0x01) &&
+	if ((!((wacom->id[idx] >> 16) & 0x01) &&
 			(features->type == WACOM_21UX2)) ||
 	    /* Only large Intuos support Lense Cursor */
 	    (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
 		break;
 	}
 
-	input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
+	input_report_abs(input, ABS_MISC,
+			 wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */
 	input_report_key(input, wacom->tool[idx], 1);
 	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 	wacom->reporting_data = true;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 12/18] HID: wacom: generic: Support tool ID and additional tool types
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (9 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
                     ` (5 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Devices following the new Custom HID mode specification (as well as even
some recent component sensors which use the same standard HID usage)
are capable of reporting tool ID information that we need to relay to
userspace. This patch adds support for reading and relaying the tool
type information, which is (unfortunately) split across two usages.
We also advertise the existence of tool types beyond BTN_TOOL_PEN
that might be available.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++---
 drivers/hid/wacom_wac.h |  4 ++-
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 60f065b..f2aadc4 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage)
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
 		    usage == WACOM_HID_WD_SENSE ||
+		    usage == WACOM_HID_WD_SERIALHI ||
+		    usage == WACOM_HID_WD_TOOLTYPE ||
 		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
@@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		features->quirks |= WACOM_QUIRK_SENSE;
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
+		set_bit(EV_KEY, input->evbit);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
+		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
+		input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
+		input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
+		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
+		break;
 	case WACOM_HID_WD_FINGERWHEEL:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
@@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
 		return 0;
+	case HID_DG_TOOLSERIALNUMBER:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFF);
+		wacom_wac->serial[0] |= value;
+		return 0;
 	case WACOM_HID_WD_SENSE:
 		wacom_wac->hid_data.sense_state = value;
 		return 0;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
+		wacom_wac->serial[0] |= ((__u64)value) << 32;
+		/*
+		 * Non-USI EMR devices may contain additional tool type
+		 * information here. See WACOM_HID_WD_TOOLTYPE case for
+		 * more details.
+		 */
+		if (value >> 20 == 1) {
+			wacom_wac->id[0] |= value & 0xFFFFF;
+		}
+		return 0;
+	case WACOM_HID_WD_TOOLTYPE:
+		/*
+		 * Some devices (MobileStudio Pro, and possibly later
+		 * devices as well) do not return the complete tool
+		 * type in their WACOM_HID_WD_TOOLTYPE usage. Use a
+		 * bitwise OR so the complete value can be built
+		 * up over time :(
+		 */
+		wacom_wac->id[0] |= value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
@@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 	bool prox = wacom_wac->hid_data.inrange_state;
 	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->tool[0] && prox) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) { /* first in prox */
 		/* Going into proximity select tool */
-		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
-						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		if (wacom_wac->hid_data.invert_state)
+			wacom_wac->tool[0] = BTN_TOOL_RUBBER;
+		else if (wacom_wac->id[0])
+			wacom_wac->tool[0] = wacom_intuos_get_tool_type(wacom_wac->id[0]);
+		else
+			wacom_wac->tool[0] = BTN_TOOL_PEN;
+	}
 
 	/* keep pen state for touch events */
 	wacom_wac->shared->stylus_in_proximity = range;
 
 	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
+		int id = wacom_wac->id[0];
+
+		/*
+		 * Non-USI EMR tools should have their IDs mangled to
+		 * match the legacy behavior of wacom_intuos_general
+		 */
+		if (wacom_wac->serial[0] >> 52 == 1)
+			id = wacom_intuos_id_mangle(id);
+
+		/*
+		 * To ensure compatibility with xf86-input-wacom, we should
+		 * report the BTN_TOOL_* event prior to the ABS_MISC or
+		 * MSC_SERIAL events.
+		 */
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
+		if (wacom_wac->serial[0]) {
+			input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+			input_report_abs(input, ABS_MISC, id);
+		}
 
 		wacom_wac->hid_data.tipswitch = false;
 
 		input_sync(input);
 	}
 
-	if (!prox)
+	if (!prox) {
 		wacom_wac->tool[0] = 0;
+		wacom_wac->id[0] = 0;
+	}
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index e8779c7..3926ff4 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -90,6 +90,8 @@
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
+#define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -247,7 +249,7 @@ struct wacom_wac {
 	unsigned char data[WACOM_PKGLEN_MAX];
 	int tool[2];
 	int id[2];
-	__u32 serial[2];
+	__u64 serial[2];
 	bool reporting_data;
 	struct wacom_features features;
 	struct wacom_shared *shared;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (10 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 12/18] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 14/18] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
                     ` (4 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Many of Wacom's display tablets include an "outbound" area where pen
digitizing is possible but outside of the display area. To ensure that
pen coordinates are mapped to the correct on-screen location, the driver
sets the minimum and maximum axis values of X and Y to those coordinates
which coincide with the screen edge. These values are simply the
hardware minimum/maximum plus/minus the outbound size for a particular
edge.

When outbound support was added/updated in ac414da, fa77034, and
ecd618d, we decided to have the wacom_features structs store the desired
minimum and maximum values directly. In hindsight, this was perhaps not
the best choice since it has allowed minor errors to crop up unnoticed.
Some tablets have had their coordinates over-corrected (e.g. most of the
devices "fixed" in ecd618d were already adjusted in ac414da), while
others never had a correction applied (e.g. the ISDv5 325, whose
declared maximum the hardware maximum instead of the outbound maximum).

A less error-prone method of handling the outbound is to let the driver
calculate the correct minimum/maximum values by providing it with both
the actual hardware maximums and the size of the outbound on each edge.
These values are more easy to verify as correct since the values can be
trivially compared against specifications.

This patch reverts the declared maximum values to the actual hardware
maximums, e.g. as declared prior to ac414da (values for these and other
display tablets that were subsuquently introduced have been verified
against specs). Per-edge outbound sizes are stored in the wacom_features
struct as offset_{left,right,top,bottom} and used in combination with
the hardware ranges to calculate effective axis ranges for ABS_X and
ABS_Y.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++-----------------
 drivers/hid/wacom_wac.h |  6 +++--
 2 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index f2aadc4..df751f2 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2684,10 +2684,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(ABS_MISC, input_dev->absbit);
 
-	input_set_abs_params(input_dev, ABS_X, features->x_min,
-			     features->x_max, features->x_fuzz, 0);
-	input_set_abs_params(input_dev, ABS_Y, features->y_min,
-			     features->y_max, features->y_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_X, 0 + features->offset_left,
+			     features->x_max - features->offset_right,
+			     features->x_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0 + features->offset_top,
+			     features->y_max - features->offset_bottom,
+			     features->y_fuzz, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0,
 		features->pressure_max, features->pressure_fuzz, 0);
 
@@ -3399,26 +3401,30 @@ static const struct wacom_features wacom_features_0x317 =
 	  INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xF4 =
-	{ "Wacom Cintiq 24HD", 104080, 65200, 2047, 63,
+	{ "Wacom Cintiq 24HD", 104480, 65600, 2047, 63,
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xF8 =
-	{ "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */
+	{ "Wacom Cintiq 24HD touch", 104480, 65600, 2047, 63, /* Pen */
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
 static const struct wacom_features wacom_features_0xF6 =
 	{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x32A =
-	{ "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x32B =
-	{ "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD touch", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
 static const struct wacom_features wacom_features_0x32C =
 	{ "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT,
@@ -3433,13 +3439,15 @@ static const struct wacom_features wacom_features_0xC6 =
 	{ "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
 	  WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
 static const struct wacom_features wacom_features_0x304 =
-	{ "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
+	{ "Wacom Cintiq 13HD", 59552, 33848, 1023, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x333 =
-	{ "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
+	{ "Wacom Cintiq 13HD touch", 59552, 33848, 2047, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
 static const struct wacom_features wacom_features_0x335 =
 	{ "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3456,42 +3464,50 @@ static const struct wacom_features wacom_features_0xF0 =
 	{ "Wacom DTU1631", 34623, 19553, 511, 0,
 	  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xFB =
-	{ "Wacom DTU1031", 21896, 13760, 511, 0,
+	{ "Wacom DTU1031", 22096, 13960, 511, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x32F =
-	{ "Wacom DTU1031X", 22472, 12728, 511, 0,
+	{ "Wacom DTU1031X", 22672, 12928, 511, 0,
 	  DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x336 =
-	{ "Wacom DTU1141", 23472, 13203, 1023, 0,
+	{ "Wacom DTU1141", 23672, 13403, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x57 =
-	{ "Wacom DTK2241", 95640, 54060, 2047, 63,
+	{ "Wacom DTK2241", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x59 = /* Pen */
-	{ "Wacom DTH2242", 95640, 54060, 2047, 63,
+	{ "Wacom DTH2242", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
 static const struct wacom_features wacom_features_0x5D = /* Touch */
 	{ "Wacom DTH2242",       .type = WACOM_24HDT,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xCC =
-	{ "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63,
+	{ "Wacom Cintiq 21UX2", 87200, 65600, 2047, 63,
 	  WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xFA =
-	{ "Wacom Cintiq 22HD", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HD", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x5B =
-	{ "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HDT", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
 static const struct wacom_features wacom_features_0x5E =
 	{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3635,18 +3651,20 @@ static const struct wacom_features wacom_features_0x6004 =
 	{ "ISD-V4", 12800, 8000, 255, 0,
 	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x307 =
-	{ "Wacom ISDv5 307", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 307", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
 static const struct wacom_features wacom_features_0x309 =
 	{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x30A =
-	{ "Wacom ISDv5 30A", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 30A", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
 static const struct wacom_features wacom_features_0x30C =
 	{ "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3662,6 +3680,7 @@ static const struct wacom_features wacom_features_0x325 =
 	{ "Wacom ISDv5 325", 59552, 33848, 2047, 63,
 	  CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };
 static const struct wacom_features wacom_features_0x326 = /* Touch */
 	{ "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3691,8 +3710,9 @@ static const struct wacom_features wacom_features_0x33E =
 	  INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x343 =
-	{ "Wacom DTK1651", 34616, 19559, 1023, 0,
+	{ "Wacom DTK1651", 34816, 19759, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 3926ff4..81ae478 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -181,8 +181,10 @@ struct wacom_features {
 	int x_resolution;
 	int y_resolution;
 	int numbered_buttons;
-	int x_min;
-	int y_min;
+	int offset_left;
+	int offset_right;
+	int offset_top;
+	int offset_bottom;
 	int device_type;
 	int x_phy;
 	int y_phy;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 14/18] HID: wacom: generic: Add support for sensor offsets
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (11 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 15/18] HID: wacom: generic: Introduce pad support Jason Gerecke
                     ` (3 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Many of Wacom's display tablets include an "outbound" area where pen
digitizing is possible but outside of the display area. To accommodate
such sensors in the HID_GENERIC codepath, we add support for the
necessary vendor-defined HID feature usages and adjust the min/max
values of the X and Y axes accordingly, similar to what is done in
the non-generic codepath.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
Changes from v1:
 * Use input_get_drvdata instead of hid_get_drvdata. This removes the
   need for a "Pass 'hdev' to 'wacom_map_usage'" patch, which is no
   longer part of the v2 set.

 drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++--------
 drivers/hid/wacom_wac.c | 40 ++++++++++++++++++++++++++++++++++++++++
 drivers/hid/wacom_wac.h |  4 ++++
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index b2e2471..b9779bc 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 	struct hid_data *hid_data = &wacom->wacom_wac.hid_data;
 	u8 *data;
 	int ret;
+	int n;
 
 	switch (usage->hid) {
 	case HID_DG_CONTACTMAX:
@@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
+	case WACOM_HID_WD_OFFSETLEFT:
+	case WACOM_HID_WD_OFFSETTOP:
+	case WACOM_HID_WD_OFFSETRIGHT:
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		/* read manually */
+		n = hid_report_len(field->report);
+		data = hid_alloc_report_buf(field->report, GFP_KERNEL);
+		if (!data)
+			break;
+		data[0] = field->report->id;
+		ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
+					data, n, WAC_CMD_RETRIES);
+		if (ret == n) {
+			ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+						   data, n, 0);
+		} else {
+			hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+				 __func__);
+		}
+		kfree(data);
+		break;
 	}
 }
 
@@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)
 		return retval;
 	}
 
-	if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
-		wacom_wac->shared->touch = hdev;
-	else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
-		wacom_wac->shared->pen = hdev;
-
 out:
 	mutex_unlock(&wacom_udev_list_lock);
 	return retval;
@@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 	if (error)
 		goto fail;
 
+	error = wacom_add_shared_data(hdev);
+	if (error)
+		goto fail;
+
 	/*
 	 * Bamboo Pad has a generic hid handling for the Pen, and we switch it
 	 * into debug mode for the touch part.
@@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 
 	wacom_update_name(wacom, wireless ? " (WL)" : "");
 
-	error = wacom_add_shared_data(hdev);
-	if (error)
-		goto fail;
+	if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
+		wacom_wac->shared->touch = hdev;
+	else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
+		wacom_wac->shared->pen = hdev;
 
 	if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
 	     (features->quirks & WACOM_QUIRK_BATTERY)) {
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index df751f2..d4a1d33 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1468,6 +1468,9 @@ static int wacom_equivalent_usage(int usage)
 static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		struct hid_field *field, __u8 type, __u16 code, int fuzz)
 {
+	struct wacom *wacom = input_get_drvdata(input);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
 	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
@@ -1477,6 +1480,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		resolution_code = ABS_RZ;
 	}
 
+	if (equivalent_usage == HID_GD_X) {
+		fmin += features->offset_left;
+		fmax -= features->offset_right;
+	}
+	if (equivalent_usage == HID_GD_Y) {
+		fmin += features->offset_top;
+		fmax -= features->offset_bottom;
+	}
+
 	usage->type = type;
 	usage->code = code;
 
@@ -1629,6 +1641,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		 */
 		wacom_wac->id[0] |= value;
 		return 0;
+	case WACOM_HID_WD_OFFSETLEFT:
+		if (features->offset_left && value != features->offset_left)
+			hid_warn(hdev, "%s: overriding exising left offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_left);
+		features->offset_left = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETRIGHT:
+		if (features->offset_right && value != features->offset_right)
+			hid_warn(hdev, "%s: overriding exising right offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_right);
+		features->offset_right = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETTOP:
+		if (features->offset_top && value != features->offset_top)
+			hid_warn(hdev, "%s: overriding exising top offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_top);
+		features->offset_top = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		if (features->offset_bottom && value != features->offset_bottom)
+			hid_warn(hdev, "%s: overriding exising bottom offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_bottom);
+		features->offset_bottom = value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 81ae478..93df1de 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -94,6 +94,10 @@
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
+#define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
+#define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
+#define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
+#define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 15/18] HID: wacom: generic: Introduce pad support
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (12 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 14/18] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
                     ` (2 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

As with usages for the pen, the Custom HID specificiation includes
usages for the pad. Here we add functions to map and handle most
of the pad usages present on the MobileStudio Pro.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------
 drivers/hid/wacom_wac.h |  19 +++++++
 2 files changed, 146 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index d4a1d33..d10b546 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");
 static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 				int button_count, int mask);
 
+static int wacom_numbered_button_to_key(int n);
+
 /*
  * Percent of battery capacity for Graphire.
  * 8th value means AC online and show 100% capacity.
@@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage)
 		int subpage = (usage & 0xFF00) << 8;
 		int subusage = (usage & 0xFF);
 
-		if (subpage == WACOM_HID_SP_DIGITIZER ||
+		if (subpage == WACOM_HID_SP_PAD ||
+		    subpage == WACOM_HID_SP_BUTTON ||
+		    subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
 		    usage == WACOM_HID_WD_SENSE ||
 		    usage == WACOM_HID_WD_SERIALHI ||
 		    usage == WACOM_HID_WD_TOOLTYPE ||
-		    usage == WACOM_HID_WD_DISTANCE) {
+		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHRING ||
+		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
 			return usage;
 		}
 
@@ -1509,6 +1515,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	}
 }
 
+static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_ACCELEROMETER_X:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Y:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 0);
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Z:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		break;
+	case WACOM_HID_WD_BUTTONHOME:
+	case WACOM_HID_WD_BUTTONUP:
+	case WACOM_HID_WD_BUTTONDOWN:
+	case WACOM_HID_WD_BUTTONLEFT:
+	case WACOM_HID_WD_BUTTONRIGHT:
+		wacom_map_usage(input, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		break;
+	case WACOM_HID_WD_TOUCHRING:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
+	}
+
+	switch (equivalent_usage & 0xfffffff0) {
+	case WACOM_HID_WD_EXPRESSKEY00:
+		wacom_map_usage(input, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		break;
+	}
+}
+
+static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) {
+		wacom_wac->hid_data.inrange_state |= value;
+	}
+
+	if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS)
+		input_event(input, usage->type, usage->code, value);
+
+	return 0;
+}
+
+static void wacom_wac_pad_pre_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+	wacom_wac->hid_data.inrange_state = 0;
+}
+
+static void wacom_wac_pad_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	bool active = wacom_wac->hid_data.inrange_state != 0;
+
+	/*
+	 * don't report prox for events like accelerometer
+	 * or battery status
+	 */
+	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY)
+		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
+
+	input_sync(input);
+}
+
 static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
@@ -1956,10 +2054,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,
 	/* currently, only direct devices have proper hid report descriptors */
 	features->device_type |= WACOM_DEVICETYPE_DIRECT;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_usage_mapping(hdev, field, usage);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_usage_mapping(hdev, field, usage);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_usage_mapping(hdev, field, usage);
 }
 
@@ -1971,10 +2070,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
 	if (wacom->wacom_wac.features.type != HID_GENERIC)
 		return 0;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_event(hdev, field, usage, value);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_event(hdev, field, usage, value);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_event(hdev, field, usage, value);
 
 	return 0;
@@ -2008,18 +2108,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
 	if (wacom_wac->features.type != HID_GENERIC)
 		return;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		wacom_wac_pad_pre_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field))
 		wacom_wac_pen_pre_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		wacom_wac_finger_pre_report(hdev, report);
 
 	wacom_report_events(hdev, report);
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_report(hdev, report);
 }
 
@@ -2593,6 +2695,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 	struct wacom_features *features = &wacom->wacom_wac.features;
 
 	/* The pen and pad share the same interface on most devices */
+	if (features->numbered_buttons > 0)
+		features->device_type |= WACOM_DEVICETYPE_PAD;
 	if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 ||
 	    features->type == DTUS ||
 	    (features->type >= INTUOS3S && features->type <= WACOM_MO)) {
@@ -3114,8 +3218,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 	__set_bit(ABS_MISC, input_dev->absbit);
 
 	/* kept for making legacy xf86-input-wacom accepting the pad */
-	input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum ||
+	      input_dev->absinfo[ABS_X].maximum)))
+		input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum ||
+	      input_dev->absinfo[ABS_Y].maximum)))
+		input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
 
 	/* kept for making udev and libwacom accepting the pad */
 	__set_bit(BTN_STYLUS, input_dev->keybit);
@@ -3235,6 +3343,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
 		break;
 
+	case HID_GENERIC:
+		break;
+
 	default:
 		/* no pad supported */
 		return -ENODEV;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 93df1de..0c69c1f 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -86,19 +86,34 @@
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
 #define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_PAD                0x00040000
+#define WACOM_HID_SP_BUTTON             0x00090000
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_DIGITIZERFNKEYS    (WACOM_HID_UP_WACOMDIGITIZER | 0x39)
 #define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
+#define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
+#define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
+#define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
+#define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
+#define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
+#define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
+#define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
+#define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
 #define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
 #define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
 #define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
+#define WACOM_HID_WD_DIGITIZERINFO      (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
 #define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
@@ -106,6 +121,10 @@
 #define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
 #define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
 
+#define WACOM_PAD_FIELD(f)	(((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERINFO))
+
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (13 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 15/18] HID: wacom: generic: Introduce pad support Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 17/18] HID: wacom: generic: Extend pad support Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Adds support for usages that may appear on the pen or pad interface which
report the state of the tablet battery.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 drivers/hid/wacom_wac.h |  6 ++++++
 include/linux/hid.h     |  1 +
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index d10b546..21c0ec3 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1525,6 +1525,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
 	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case WACOM_HID_WD_ACCELEROMETER_X:
 		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
@@ -1574,8 +1578,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
 		wacom_wac->hid_data.inrange_state |= value;
 	}
 
-	if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS)
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		return 0;
+
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		wacom_wac->hid_data.bat_charging = value;
+		wacom_wac->hid_data.ps_connected = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		return 0;
+
+	case WACOM_HID_WD_TOUCHRINGSTATUS:
+		return 0;
+
+	default:
 		input_event(input, usage->type, usage->code, value);
+		break;
+	}
 
 	return 0;
 }
@@ -1594,6 +1615,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pad_input;
 	bool active = wacom_wac->hid_data.inrange_state != 0;
 
@@ -1604,6 +1626,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
 	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY)
 		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
 
+	if (features->quirks & WACOM_QUIRK_BATTERY) {
+		int capacity = wacom_wac->hid_data.battery_capacity;
+		bool charging = wacom_wac->hid_data.bat_charging;
+		bool connected = wacom_wac->hid_data.bat_connected;
+		bool powered = wacom_wac->hid_data.ps_connected;
+
+		wacom_notify_battery(wacom_wac, capacity, charging,
+				     connected, powered);
+	}
+
 	input_sync(input);
 }
 
@@ -1633,6 +1665,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_INRANGE:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case HID_DG_BATTERYSTRENGTH:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case HID_DG_INVERT:
 		wacom_map_usage(input, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
@@ -1703,6 +1738,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		if (!(features->quirks & WACOM_QUIRK_SENSE))
 			wacom_wac->hid_data.sense_state = value;
 		return 0;
+	case HID_DG_BATTERYSTRENGTH:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		break;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
 		return 0;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 0c69c1f..fa5b772 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -101,6 +101,8 @@
 #define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
 #define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
 #define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
+#define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
 #define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
 #define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
@@ -257,6 +259,10 @@ struct hid_data {
 	int cc_value_index;
 	int num_expected;
 	int num_received;
+	int battery_capacity;
+	int bat_charging;
+	int bat_connected;
+	int ps_connected;
 };
 
 struct wacom_remote_data {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0c05b27..021da44 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -231,6 +231,7 @@ struct hid_item {
 #define HID_DG_TAP		0x000d0035
 #define HID_DG_TABLETFUNCTIONKEY	0x000d0039
 #define HID_DG_PROGRAMCHANGEKEY	0x000d003a
+#define HID_DG_BATTERYSTRENGTH	0x000d003b
 #define HID_DG_INVERT		0x000d003c
 #define HID_DG_TILT_X		0x000d003d
 #define HID_DG_TILT_Y		0x000d003e
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 17/18] HID: wacom: generic: Extend pad support
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (14 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  2016-10-07 22:16   ` [PATCH v2 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The HID specification that the MobileStudio Pro follows includes usages
for several values that would be good to support so that future devices
"just work" out of the box. Extend the HID_GENERIC pad codepath to handle
these usages.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 15 +++++++++++++++
 drivers/hid/wacom_wac.h |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 21c0ec3..8d4a3d3 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage)
 		    usage == WACOM_HID_WD_SERIALHI ||
 		    usage == WACOM_HID_WD_TOOLTYPE ||
 		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP2 ||
 		    usage == WACOM_HID_WD_TOUCHRING ||
 		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
 			return usage;
@@ -1512,6 +1514,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	case EV_MSC:
 		input_set_capability(input, EV_MSC, code);
 		break;
+	case EV_SW:
+		input_set_capability(input, EV_SW, code);
+		break;
 	}
 }
 
@@ -1546,11 +1551,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 	case WACOM_HID_WD_BUTTONDOWN:
 	case WACOM_HID_WD_BUTTONLEFT:
 	case WACOM_HID_WD_BUTTONRIGHT:
+	case WACOM_HID_WD_BUTTONCENTER:
 		wacom_map_usage(input, usage, field, EV_KEY,
 				wacom_numbered_button_to_key(features->numbered_buttons),
 				0);
 		features->numbered_buttons++;
 		break;
+	case WACOM_HID_WD_TOUCHONOFF:
+		wacom_map_usage(input, usage, field, EV_SW, SW_MUTE_DEVICE, 0);
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0);
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP2:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, 0);
+		break;
 	case WACOM_HID_WD_TOUCHRING:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index fa5b772..f70f7fd 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -96,6 +96,8 @@
 #define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHSTRIP         (WACOM_HID_UP_WACOMDIGITIZER | 0x0136)
+#define WACOM_HID_WD_TOUCHSTRIP2        (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)
 #define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
 #define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
 #define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
@@ -104,11 +106,14 @@
 #define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
 #define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_EXPRESSKEYCAP00    (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
 #define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
 #define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
 #define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
 #define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
 #define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
+#define WACOM_HID_WD_BUTTONCENTER       (WACOM_HID_UP_WACOMDIGITIZER | 0x0995)
+#define WACOM_HID_WD_TOUCHONOFF         (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
 #define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (15 preceding siblings ...)
  2016-10-07 22:16   ` [PATCH v2 17/18] HID: wacom: generic: Extend pad support Jason Gerecke
@ 2016-10-07 22:16   ` Jason Gerecke
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-07 22:16 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as
follows:

"A steering wheel is a single degree-of-freedom device that rotates about
an axis. The zero position is always the neutral or 'straight ahead'
position, with positive values turning clockwise and negative values
turning counterclockwise. If the Coordinate Values Wrap attribute is
set, the steering wheel can be turned past 360 degrees."

The hidinput_configure_usage function canonically maps this usage to the
ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis
as one for which it can calculate a resolution. This effectively prevents
wheels from being assigned a proper resolution that userspace can use
to determine the precise angle of input.

This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/hid-input.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index bcfaf32..81d35e9 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 	case ABS_RX:
 	case ABS_RY:
 	case ABS_RZ:
+	case ABS_WHEEL:
 	case ABS_TILT_X:
 	case ABS_TILT_Y:
 		if (field->unit == 0x14) {		/* If degrees */
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-07 22:16   ` [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
@ 2016-10-18 15:26     ` Jiri Kosina
  2016-10-18 17:09       ` Jason Gerecke
  0 siblings, 1 reply; 64+ messages in thread
From: Jiri Kosina @ 2016-10-18 15:26 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: linux-input, Benjamin Tissoires, Ping Cheng, Ping Cheng,
	Aaron Skomra, Jason Gerecke

On Fri, 7 Oct 2016, Jason Gerecke wrote:

> @@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
>  
>  
>  	if (usage->usage_index + 1 == field->report_count) {
> -		if (usage->hid == wacom_wac->features.last_slot_field)
> +		if (equivalent_usage == wacom_wac->features.last_slot_field)

What tree is this based on please? In all the codebase I have, 
last_slot_field is a member field of wacom_wac's hid_data, not a member of 
struct wacom_features.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-18 15:26     ` Jiri Kosina
@ 2016-10-18 17:09       ` Jason Gerecke
  2016-10-18 21:39         ` Jiri Kosina
  0 siblings, 1 reply; 64+ messages in thread
From: Jason Gerecke @ 2016-10-18 17:09 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-input, Benjamin Tissoires, Ping Cheng, Ping Cheng,
	Aaron Skomra, Jason Gerecke

On 10/18/2016 08:26 AM, Jiri Kosina wrote:
> On Fri, 7 Oct 2016, Jason Gerecke wrote:
> 
>> @@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
>>  
>>  
>>  	if (usage->usage_index + 1 == field->report_count) {
>> -		if (usage->hid == wacom_wac->features.last_slot_field)
>> +		if (equivalent_usage == wacom_wac->features.last_slot_field)
> 
> What tree is this based on please? In all the codebase I have, 
> last_slot_field is a member field of wacom_wac's hid_data, not a member of 
> struct wacom_features.
> 

This was based on your for-4.9/wacom tree, whose tip (for me) was commit
1924e05 ("HID: wacom - add touch_arbitration parameter to wacom module").

It looks like my tree only has commit 601a22f ("HID: wacom: Report input
events for each finger on generic devices") but not commit 003f50a
("HID: wacom: Update last_slot_field during pre_report phase"). Not sure
why though.

What would you like me to do?

Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-18 17:09       ` Jason Gerecke
@ 2016-10-18 21:39         ` Jiri Kosina
  2016-10-20  1:04           ` Jason Gerecke
  0 siblings, 1 reply; 64+ messages in thread
From: Jiri Kosina @ 2016-10-18 21:39 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: linux-input, Benjamin Tissoires, Ping Cheng, Ping Cheng,
	Aaron Skomra, Jason Gerecke

On Tue, 18 Oct 2016, Jason Gerecke wrote:

> >>  	if (usage->usage_index + 1 == field->report_count) {
> >> -		if (usage->hid == wacom_wac->features.last_slot_field)
> >> +		if (equivalent_usage == wacom_wac->features.last_slot_field)
> > 
> > What tree is this based on please? In all the codebase I have, 
> > last_slot_field is a member field of wacom_wac's hid_data, not a member of 
> > struct wacom_features.
> > 
> 
> This was based on your for-4.9/wacom tree, whose tip (for me) was commit
> 1924e05 ("HID: wacom - add touch_arbitration parameter to wacom module").
> 
> It looks like my tree only has commit 601a22f ("HID: wacom: Report input
> events for each finger on generic devices") 

Pardon me? That commit is from 2014 (3.19-rc1). It really shouldn't be 
used as a basis for a development.

> but not commit 003f50a ("HID: wacom: Update last_slot_field during 
> pre_report phase"). 

That's a commit that went in for 4.9-rc1 (authored by you).

> Not sure why though.
> 
> What would you like me to do?

Dunno where the confusion is coming from really. Could you please just 
rebase the patchset on top of something up to date (such as or Linus' 
git, master branch in my tree, or whatnot), and resubmit?

Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards
  2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
                   ` (20 preceding siblings ...)
  2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
@ 2016-10-20  1:03 ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
                     ` (16 more replies)
  21 siblings, 17 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Our loose use of "pen" and "digitizer" in the naming of several of our
vendor-defined usages may be a source of confusion given that the terms
have specific meaning within the HID specification. "Pen" specifically
refers to "an integrated display that allows the use of a stylus" (e.g.
something like a tablet PC or Cintiq) wheras "Digitizer" is a better
fit for opaque tablets like an Intuos.

While we're at it, go ahead and rename the definitions to make them more
distinct and better match up with the convention used by HID (e.g. the use
of '_UP_' for usage pages) and make them more distinct.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 12 ++++++------
 drivers/hid/wacom_wac.c |  2 +-
 drivers/hid/wacom_wac.h | 17 +++++++++--------
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 5e7a564..773fa11 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -159,18 +159,18 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 
 	case HID_UP_DIGITIZER:
 		if (field->report->id == 0x0B &&
-		    (field->application == WACOM_G9_DIGITIZER ||
-		     field->application == WACOM_G11_DIGITIZER)) {
+		    (field->application == WACOM_HID_G9_PEN ||
+		     field->application == WACOM_HID_G11_PEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
 
-	case WACOM_G9_PAGE:
-	case WACOM_G11_PAGE:
+	case WACOM_HID_UP_G9:
+	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
-		    (field->application == WACOM_G9_TOUCHSCREEN ||
-		     field->application == WACOM_G11_TOUCHSCREEN)) {
+		    (field->application == WACOM_HID_G9_TOUCHSCREEN ||
+		     field->application == WACOM_HID_G11_TOUCHSCREEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 1cb7992..3038954 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2448,7 +2448,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 	/*
 	 * Raw Wacom-mode pen and touch events both come from interface
 	 * 0, whose HID descriptor has an application usage of 0xFF0D
-	 * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
+	 * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back
 	 * out through the HID_GENERIC device created for interface 1,
 	 * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
 	 */
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 324c40b..f58bbd1 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -84,20 +84,21 @@
 #define WACOM_DEVICETYPE_WL_MONITOR     0x0008
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
-#define WACOM_VENDORDEFINED_PEN		0xff0d0001
-#define WACOM_G9_PAGE			0xff090000
-#define WACOM_G9_DIGITIZER		(WACOM_G9_PAGE | 0x02)
-#define WACOM_G9_TOUCHSCREEN		(WACOM_G9_PAGE | 0x11)
-#define WACOM_G11_PAGE			0xff110000
-#define WACOM_G11_DIGITIZER		(WACOM_G11_PAGE | 0x02)
-#define WACOM_G11_TOUCHSCREEN		(WACOM_G11_PAGE | 0x11)
+#define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_UP_G9                 0xff090000
+#define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
+#define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
+#define WACOM_HID_UP_G11                0xff110000
+#define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
+#define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
 
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_VENDORDEFINED_PEN))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
 				 ((f)->application == HID_DG_TOUCHSCREEN))
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 03/18] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
                     ` (15 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

We've defined several new usages (e.g. WACOM_G9_PEN and WACOM_G9_TOUCHSCREEN)
which aren't checked by the WACOM_PEN_FIELD and WACOM_FINGER_FIELD macros but
probably should be.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index f58bbd1..d2629c8 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -98,10 +98,14 @@
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_HID_WD_DIGITIZER))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER) || \
+				 ((f)->application == WACOM_HID_G9_PEN) || \
+				 ((f)->application == WACOM_HID_G11_PEN))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
-				 ((f)->application == HID_DG_TOUCHSCREEN))
+				 ((f)->application == HID_DG_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G11_TOUCHSCREEN))
 
 enum {
 	PENPARTNER = 0,
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 03/18] HID: wacom: Refactor button-to-key translation into function
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
                     ` (14 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

This just centralizes the logic used in both wacom_setup_numbered_buttons
and wacom_report_numbered_buttons so that they don't drift out of sync.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 3038954..8071c18 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2769,17 +2769,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
 	return 0;
 }
 
+static int wacom_numbered_button_to_key(int n)
+{
+	if (n < 10)
+		return BTN_0 + n;
+	else if (n < 16)
+		return BTN_A + (n-10);
+	else if (n < 18)
+		return BTN_BASE + (n-16);
+	else
+		return 0;
+}
+
 static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
 				int button_count)
 {
 	int i;
 
-	for (i = 0; i < button_count && i < 10; i++)
-		__set_bit(BTN_0 + i, input_dev->keybit);
-	for (i = 10; i < button_count && i < 16; i++)
-		__set_bit(BTN_A + (i-10), input_dev->keybit);
-	for (i = 16; i < button_count && i < 18; i++)
-		__set_bit(BTN_BASE + (i-16), input_dev->keybit);
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			__set_bit(key, input_dev->keybit);
+	}
 }
 
 static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group)
@@ -2881,12 +2893,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 	for (i = 0; i < wacom->led.count; i++)
 		wacom_update_led(wacom,  button_count, mask, i);
 
-	for (i = 0; i < button_count && i < 10; i++)
-		input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
-	for (i = 10; i < button_count && i < 16; i++)
-		input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
-	for (i = 16; i < button_count && i < 18; i++)
-		input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			input_report_key(input_dev, key, mask & (1 << i));
+	}
 }
 
 int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 03/18] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 05/18] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
                     ` (13 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

ISDv4 devices have long supported reporting data from each of two barrel
switches, but HID_DG_BARRELSWITCH2 itself was only recently standardized.
Prior to its adoption, ISDv4 devices would associate the bit indicating
the state of the second barrel switch with the "Undefined" 0x000D0000
usage. Although most such devices have explicit support, a few use the
HID_GENERIC codepath which ignores the "Undefined" usage.

This patch adds code which detects the presence of a pre-standard second
barrel switch and corrects the usage value so that the HID_GENERIC code
will declare its presence and report its state.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 773fa11..033cc03 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -240,6 +240,30 @@ static void wacom_usage_mapping(struct hid_device *hdev,
 			features->touch_max = 1;
 	}
 
+	/*
+	 * ISDv4 devices which predate HID's adoption of the
+	 * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
+	 * position instead. We can accurately detect if a
+	 * usage with that value should be HID_DG_BARRELSWITCH2
+	 * based on the surrounding usages, which have remained
+	 * constant across generations.
+	 */
+	if (features->type == HID_GENERIC &&
+	    usage->hid == 0x000D0000 &&
+	    field->application == HID_DG_PEN &&
+	    field->physical == HID_DG_STYLUS) {
+		int i = usage->usage_index;
+
+		if (i-4 >= 0 && i+1 < field->maxusage &&
+		    field->usage[i-4].hid == HID_DG_TIPSWITCH &&
+		    field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
+		    field->usage[i-2].hid == HID_DG_ERASER &&
+		    field->usage[i-1].hid == HID_DG_INVERT &&
+		    field->usage[i+1].hid == HID_DG_INRANGE) {
+			usage->hid = HID_DG_BARRELSWITCH2;
+		}
+	}
+
 	switch (usage->hid) {
 	case HID_GD_X:
 		features->x_max = field->logical_maximum;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 05/18] HID: wacom: generic: Strip off excessive name prefixing
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (2 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
                     ` (12 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The product name received from the string descriptor in the new MobileStudio
Pro line of tablets begins with "Wacom", which leads to unnecessary visual
noise in the device name when appended to the vendor name which also includes
"Wacom". Look for and fix cases like this.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 033cc03..7b9bff2 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1940,6 +1940,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
 				/* shift everything including the terminator */
 				memmove(gap, gap+1, strlen(gap));
 			}
+
+			/* strip off excessive prefixing */
+			if (strstr(name, "Wacom Co.,Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co.,Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+			if (strstr(name, "Wacom Co., Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co., Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+
 			/* get rid of trailing whitespace */
 			if (name[strlen(name)-1] == ' ')
 				name[strlen(name)-1] = '\0';
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (3 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 05/18] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
                     ` (11 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The HID standard defines usages that allow digitizers to report the pen's
height, tilt, and rotation and which are used by Wacom's new "MobileStudio
Pro" devices.

Note that 'hidinput_calc_abs_res' expects ABS_Z (historically used by our
driver to report twist) to have linear units. To ensure it calculates a
resolution with the actually-angular units provided in the HID descriptor
we nedd to lie and tell it we're calculating it for the (rotational) ABS_RZ
axis instead.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 28 ++++++++++++++++++++++++++--
 include/linux/hid.h     |  3 +++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 8071c18..3f4ba53 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1440,6 +1440,11 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 {
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	int resolution_code = code;
+
+	if (usage->hid == HID_DG_TWIST) {
+		resolution_code = ABS_RZ;
+	}
 
 	usage->type = type;
 	usage->code = code;
@@ -1450,7 +1455,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	case EV_ABS:
 		input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
 		input_abs_set_res(input, code,
-				  hidinput_calc_abs_res(field, code));
+				  hidinput_calc_abs_res(field, resolution_code));
 		break;
 	case EV_KEY:
 		input_set_capability(input, EV_KEY, code);
@@ -1475,6 +1480,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case HID_GD_Z:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
+		break;
 	case HID_DG_TIPPRESSURE:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
 		break;
@@ -1485,6 +1493,15 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		wacom_map_usage(input, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
 		break;
+	case HID_DG_TILT_X:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
+		break;
+	case HID_DG_TILT_Y:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
+		break;
+	case HID_DG_TWIST:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		break;
 	case HID_DG_ERASER:
 	case HID_DG_TIPSWITCH:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
@@ -1508,8 +1525,15 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 
-	/* checking which Tool / tip switch to send */
 	switch (usage->hid) {
+	case HID_GD_Z:
+		/*
+		 * HID_GD_Z "should increase as the control's position is
+		 * moved from high to low", while ABS_DISTANCE instead
+		 * increases in value as the tool moves from low to high.
+		 */
+		value = field->logical_maximum - value;
+		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
 		return 0;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index b2ec827..e712101 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -232,6 +232,9 @@ struct hid_item {
 #define HID_DG_TABLETFUNCTIONKEY	0x000d0039
 #define HID_DG_PROGRAMCHANGEKEY	0x000d003a
 #define HID_DG_INVERT		0x000d003c
+#define HID_DG_TILT_X		0x000d003d
+#define HID_DG_TILT_Y		0x000d003e
+#define HID_DG_TWIST		0x000d0041
 #define HID_DG_TIPSWITCH	0x000d0042
 #define HID_DG_TIPSWITCH2	0x000d0043
 #define HID_DG_BARRELSWITCH	0x000d0044
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (4 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
                     ` (10 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom's new "MobileStudio Pro" tablets are the first devices in their
branded product line-up to include a usable HID descriptor for the pen
interface. Like prior branded products, the device can operate in one
of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the
first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is
subject to some restrictions -- most notably pressure being limited
to 2048 levels instead of 8192. To ensure tablets that include support
for Custom HID mode work optimally, we add support for its usages and
switch the device to Custom HID mode if possible.

The usages defined for Custom HID mode are often numerically similar to
their standard HID equivalents, allowing us to write a simple translation
function that takes arbitrary HID usages as input and which returns
the corresponding standard HID usage as output (if one exists). Switching
on this translated usage instead of the actual usage allows the existing
cases to apply to both modes of operation without having to explicitly
define every Custom HID usage.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c |  5 +++++
 drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------
 drivers/hid/wacom_wac.h |  3 +++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 7b9bff2..b2e2471 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 		}
 		break;
 
+	case WACOM_HID_WD_DATAMODE:
+		wacom->wacom_wac.mode_report = field->report->id;
+		wacom->wacom_wac.mode_value = 2;
+		break;
+
 	case WACOM_HID_UP_G9:
 	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 3f4ba53..6c2f0e4 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 	return 0;
 }
 
+static int wacom_equivalent_usage(int usage)
+{
+	if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) {
+		int subpage = (usage & 0xFF00) << 8;
+		int subusage = (usage & 0xFF);
+
+		if (subpage == WACOM_HID_SP_DIGITIZER ||
+		    subpage == WACOM_HID_SP_DIGITIZERINFO) {
+			return usage;
+		}
+
+		if (subpage == HID_UP_UNDEFINED)
+			subpage = HID_UP_DIGITIZER;
+
+		return subpage | subusage;
+	}
+
+	return usage;
+}
+
 static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		struct hid_field *field, __u8 type, __u16 code, int fuzz)
 {
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
 	int resolution_code = code;
 
-	if (usage->hid == HID_DG_TWIST) {
+	if (equivalent_usage == HID_DG_TWIST) {
 		resolution_code = ABS_RZ;
 	}
 
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
 		break;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_Z:
 		/*
 		 * HID_GD_Z "should increase as the control's position is
@@ -1597,8 +1620,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->touch_input;
 	unsigned touch_max = wacom_wac->features.touch_max;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		if (touch_max == 1)
 			wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
@@ -1673,8 +1697,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_wac->hid_data.x = value;
 		break;
@@ -1697,7 +1722,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
 
 
 	if (usage->usage_index + 1 == field->report_count) {
-		if (usage->hid == wacom_wac->hid_data.last_slot_field)
+		if (equivalent_usage == wacom_wac->hid_data.last_slot_field)
 			wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
 	}
 
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index d2629c8..ba914ba 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -85,7 +85,10 @@
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
 #define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_DIGITIZER          0x000d0000
+#define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
 #define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (5 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
                     ` (9 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The vendor-defined 0xFF0D01032 ("Distance") usage is nearly equivalent to
HID_GD_Z, except that the axis direction is inverted. Unlike HID_GD_Z which
increases in value as the pen-to-surface distance is decreased, this usage
decreases. Treat this usage as a special case to ensure we don't invert the
scale to be ABS_DISTANCE compatible like we do for HID_GD_Z.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 4 +++-
 drivers/hid/wacom_wac.h | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 6c2f0e4..f78ad77 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1442,7 +1442,8 @@ static int wacom_equivalent_usage(int usage)
 		int subusage = (usage & 0xFF);
 
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
-		    subpage == WACOM_HID_SP_DIGITIZERINFO) {
+		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
 
@@ -1502,6 +1503,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case WACOM_HID_WD_DISTANCE:
 	case HID_GD_Z:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
 		break;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index ba914ba..63a5a25 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -88,6 +88,7 @@
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (6 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
                     ` (8 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The airbrush fingerwheel does not have a usage that corresponds cleanly
with a standard HID usage, so we add explicit support for it via its
vendor-defined usage.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 3 +++
 drivers/hid/wacom_wac.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index f78ad77..81467c9 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1539,6 +1539,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_FINGERWHEEL:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
 	}
 }
 
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 63a5a25..5447559 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -89,6 +89,7 @@
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (7 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
                     ` (7 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Wacom's professional tablets beginning with the Intuos4 are capable of
reporting an intermediate degree of proximity where the pen is no longer
close enough to communicate with ("in prox"), but still close enough to
be sensed ("in range"). This additional state is particularly useful for
performing palm rejection as it allows the driver to disable the touch
sensor while the pen is a greater distance from the tablet.

Like other professional tablets, the new MobileStudio Pro also reports
this intermeidate "in range" proximity state. Its descriptor assigns
usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would
translate this to the standard HID "Quality" usage, but since this has
a different meaning we have it explicitly ignore the usage and define
it ourselves as "Sense" (since "In Range" is already defined by the
HID standard and interpreted by our driver as meaning "in prox").

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 26 +++++++++++++++++++++++---
 drivers/hid/wacom_wac.h |  3 +++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 81467c9..c0d75ae 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)
 
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_SENSE ||
 		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
@@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
@@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_SENSE:
+		features->quirks |= WACOM_QUIRK_SENSE;
+		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+		break;
 	case WACOM_HID_WD_FINGERWHEEL:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
@@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
@@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
+		if (!(features->quirks & WACOM_QUIRK_SENSE))
+			wacom_wac->hid_data.sense_state = value;
 		return 0;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
@@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
 		return 0;
+	case WACOM_HID_WD_SENSE:
+		wacom_wac->hid_data.sense_state = value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
@@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	if (!usage->type || delay_pen_events(wacom_wac))
 		return 0;
 
+	/* send pen events only when the pen is in/entering/leaving proximity */
+	if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
+		return 0;
+
 	input_event(input, usage->type, usage->code, value);
 
 	return 0;
@@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 	bool prox = wacom_wac->hid_data.inrange_state;
+	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) /* first in prox */
 		/* Going into proximity select tool */
 		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
 						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
 	/* keep pen state for touch events */
-	wacom_wac->shared->stylus_in_proximity = prox;
+	wacom_wac->shared->stylus_in_proximity = range;
 
-	if (!delay_pen_events(wacom_wac)) {
+	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
@@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 
 		input_sync(input);
 	}
+
+	if (!prox)
+		wacom_wac->tool[0] = 0;
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 5447559..c27b7b4 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -74,6 +74,7 @@
 
 /* device quirks */
 #define WACOM_QUIRK_BBTOUCH_LOWRES	0x0001
+#define WACOM_QUIRK_SENSE		0x0002
 #define WACOM_QUIRK_BATTERY		0x0008
 
 /* device types */
@@ -88,6 +89,7 @@
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -212,6 +214,7 @@ struct wacom_shared {
 struct hid_data {
 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
+	bool sense_state;
 	bool inrange_state;
 	bool invert_state;
 	bool tipswitch;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (8 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 12/18] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
                     ` (6 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The 'wacom_intuos_inout' function incorrectly assmebles tool IDs from the
proximity report, shifting the higher values of the ID four bits farther
than intended. This problem was not detected until too late, but has not
caused any issues since the incorrect IDs still fit in a 32-bit integer
and userspace programs have not required the value to match the hardware
(just that the values are unique and constant).

The tool IDs reported by the new MobileStudio Pro (or any future
HID_GENERIC device that supports them) do not suffer from the same
assembly issue, however. In order for 'wacom_intuos_get_tool_type' to
work for with both codepaths, we correct this issue internally and
have 'wacom_intuos_general' only mangle the ID when it is posted to
userspace.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index c0d75ae..df9d866 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -588,6 +588,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
 	return 1;
 }
 
+static int wacom_intuos_id_mangle(int tool_id)
+{
+	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
+}
+
 static int wacom_intuos_get_tool_type(int tool_id)
 {
 	int tool_type;
@@ -595,7 +600,7 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	switch (tool_id) {
 	case 0x812: /* Inking pen */
 	case 0x801: /* Intuos3 Inking pen */
-	case 0x120802: /* Intuos4/5 Inking Pen */
+	case 0x12802: /* Intuos4/5 Inking Pen */
 	case 0x012:
 		tool_type = BTN_TOOL_PENCIL;
 		break;
@@ -610,11 +615,11 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
 	case 0x8e2: /* IntuosHT2 pen */
 	case 0x022:
-	case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
-	case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
-	case 0x160802: /* Cintiq 13HD Pro Pen */
-	case 0x180802: /* DTH2242 Pen */
-	case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
+	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+	case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
+	case 0x16802: /* Cintiq 13HD Pro Pen */
+	case 0x18802: /* DTH2242 Pen */
+	case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
 		tool_type = BTN_TOOL_PEN;
 		break;
 
@@ -648,12 +653,12 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
 	case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 	case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
-	case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
-	case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
-	case 0x18080a: /* DTH2242 Eraser */
-	case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
+	case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
+	case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
+	case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
+	case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
+	case 0x1880a: /* DTH2242 Eraser */
+	case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 		tool_type = BTN_TOOL_RUBBER;
 		break;
 
@@ -662,7 +667,7 @@ static int wacom_intuos_get_tool_type(int tool_id)
 	case 0x112:
 	case 0x913: /* Intuos3 Airbrush */
 	case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
-	case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
+	case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
 		tool_type = BTN_TOOL_AIRBRUSH;
 		break;
 
@@ -693,7 +698,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 			(data[6] << 4) + (data[7] >> 4);
 
 		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
-			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
+		     ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8);
 
 		wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);
 
@@ -923,7 +928,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
 	 * don't report events for invalid data
 	 */
 	/* older I4 styli don't work with new Cintiqs */
-	if ((!((wacom->id[idx] >> 20) & 0x01) &&
+	if ((!((wacom->id[idx] >> 16) & 0x01) &&
 			(features->type == WACOM_21UX2)) ||
 	    /* Only large Intuos support Lense Cursor */
 	    (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1064,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
 		break;
 	}
 
-	input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
+	input_report_abs(input, ABS_MISC,
+			 wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */
 	input_report_key(input, wacom->tool[idx], 1);
 	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 	wacom->reporting_data = true;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 12/18] HID: wacom: generic: Support tool ID and additional tool types
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (9 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
                     ` (5 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Devices following the new Custom HID mode specification (as well as even
some recent component sensors which use the same standard HID usage)
are capable of reporting tool ID information that we need to relay to
userspace. This patch adds support for reading and relaying the tool
type information, which is (unfortunately) split across two usages.
We also advertise the existence of tool types beyond BTN_TOOL_PEN
that might be available.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++---
 drivers/hid/wacom_wac.h |  4 ++-
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index df9d866..85e1ad1 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1450,6 +1450,8 @@ static int wacom_equivalent_usage(int usage)
 		if (subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
 		    usage == WACOM_HID_WD_SENSE ||
+		    usage == WACOM_HID_WD_SERIALHI ||
+		    usage == WACOM_HID_WD_TOOLTYPE ||
 		    usage == WACOM_HID_WD_DISTANCE) {
 			return usage;
 		}
@@ -1551,6 +1553,17 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		features->quirks |= WACOM_QUIRK_SENSE;
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
+		set_bit(EV_KEY, input->evbit);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
+		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
+		input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
+		input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
+		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
+		break;
 	case WACOM_HID_WD_FINGERWHEEL:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
@@ -1587,9 +1600,35 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
 		return 0;
+	case HID_DG_TOOLSERIALNUMBER:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFF);
+		wacom_wac->serial[0] |= value;
+		return 0;
 	case WACOM_HID_WD_SENSE:
 		wacom_wac->hid_data.sense_state = value;
 		return 0;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
+		wacom_wac->serial[0] |= ((__u64)value) << 32;
+		/*
+		 * Non-USI EMR devices may contain additional tool type
+		 * information here. See WACOM_HID_WD_TOOLTYPE case for
+		 * more details.
+		 */
+		if (value >> 20 == 1) {
+			wacom_wac->id[0] |= value & 0xFFFFF;
+		}
+		return 0;
+	case WACOM_HID_WD_TOOLTYPE:
+		/*
+		 * Some devices (MobileStudio Pro, and possibly later
+		 * devices as well) do not return the complete tool
+		 * type in their WACOM_HID_WD_TOOLTYPE usage. Use a
+		 * bitwise OR so the complete value can be built
+		 * up over time :(
+		 */
+		wacom_wac->id[0] |= value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
@@ -1622,26 +1661,51 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 	bool prox = wacom_wac->hid_data.inrange_state;
 	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->tool[0] && prox) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) { /* first in prox */
 		/* Going into proximity select tool */
-		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
-						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		if (wacom_wac->hid_data.invert_state)
+			wacom_wac->tool[0] = BTN_TOOL_RUBBER;
+		else if (wacom_wac->id[0])
+			wacom_wac->tool[0] = wacom_intuos_get_tool_type(wacom_wac->id[0]);
+		else
+			wacom_wac->tool[0] = BTN_TOOL_PEN;
+	}
 
 	/* keep pen state for touch events */
 	wacom_wac->shared->stylus_in_proximity = range;
 
 	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
+		int id = wacom_wac->id[0];
+
+		/*
+		 * Non-USI EMR tools should have their IDs mangled to
+		 * match the legacy behavior of wacom_intuos_general
+		 */
+		if (wacom_wac->serial[0] >> 52 == 1)
+			id = wacom_intuos_id_mangle(id);
+
+		/*
+		 * To ensure compatibility with xf86-input-wacom, we should
+		 * report the BTN_TOOL_* event prior to the ABS_MISC or
+		 * MSC_SERIAL events.
+		 */
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
+		if (wacom_wac->serial[0]) {
+			input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+			input_report_abs(input, ABS_MISC, id);
+		}
 
 		wacom_wac->hid_data.tipswitch = false;
 
 		input_sync(input);
 	}
 
-	if (!prox)
+	if (!prox) {
 		wacom_wac->tool[0] = 0;
+		wacom_wac->id[0] = 0;
+	}
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index c27b7b4..83ddb2a0 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -90,6 +90,8 @@
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
+#define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
@@ -247,7 +249,7 @@ struct wacom_wac {
 	unsigned char data[WACOM_PKGLEN_MAX];
 	int tool[2];
 	int id[2];
-	__u32 serial[2];
+	__u64 serial[2];
 	bool reporting_data;
 	struct wacom_features features;
 	struct wacom_shared *shared;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (10 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 12/18] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 14/18] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
                     ` (4 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Many of Wacom's display tablets include an "outbound" area where pen
digitizing is possible but outside of the display area. To ensure that
pen coordinates are mapped to the correct on-screen location, the driver
sets the minimum and maximum axis values of X and Y to those coordinates
which coincide with the screen edge. These values are simply the
hardware minimum/maximum plus/minus the outbound size for a particular
edge.

When outbound support was added/updated in ac414da, fa77034, and
ecd618d, we decided to have the wacom_features structs store the desired
minimum and maximum values directly. In hindsight, this was perhaps not
the best choice since it has allowed minor errors to crop up unnoticed.
Some tablets have had their coordinates over-corrected (e.g. most of the
devices "fixed" in ecd618d were already adjusted in ac414da), while
others never had a correction applied (e.g. the ISDv5 325, whose
declared maximum the hardware maximum instead of the outbound maximum).

A less error-prone method of handling the outbound is to let the driver
calculate the correct minimum/maximum values by providing it with both
the actual hardware maximums and the size of the outbound on each edge.
These values are more easy to verify as correct since the values can be
trivially compared against specifications.

This patch reverts the declared maximum values to the actual hardware
maximums, e.g. as declared prior to ac414da (values for these and other
display tablets that were subsuquently introduced have been verified
against specs). Per-edge outbound sizes are stored in the wacom_features
struct as offset_{left,right,top,bottom} and used in combination with
the hardware ranges to calculate effective axis ranges for ABS_X and
ABS_Y.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 62 ++++++++++++++++++++++++++++++++-----------------
 drivers/hid/wacom_wac.h |  6 +++--
 2 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 85e1ad1..5046071 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2674,10 +2674,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(ABS_MISC, input_dev->absbit);
 
-	input_set_abs_params(input_dev, ABS_X, features->x_min,
-			     features->x_max, features->x_fuzz, 0);
-	input_set_abs_params(input_dev, ABS_Y, features->y_min,
-			     features->y_max, features->y_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_X, 0 + features->offset_left,
+			     features->x_max - features->offset_right,
+			     features->x_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0 + features->offset_top,
+			     features->y_max - features->offset_bottom,
+			     features->y_fuzz, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0,
 		features->pressure_max, features->pressure_fuzz, 0);
 
@@ -3389,26 +3391,30 @@ static const struct wacom_features wacom_features_0x317 =
 	  INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xF4 =
-	{ "Wacom Cintiq 24HD", 104080, 65200, 2047, 63,
+	{ "Wacom Cintiq 24HD", 104480, 65600, 2047, 63,
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xF8 =
-	{ "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */
+	{ "Wacom Cintiq 24HD touch", 104480, 65600, 2047, 63, /* Pen */
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
 static const struct wacom_features wacom_features_0xF6 =
 	{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x32A =
-	{ "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x32B =
-	{ "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD touch", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
 static const struct wacom_features wacom_features_0x32C =
 	{ "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT,
@@ -3423,13 +3429,15 @@ static const struct wacom_features wacom_features_0xC6 =
 	{ "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
 	  WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
 static const struct wacom_features wacom_features_0x304 =
-	{ "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
+	{ "Wacom Cintiq 13HD", 59552, 33848, 1023, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x333 =
-	{ "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
+	{ "Wacom Cintiq 13HD touch", 59552, 33848, 2047, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
 static const struct wacom_features wacom_features_0x335 =
 	{ "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3446,42 +3454,50 @@ static const struct wacom_features wacom_features_0xF0 =
 	{ "Wacom DTU1631", 34623, 19553, 511, 0,
 	  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xFB =
-	{ "Wacom DTU1031", 21896, 13760, 511, 0,
+	{ "Wacom DTU1031", 22096, 13960, 511, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x32F =
-	{ "Wacom DTU1031X", 22472, 12728, 511, 0,
+	{ "Wacom DTU1031X", 22672, 12928, 511, 0,
 	  DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x336 =
-	{ "Wacom DTU1141", 23472, 13203, 1023, 0,
+	{ "Wacom DTU1141", 23672, 13403, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x57 =
-	{ "Wacom DTK2241", 95640, 54060, 2047, 63,
+	{ "Wacom DTK2241", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x59 = /* Pen */
-	{ "Wacom DTH2242", 95640, 54060, 2047, 63,
+	{ "Wacom DTH2242", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
 static const struct wacom_features wacom_features_0x5D = /* Touch */
 	{ "Wacom DTH2242",       .type = WACOM_24HDT,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xCC =
-	{ "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63,
+	{ "Wacom Cintiq 21UX2", 87200, 65600, 2047, 63,
 	  WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xFA =
-	{ "Wacom Cintiq 22HD", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HD", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x5B =
-	{ "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HDT", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
 static const struct wacom_features wacom_features_0x5E =
 	{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3625,18 +3641,20 @@ static const struct wacom_features wacom_features_0x6004 =
 	{ "ISD-V4", 12800, 8000, 255, 0,
 	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x307 =
-	{ "Wacom ISDv5 307", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 307", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
 static const struct wacom_features wacom_features_0x309 =
 	{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x30A =
-	{ "Wacom ISDv5 30A", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 30A", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
 static const struct wacom_features wacom_features_0x30C =
 	{ "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3652,6 +3670,7 @@ static const struct wacom_features wacom_features_0x325 =
 	{ "Wacom ISDv5 325", 59552, 33848, 2047, 63,
 	  CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };
 static const struct wacom_features wacom_features_0x326 = /* Touch */
 	{ "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3681,8 +3700,9 @@ static const struct wacom_features wacom_features_0x33E =
 	  INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x343 =
-	{ "Wacom DTK1651", 34616, 19559, 1023, 0,
+	{ "Wacom DTK1651", 34816, 19759, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 83ddb2a0..5c5c689 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -181,8 +181,10 @@ struct wacom_features {
 	int x_resolution;
 	int y_resolution;
 	int numbered_buttons;
-	int x_min;
-	int y_min;
+	int offset_left;
+	int offset_right;
+	int offset_top;
+	int offset_bottom;
 	int device_type;
 	int x_phy;
 	int y_phy;
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 14/18] HID: wacom: generic: Add support for sensor offsets
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (11 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 15/18] HID: wacom: generic: Introduce pad support Jason Gerecke
                     ` (3 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Many of Wacom's display tablets include an "outbound" area where pen
digitizing is possible but outside of the display area. To accommodate
such sensors in the HID_GENERIC codepath, we add support for the
necessary vendor-defined HID feature usages and adjust the min/max
values of the X and Y axes accordingly, similar to what is done in
the non-generic codepath.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_sys.c | 38 ++++++++++++++++++++++++++++++--------
 drivers/hid/wacom_wac.c | 40 ++++++++++++++++++++++++++++++++++++++++
 drivers/hid/wacom_wac.h |  4 ++++
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index b2e2471..b9779bc 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 	struct hid_data *hid_data = &wacom->wacom_wac.hid_data;
 	u8 *data;
 	int ret;
+	int n;
 
 	switch (usage->hid) {
 	case HID_DG_CONTACTMAX:
@@ -180,6 +181,27 @@ static void wacom_feature_mapping(struct hid_device *hdev,
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
+	case WACOM_HID_WD_OFFSETLEFT:
+	case WACOM_HID_WD_OFFSETTOP:
+	case WACOM_HID_WD_OFFSETRIGHT:
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		/* read manually */
+		n = hid_report_len(field->report);
+		data = hid_alloc_report_buf(field->report, GFP_KERNEL);
+		if (!data)
+			break;
+		data[0] = field->report->id;
+		ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
+					data, n, WAC_CMD_RETRIES);
+		if (ret == n) {
+			ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+						   data, n, 0);
+		} else {
+			hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+				 __func__);
+		}
+		kfree(data);
+		break;
 	}
 }
 
@@ -718,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)
 		return retval;
 	}
 
-	if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
-		wacom_wac->shared->touch = hdev;
-	else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
-		wacom_wac->shared->pen = hdev;
-
 out:
 	mutex_unlock(&wacom_udev_list_lock);
 	return retval;
@@ -2019,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 	if (error)
 		goto fail;
 
+	error = wacom_add_shared_data(hdev);
+	if (error)
+		goto fail;
+
 	/*
 	 * Bamboo Pad has a generic hid handling for the Pen, and we switch it
 	 * into debug mode for the touch part.
@@ -2059,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 
 	wacom_update_name(wacom, wireless ? " (WL)" : "");
 
-	error = wacom_add_shared_data(hdev);
-	if (error)
-		goto fail;
+	if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
+		wacom_wac->shared->touch = hdev;
+	else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
+		wacom_wac->shared->pen = hdev;
 
 	if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
 	     (features->quirks & WACOM_QUIRK_BATTERY)) {
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 5046071..3bb6dd6 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1468,6 +1468,9 @@ static int wacom_equivalent_usage(int usage)
 static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		struct hid_field *field, __u8 type, __u16 code, int fuzz)
 {
+	struct wacom *wacom = input_get_drvdata(input);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
 	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
@@ -1477,6 +1480,15 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		resolution_code = ABS_RZ;
 	}
 
+	if (equivalent_usage == HID_GD_X) {
+		fmin += features->offset_left;
+		fmax -= features->offset_right;
+	}
+	if (equivalent_usage == HID_GD_Y) {
+		fmin += features->offset_top;
+		fmax -= features->offset_bottom;
+	}
+
 	usage->type = type;
 	usage->code = code;
 
@@ -1629,6 +1641,34 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		 */
 		wacom_wac->id[0] |= value;
 		return 0;
+	case WACOM_HID_WD_OFFSETLEFT:
+		if (features->offset_left && value != features->offset_left)
+			hid_warn(hdev, "%s: overriding exising left offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_left);
+		features->offset_left = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETRIGHT:
+		if (features->offset_right && value != features->offset_right)
+			hid_warn(hdev, "%s: overriding exising right offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_right);
+		features->offset_right = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETTOP:
+		if (features->offset_top && value != features->offset_top)
+			hid_warn(hdev, "%s: overriding exising top offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_top);
+		features->offset_top = value;
+		return 0;
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		if (features->offset_bottom && value != features->offset_bottom)
+			hid_warn(hdev, "%s: overriding exising bottom offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_bottom);
+		features->offset_bottom = value;
+		return 0;
 	}
 
 	/* send pen events only when touch is up or forced out
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 5c5c689..b4c3c64 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -94,6 +94,10 @@
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
+#define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
+#define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
+#define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
+#define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 15/18] HID: wacom: generic: Introduce pad support
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (12 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 14/18] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
                     ` (2 subsequent siblings)
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

As with usages for the pen, the Custom HID specificiation includes
usages for the pad. Here we add functions to map and handle most
of the pad usages present on the MobileStudio Pro.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 143 ++++++++++++++++++++++++++++++++++++++++++------
 drivers/hid/wacom_wac.h |  19 +++++++
 2 files changed, 146 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 3bb6dd6..70de1fa 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");
 static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 				int button_count, int mask);
 
+static int wacom_numbered_button_to_key(int n);
+
 /*
  * Percent of battery capacity for Graphire.
  * 8th value means AC online and show 100% capacity.
@@ -1447,12 +1449,16 @@ static int wacom_equivalent_usage(int usage)
 		int subpage = (usage & 0xFF00) << 8;
 		int subusage = (usage & 0xFF);
 
-		if (subpage == WACOM_HID_SP_DIGITIZER ||
+		if (subpage == WACOM_HID_SP_PAD ||
+		    subpage == WACOM_HID_SP_BUTTON ||
+		    subpage == WACOM_HID_SP_DIGITIZER ||
 		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
 		    usage == WACOM_HID_WD_SENSE ||
 		    usage == WACOM_HID_WD_SERIALHI ||
 		    usage == WACOM_HID_WD_TOOLTYPE ||
-		    usage == WACOM_HID_WD_DISTANCE) {
+		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHRING ||
+		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
 			return usage;
 		}
 
@@ -1509,6 +1515,98 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	}
 }
 
+static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_ACCELEROMETER_X:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Y:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 0);
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Z:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		break;
+	case WACOM_HID_WD_BUTTONHOME:
+	case WACOM_HID_WD_BUTTONUP:
+	case WACOM_HID_WD_BUTTONDOWN:
+	case WACOM_HID_WD_BUTTONLEFT:
+	case WACOM_HID_WD_BUTTONRIGHT:
+		wacom_map_usage(input, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		break;
+	case WACOM_HID_WD_TOUCHRING:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
+	}
+
+	switch (equivalent_usage & 0xfffffff0) {
+	case WACOM_HID_WD_EXPRESSKEY00:
+		wacom_map_usage(input, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		break;
+	}
+}
+
+static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) {
+		wacom_wac->hid_data.inrange_state |= value;
+	}
+
+	if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS)
+		input_event(input, usage->type, usage->code, value);
+
+	return 0;
+}
+
+static void wacom_wac_pad_pre_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+	wacom_wac->hid_data.inrange_state = 0;
+}
+
+static void wacom_wac_pad_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	bool active = wacom_wac->hid_data.inrange_state != 0;
+
+	/*
+	 * don't report prox for events like accelerometer
+	 * or battery status
+	 */
+	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY)
+		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
+
+	input_sync(input);
+}
+
 static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
@@ -1946,10 +2044,11 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,
 	/* currently, only direct devices have proper hid report descriptors */
 	features->device_type |= WACOM_DEVICETYPE_DIRECT;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_usage_mapping(hdev, field, usage);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_usage_mapping(hdev, field, usage);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_usage_mapping(hdev, field, usage);
 }
 
@@ -1961,10 +2060,11 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
 	if (wacom->wacom_wac.features.type != HID_GENERIC)
 		return 0;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_event(hdev, field, usage, value);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_event(hdev, field, usage, value);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_event(hdev, field, usage, value);
 
 	return 0;
@@ -1998,18 +2098,20 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
 	if (wacom_wac->features.type != HID_GENERIC)
 		return;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		wacom_wac_pad_pre_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field))
 		wacom_wac_pen_pre_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		wacom_wac_finger_pre_report(hdev, report);
 
 	wacom_report_events(hdev, report);
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field))
+		return wacom_wac_pad_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field))
 		return wacom_wac_pen_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field))
 		return wacom_wac_finger_report(hdev, report);
 }
 
@@ -2583,6 +2685,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 	struct wacom_features *features = &wacom->wacom_wac.features;
 
 	/* The pen and pad share the same interface on most devices */
+	if (features->numbered_buttons > 0)
+		features->device_type |= WACOM_DEVICETYPE_PAD;
 	if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 ||
 	    features->type == DTUS ||
 	    (features->type >= INTUOS3S && features->type <= WACOM_MO)) {
@@ -3104,8 +3208,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 	__set_bit(ABS_MISC, input_dev->absbit);
 
 	/* kept for making legacy xf86-input-wacom accepting the pad */
-	input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum ||
+	      input_dev->absinfo[ABS_X].maximum)))
+		input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum ||
+	      input_dev->absinfo[ABS_Y].maximum)))
+		input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
 
 	/* kept for making udev and libwacom accepting the pad */
 	__set_bit(BTN_STYLUS, input_dev->keybit);
@@ -3225,6 +3333,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
 		break;
 
+	case HID_GENERIC:
+		break;
+
 	default:
 		/* no pad supported */
 		return -ENODEV;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index b4c3c64..1f7c4a8 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -86,19 +86,34 @@
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
 #define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_PAD                0x00040000
+#define WACOM_HID_SP_BUTTON             0x00090000
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
 #define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_DIGITIZERFNKEYS    (WACOM_HID_UP_WACOMDIGITIZER | 0x39)
 #define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
+#define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
+#define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
+#define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
+#define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
+#define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
+#define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
+#define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
+#define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
 #define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
 #define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
 #define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
+#define WACOM_HID_WD_DIGITIZERINFO      (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)
 #define WACOM_HID_UP_G9                 0xff090000
 #define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
 #define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
@@ -106,6 +121,10 @@
 #define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
 #define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
 
+#define WACOM_PAD_FIELD(f)	(((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERINFO))
+
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (13 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 15/18] HID: wacom: generic: Introduce pad support Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 17/18] HID: wacom: generic: Extend pad support Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

Adds support for usages that may appear on the pen or pad interface which
report the state of the tablet battery.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 drivers/hid/wacom_wac.h |  6 ++++++
 include/linux/hid.h     |  1 +
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 70de1fa..f3edecf 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1525,6 +1525,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
 	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case WACOM_HID_WD_ACCELEROMETER_X:
 		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
@@ -1574,8 +1578,25 @@ static int wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
 		wacom_wac->hid_data.inrange_state |= value;
 	}
 
-	if (equivalent_usage != WACOM_HID_WD_TOUCHRINGSTATUS)
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		return 0;
+
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		wacom_wac->hid_data.bat_charging = value;
+		wacom_wac->hid_data.ps_connected = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		return 0;
+
+	case WACOM_HID_WD_TOUCHRINGSTATUS:
+		return 0;
+
+	default:
 		input_event(input, usage->type, usage->code, value);
+		break;
+	}
 
 	return 0;
 }
@@ -1594,6 +1615,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pad_input;
 	bool active = wacom_wac->hid_data.inrange_state != 0;
 
@@ -1604,6 +1626,16 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
 	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY)
 		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
 
+	if (features->quirks & WACOM_QUIRK_BATTERY) {
+		int capacity = wacom_wac->hid_data.battery_capacity;
+		bool charging = wacom_wac->hid_data.bat_charging;
+		bool connected = wacom_wac->hid_data.bat_connected;
+		bool powered = wacom_wac->hid_data.ps_connected;
+
+		wacom_notify_battery(wacom_wac, capacity, charging,
+				     connected, powered);
+	}
+
 	input_sync(input);
 }
 
@@ -1633,6 +1665,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	case HID_DG_INRANGE:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case HID_DG_BATTERYSTRENGTH:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case HID_DG_INVERT:
 		wacom_map_usage(input, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
@@ -1703,6 +1738,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		if (!(features->quirks & WACOM_QUIRK_SENSE))
 			wacom_wac->hid_data.sense_state = value;
 		return 0;
+	case HID_DG_BATTERYSTRENGTH:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		break;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
 		return 0;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 1f7c4a8..7418c97 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -101,6 +101,8 @@
 #define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
 #define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
 #define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
+#define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
 #define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
 #define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
@@ -257,6 +259,10 @@ struct hid_data {
 	int last_slot_field;
 	int num_expected;
 	int num_received;
+	int battery_capacity;
+	int bat_charging;
+	int bat_connected;
+	int ps_connected;
 };
 
 struct wacom_remote_data {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index e712101..3baa2f9 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -231,6 +231,7 @@ struct hid_item {
 #define HID_DG_TAP		0x000d0035
 #define HID_DG_TABLETFUNCTIONKEY	0x000d0039
 #define HID_DG_PROGRAMCHANGEKEY	0x000d003a
+#define HID_DG_BATTERYSTRENGTH	0x000d003b
 #define HID_DG_INVERT		0x000d003c
 #define HID_DG_TILT_X		0x000d003d
 #define HID_DG_TILT_Y		0x000d003e
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 17/18] HID: wacom: generic: Extend pad support
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (14 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  2016-10-20  1:03   ` [PATCH v3 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The HID specification that the MobileStudio Pro follows includes usages
for several values that would be good to support so that future devices
"just work" out of the box. Extend the HID_GENERIC pad codepath to handle
these usages.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/wacom_wac.c | 15 +++++++++++++++
 drivers/hid/wacom_wac.h |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index f3edecf..0723ba8 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1457,6 +1457,8 @@ static int wacom_equivalent_usage(int usage)
 		    usage == WACOM_HID_WD_SERIALHI ||
 		    usage == WACOM_HID_WD_TOOLTYPE ||
 		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP2 ||
 		    usage == WACOM_HID_WD_TOUCHRING ||
 		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
 			return usage;
@@ -1512,6 +1514,9 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 	case EV_MSC:
 		input_set_capability(input, EV_MSC, code);
 		break;
+	case EV_SW:
+		input_set_capability(input, EV_SW, code);
+		break;
 	}
 }
 
@@ -1546,11 +1551,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 	case WACOM_HID_WD_BUTTONDOWN:
 	case WACOM_HID_WD_BUTTONLEFT:
 	case WACOM_HID_WD_BUTTONRIGHT:
+	case WACOM_HID_WD_BUTTONCENTER:
 		wacom_map_usage(input, usage, field, EV_KEY,
 				wacom_numbered_button_to_key(features->numbered_buttons),
 				0);
 		features->numbered_buttons++;
 		break;
+	case WACOM_HID_WD_TOUCHONOFF:
+		wacom_map_usage(input, usage, field, EV_SW, SW_MUTE_DEVICE, 0);
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0);
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP2:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, 0);
+		break;
 	case WACOM_HID_WD_TOUCHRING:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
 		break;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 7418c97..a54a301 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -96,6 +96,8 @@
 #define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
 #define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHSTRIP         (WACOM_HID_UP_WACOMDIGITIZER | 0x0136)
+#define WACOM_HID_WD_TOUCHSTRIP2        (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)
 #define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
 #define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
 #define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
@@ -104,11 +106,14 @@
 #define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
 #define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_EXPRESSKEYCAP00    (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
 #define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
 #define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
 #define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
 #define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
 #define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
+#define WACOM_HID_WD_BUTTONCENTER       (WACOM_HID_UP_WACOMDIGITIZER | 0x0995)
+#define WACOM_HID_WD_TOUCHONOFF         (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
 #define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v3 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res
  2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
                     ` (15 preceding siblings ...)
  2016-10-20  1:03   ` [PATCH v3 17/18] HID: wacom: generic: Extend pad support Jason Gerecke
@ 2016-10-20  1:03   ` Jason Gerecke
  16 siblings, 0 replies; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:03 UTC (permalink / raw)
  To: linux-input, Jiri Kosina
  Cc: Benjamin Tissoires, Ping Cheng, Ping Cheng, Aaron Skomra,
	Jason Gerecke, Jason Gerecke

The "Steering" usage (HID_UP_SIMULATION | 0xc8) is defined in HUT 1.12 as
follows:

"A steering wheel is a single degree-of-freedom device that rotates about
an axis. The zero position is always the neutral or 'straight ahead'
position, with positive values turning clockwise and negative values
turning counterclockwise. If the Coordinate Values Wrap attribute is
set, the steering wheel can be turned past 360 degrees."

The hidinput_configure_usage function canonically maps this usage to the
ABS_WHEEL axis, but hidinput_calc_abs_res does not recognize this axis
as one for which it can calculate a resolution. This effectively prevents
wheels from being assigned a proper resolution that userspace can use
to determine the precise angle of input.

This commit adds ABS_WHEEL as a rotational axis to hidinput_calc_abs_res.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/hid-input.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index fb9ace1..c4e935b5 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 	case ABS_RX:
 	case ABS_RY:
 	case ABS_RZ:
+	case ABS_WHEEL:
 	case ABS_TILT_X:
 	case ABS_TILT_Y:
 		if (field->unit == 0x14) {		/* If degrees */
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-18 21:39         ` Jiri Kosina
@ 2016-10-20  1:04           ` Jason Gerecke
  2016-10-20  8:32             ` Jiri Kosina
  0 siblings, 1 reply; 64+ messages in thread
From: Jason Gerecke @ 2016-10-20  1:04 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-input, Benjamin Tissoires, Ping Cheng, Ping Cheng,
	Aaron Skomra, Jason Gerecke

On 10/18/2016 02:39 PM, Jiri Kosina wrote:
> On Tue, 18 Oct 2016, Jason Gerecke wrote:
> 
>>>>  	if (usage->usage_index + 1 == field->report_count) {
>>>> -		if (usage->hid == wacom_wac->features.last_slot_field)
>>>> +		if (equivalent_usage == wacom_wac->features.last_slot_field)
>>>
>>> What tree is this based on please? In all the codebase I have, 
>>> last_slot_field is a member field of wacom_wac's hid_data, not a member of 
>>> struct wacom_features.
>>>
>>
>> This was based on your for-4.9/wacom tree, whose tip (for me) was commit
>> 1924e05 ("HID: wacom - add touch_arbitration parameter to wacom module").
>>
>> It looks like my tree only has commit 601a22f ("HID: wacom: Report input
>> events for each finger on generic devices") 
> 
> Pardon me? That commit is from 2014 (3.19-rc1). It really shouldn't be 
> used as a basis for a development.
> 
>> but not commit 003f50a ("HID: wacom: Update last_slot_field during 
>> pre_report phase"). 
> 
> That's a commit that went in for 4.9-rc1 (authored by you).
> 
>> Not sure why though.
>>
>> What would you like me to do?
> 
> Dunno where the confusion is coming from really. Could you please just 
> rebase the patchset on top of something up to date (such as or Linus' 
> git, master branch in my tree, or whatnot), and resubmit?
> 
> Thanks,
> 

New v3 patches submitted based on your master branch.

Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages
  2016-10-20  1:04           ` Jason Gerecke
@ 2016-10-20  8:32             ` Jiri Kosina
  0 siblings, 0 replies; 64+ messages in thread
From: Jiri Kosina @ 2016-10-20  8:32 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: linux-input, Benjamin Tissoires, Ping Cheng, Ping Cheng,
	Aaron Skomra, Jason Gerecke

On Wed, 19 Oct 2016, Jason Gerecke wrote:

> New v3 patches submitted based on your master branch.

Applied to for-4.10/wacom/mobile-studio-pro, thanks.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2016-10-20  8:32 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-06 21:22 [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Jason Gerecke
2016-10-06 21:22 ` [PATCH 01/19] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
2016-10-06 21:22 ` [PATCH 02/19] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
2016-10-06 21:22 ` [PATCH 03/19] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
2016-10-06 21:22 ` [PATCH 04/19] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
2016-10-06 21:22 ` [PATCH 05/19] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
2016-10-06 21:22 ` [PATCH 06/19] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
2016-10-06 21:22 ` [PATCH 07/19] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
2016-10-06 21:22 ` [PATCH 08/19] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
2016-10-06 21:22 ` [PATCH 09/19] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
2016-10-06 21:22 ` [PATCH 10/19] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
2016-10-06 21:22 ` [PATCH 11/19] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
2016-10-06 21:22 ` [PATCH 12/19] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
2016-10-06 21:22 ` [PATCH 13/19] HID: wacom: generic: Pass 'hdev' to 'wacom_map_usage' Jason Gerecke
2016-10-07 15:46   ` Benjamin Tissoires
2016-10-07 20:53     ` Jason Gerecke
2016-10-06 21:22 ` [PATCH 14/19] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
2016-10-06 21:22 ` [PATCH 15/19] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
2016-10-06 21:22 ` [PATCH 16/19] HID: wacom: generic: Introduce pad support Jason Gerecke
2016-10-06 21:22 ` [PATCH 17/19] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
2016-10-06 21:22 ` [PATCH 18/19] HID: wacom: generic: Extend pad support Jason Gerecke
2016-10-06 21:22 ` [PATCH 19/19] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
2016-10-07 15:41 ` [PATCH 00/19] HID: wacom: Add support for MobileStudio Pro Benjamin Tissoires
2016-10-07 22:16 ` [PATCH v2 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 03/18] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 05/18] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
2016-10-18 15:26     ` Jiri Kosina
2016-10-18 17:09       ` Jason Gerecke
2016-10-18 21:39         ` Jiri Kosina
2016-10-20  1:04           ` Jason Gerecke
2016-10-20  8:32             ` Jiri Kosina
2016-10-07 22:16   ` [PATCH v2 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 12/18] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 14/18] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 15/18] HID: wacom: generic: Introduce pad support Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 17/18] HID: wacom: generic: Extend pad support Jason Gerecke
2016-10-07 22:16   ` [PATCH v2 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke
2016-10-20  1:03 ` [PATCH v3 01/18] HID: wacom: Update vendor-defined usage names to better match standards Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 02/18] HID: wacom: Have WACOM_PEN_FIELD and WACOM_FINGER_FIELD recgonize more fields Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 03/18] HID: wacom: Refactor button-to-key translation into function Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 04/18] HID: wacom: Detect and correct descriptors missing HID_DG_BARRELSWITCH2 Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 05/18] HID: wacom: generic: Strip off excessive name prefixing Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 06/18] HID: wacom: generic: Add support for height, tilt, and twist usages Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 07/18] HID: wacom: generic: Support and use 'Custom HID' mode and usages Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 08/18] HID: wacom: generic: Add support for vendor-defined "Distance" usage Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 09/18] HID: wacom: generic: Add support for vendor-defined "Fingerwheel" usage Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 10/18] HID: wacom: generic: Add support for vendor-defined "Sense" usage Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 11/18] HID: wacom: Read and internally use corrected Intuos tool IDs Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 12/18] HID: wacom: generic: Support tool ID and additional tool types Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 13/18] HID: wacom: Fix sensor outbounds and redefine as offsets from each edge Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 14/18] HID: wacom: generic: Add support for sensor offsets Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 15/18] HID: wacom: generic: Introduce pad support Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 16/18] HID: wacom: generic: Add support for battery status on pen and pad interfaces Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 17/18] HID: wacom: generic: Extend pad support Jason Gerecke
2016-10-20  1:03   ` [PATCH v3 18/18] HID: input: Recognize ABS_WHEEL in hidinput_calc_abs_res Jason Gerecke

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.