Skip to contentSkip to conversation

Input: wacom: Use full 32-bit HID Usage value in switch statement

PATCH In review Jason Gerecke 3 participants 11 messages Jan 30, 2014 – Feb 27, 2014 3 messages not in the archive

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

PATCH 1/4 Input: wacom: Use full 32-bit HID Usage value in switch statement

A HID Usage is a 32-bit value: an upper 16-bit "page" and a lower 16-bit ID. While the two halves are normally reported seperately, only the combination uniquely idenfifes a particular HID Usage.

The existing code performs the comparison in two steps, first performing a switch on the ID and then verifying the page within each case. While this works fine, it is very akward to handle two Usages that share a single ID, such as HID_USAGE_PRESSURE and HID_USAGE_X because the case statement can only have a single identifier.

To work around this, we now check the full 32-bit HID Usage directly rather than first checking the ID and then the page. This allows the switch statement to have distinct cases for e.g. HID_USAGE_PRESSURE and HID_USAGE_X.

---
 drivers/input/tablet/wacom_sys.c | 237 ++++++++++++++++++---------------------
 1 file changed, 109 insertions(+), 128 deletions(-)
drivers/input/tablet/wacom_sys.c +109 -128
index b16ebef..5be6177 100644
@@ -22,23 +22,17 @@
 #define HID_USAGE_PAGE_DIGITIZER	0x0d
 #define HID_USAGE_PAGE_DESKTOP		0x01
 #define HID_USAGE			0x09
-#define HID_USAGE_X			0x30
-#define HID_USAGE_Y			0x31
-#define HID_USAGE_X_TILT		0x3d
-#define HID_USAGE_Y_TILT		0x3e
-#define HID_USAGE_FINGER		0x22
-#define HID_USAGE_STYLUS		0x20
-#define HID_USAGE_CONTACTMAX		0x55
+#define HID_USAGE_X			((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
+#define HID_USAGE_Y			((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
+#define HID_USAGE_X_TILT		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
+#define HID_USAGE_Y_TILT		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
+#define HID_USAGE_FINGER		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
+#define HID_USAGE_STYLUS		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
+#define HID_USAGE_CONTACTMAX		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
 #define HID_COLLECTION			0xa1
 #define HID_COLLECTION_LOGICAL		0x02
 #define HID_COLLECTION_END		0xc0
 
-enum {
-	WCM_UNDEFINED = 0,
-	WCM_DESKTOP,
-	WCM_DIGITIZER,
-};
-
 struct hid_descriptor {
 	struct usb_descriptor_header header;
 	__le16   bcdHID;
@@ -305,7 +299,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
 	char limit = 0;
 	/* result has to be defined as int for some devices */
 	int result = 0, touch_max = 0;
-	int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+	int i = 0, page = 0, finger = 0, pen = 0;
 	unsigned char *report;
 
 	report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
@@ -332,134 +326,121 @@ static int wacom_parse_hid(struct usb_interface *intf,
 
 		switch (report[i]) {
 		case HID_USAGE_PAGE:
-			switch (report[i + 1]) {
-			case HID_USAGE_PAGE_DIGITIZER:
-				usage = WCM_DIGITIZER;
-				i++;
-				break;
-
-			case HID_USAGE_PAGE_DESKTOP:
-				usage = WCM_DESKTOP;
-				i++;
-				break;
-			}
+			page = report[i + 1];
+			i++;
 			break;
 
 		case HID_USAGE:
-			switch (report[i + 1]) {
+			switch (page << 16 | report[i + 1]) {
 			case HID_USAGE_X:
-				if (usage == WCM_DESKTOP) {
-					if (finger) {
-						features->device_type = BTN_TOOL_FINGER;
-						/* touch device at least supports one touch point */
-						touch_max = 1;
-						switch (features->type) {
-						case TABLETPC2FG:
-							features->pktlen = WACOM_PKGLEN_TPC2FG;
-							break;
-
-						case MTSCREEN:
-						case WACOM_24HDT:
-							features->pktlen = WACOM_PKGLEN_MTOUCH;
-							break;
-
-						case MTTPC:
-							features->pktlen = WACOM_PKGLEN_MTTPC;
-							break;
-
-						case BAMBOO_PT:
-							features->pktlen = WACOM_PKGLEN_BBTOUCH;
-							break;
-
-						default:
-							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-							break;
-						}
-
-						switch (features->type) {
-						case BAMBOO_PT:
-							features->x_phy =
-								get_unaligned_le16(&report[i + 5]);
-							features->x_max =
-								get_unaligned_le16(&report[i + 8]);
-							i += 15;
-							break;
-
-						case WACOM_24HDT:
-							features->x_max =
-								get_unaligned_le16(&report[i + 3]);
-							features->x_phy =
-								get_unaligned_le16(&report[i + 8]);
-							features->unit = report[i - 1];
-							features->unitExpo = report[i - 3];
-							i += 12;
-							break;
-
-						default:
-							features->x_max =
-								get_unaligned_le16(&report[i + 3]);
-							features->x_phy =
-								get_unaligned_le16(&report[i + 6]);
-							features->unit = report[i + 9];
-							features->unitExpo = report[i + 11];
-							i += 12;
-							break;
-						}
-					} else if (pen) {
-						/* penabled only accepts exact bytes of data */
-						if (features->type >= TABLETPC)
-							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-						features->device_type = BTN_TOOL_PEN;
+				if (finger) {
+					features->device_type = BTN_TOOL_FINGER;
+					/* touch device at least supports one touch point */
+					touch_max = 1;
+					switch (features->type) {
+					case TABLETPC2FG:
+						features->pktlen = WACOM_PKGLEN_TPC2FG;
+						break;
+
+					case MTSCREEN:
+					case WACOM_24HDT:
+						features->pktlen = WACOM_PKGLEN_MTOUCH;
+						break;
+
+					case MTTPC:
+						features->pktlen = WACOM_PKGLEN_MTTPC;
+						break;
+
+					case BAMBOO_PT:
+						features->pktlen = WACOM_PKGLEN_BBTOUCH;
+						break;
+
+					default:
+						features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+						break;
+					}
+
+					switch (features->type) {
+					case BAMBOO_PT:
+						features->x_phy =
+							get_unaligned_le16(&report[i + 5]);
+						features->x_max =
+							get_unaligned_le16(&report[i + 8]);
+						i += 15;
+						break;
+
+					case WACOM_24HDT:
 						features->x_max =
 							get_unaligned_le16(&report[i + 3]);
-						i += 4;
+						features->x_phy =
+							get_unaligned_le16(&report[i + 8]);
+						features->unit = report[i - 1];
+						features->unitExpo = report[i - 3];
+						i += 12;
+						break;
+
+					default:
+						features->x_max =
+							get_unaligned_le16(&report[i + 3]);
+						features->x_phy =
+							get_unaligned_le16(&report[i + 6]);
+						features->unit = report[i + 9];
+						features->unitExpo = report[i + 11];
+						i += 12;
+						break;
 					}
+				} else if (pen) {
+					/* penabled only accepts exact bytes of data */
+					if (features->type >= TABLETPC)
+						features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+					features->device_type = BTN_TOOL_PEN;
+					features->x_max =
+						get_unaligned_le16(&report[i + 3]);
+					i += 4;
 				}
 				break;
 
 			case HID_USAGE_Y:
-				if (usage == WCM_DESKTOP) {
-					if (finger) {
-						switch (features->type) {
-						case TABLETPC2FG:
-						case MTSCREEN:
-						case MTTPC:
-							features->y_max =
-								get_unaligned_le16(&report[i + 3]);
-							features->y_phy =
-								get_unaligned_le16(&report[i + 6]);
-							i += 7;
-							break;
-
-						case WACOM_24HDT:
-							features->y_max =
-								get_unaligned_le16(&report[i + 3]);
-							features->y_phy =
-								get_unaligned_le16(&report[i - 2]);
-							i += 7;
-							break;
-
-						case BAMBOO_PT:
-							features->y_phy =
-								get_unaligned_le16(&report[i + 3]);
-							features->y_max =
-								get_unaligned_le16(&report[i + 6]);
-							i += 12;
-							break;
-
-						default:
-							features->y_max =
-								features->x_max;
-							features->y_phy =
-								get_unaligned_le16(&report[i + 3]);
-							i += 4;
-							break;
-						}
-					} else if (pen) {
+				if (finger) {
+					switch (features->type) {
+					case TABLETPC2FG:
+					case MTSCREEN:
+					case MTTPC:
+						features->y_max =
+							get_unaligned_le16(&report[i + 3]);
+						features->y_phy =
+							get_unaligned_le16(&report[i + 6]);
+						i += 7;
+						break;
+
+					case WACOM_24HDT:
+						features->y_max =
+							get_unaligned_le16(&report[i + 3]);
+						features->y_phy =
+							get_unaligned_le16(&report[i - 2]);
+						i += 7;
+						break;
+
+					case BAMBOO_PT:
+						features->y_phy =
+							get_unaligned_le16(&report[i + 3]);
+						features->y_max =
+							get_unaligned_le16(&report[i + 6]);
+						i += 12;
+						break;
+
+					default:
 						features->y_max =
+							features->x_max;
+						features->y_phy =
 							get_unaligned_le16(&report[i + 3]);
 						i += 4;
+						break;
 					}
+				} else if (pen) {
+					features->y_max =
+						get_unaligned_le16(&report[i + 3]);
+					i += 4;
 				}
 				break;
 
@@ -489,7 +470,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
 
 		case HID_COLLECTION_END:
 			/* reset UsagePage and Finger */
-			finger = usage = 0;
+			finger = page = 0;
 			break;
 
 		case HID_COLLECTION:
Signature · 1 line
1.8.5.3
#1 lore raw

PATCH 2/4 Input: wacom: Override 'pressure_max' with value from HID_USAGE_PRESSURE

The 0xEC sensor is used in multiple tablet PCs and curiously has versions that report 256 levels of pressure (Samsung Slate 7) as well as versions that report 1024 levels (Lenovo Thinkpad Yoga). To allow both versions to work properly, we allow the value of HID_USAGE_PRESSURE reported to override pressure_max.

---
 drivers/input/tablet/wacom_sys.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/input/tablet/wacom_sys.c +9 -0
index 5be6177..611fc39 100644
@@ -24,6 +24,7 @@
 #define HID_USAGE			0x09
 #define HID_USAGE_X			((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
 #define HID_USAGE_Y			((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
+#define HID_USAGE_PRESSURE		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
 #define HID_USAGE_X_TILT		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
 #define HID_USAGE_Y_TILT		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
 #define HID_USAGE_FINGER		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
@@ -465,6 +466,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
 					wacom_retrieve_report_data(intf, features);
 				i++;
 				break;
+
+			case HID_USAGE_PRESSURE:
+				if (pen) {
+					features->pressure_max =
+						get_unaligned_le16(&report[i + 3]);
+					i += 4;
+				}
+				break;
 			}
 			break;
 
Signature · 1 line
1.8.5.3

A message that is not in the archive (sent off-list or not yet received): 1391107728-1306-2-git-send-email-killertofu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

Tested-by Aaron Skomra
#3 lore raw

Re: [PATCH 2/4] Input: wacom: Override 'pressure_max' with value from HID_USAGE_PRESSURE

Quoted 51 lines · Jason Gerecke

The 0xEC sensor is used in multiple tablet PCs and curiously has versions that report 256 levels of pressure (Samsung Slate 7) as well as versions that report 1024 levels (Lenovo Thinkpad Yoga). To allow both versions to work properly, we allow the value of HID_USAGE_PRESSURE reported to override pressure_max.

---
 drivers/input/tablet/wacom_sys.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/input/tablet/wacom_sys.c +1 -0
index 5be6177..611fc39 100644
@@ -24,6 +24,7 @@
 #define HID_USAGE                      0x09
 #define HID_USAGE_X                    ((HID_USAGE_PAGE_DESKTOP << 16) |
 0x30)
 #define HID_USAGE_Y                    ((HID_USAGE_PAGE_DESKTOP << 16) |
 0x31)
+#define HID_USAGE_PRESSURE             ((HID_USAGE_PAGE_DIGITIZER << 16)
 | 0x30)

#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16)
| 0x3d)
#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16)
| 0x3e)
#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16)
| 0x22)

drivers/input/tablet/wacom_sys.c +8 -0
@@ -465,6 +466,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                        wacom_retrieve_report_data(intf,
 features);
                                i++;
                                break;
+
+                       case HID_USAGE_PRESSURE:
+                               if (pen) {
+                                       features->pressure_max =
+
 get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
+                               }
+                               break;
                        }
                        break;

--
1.8.5.3

Signature · 3 lines
Aaron Skomra
[email protected]
503-208-5430

------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool. Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer Customize your own dashboards, set traffic alerts and generate reports. Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk

Tested-by Aaron Skomra on v1 2/4
#4 lore raw

Re: [PATCH 2/4] Input: wacom: Override 'pressure_max' with value from HID_USAGE_PRESSURE

In reply to Jason Gerecke
Quoted 39 lines · Jason Gerecke

The 0xEC sensor is used in multiple tablet PCs and curiously has versions that report 256 levels of pressure (Samsung Slate 7) as well as versions that report 1024 levels (Lenovo Thinkpad Yoga). To allow both versions to work properly, we allow the value of HID_USAGE_PRESSURE reported to override pressure_max.

---
 drivers/input/tablet/wacom_sys.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/input/tablet/wacom_sys.c +9 -1
index 5be6177..611fc39 100644
@@ -24,6 +24,7 @@
 #define HID_USAGE                      0x09
 #define HID_USAGE_X                    ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
 #define HID_USAGE_Y                    ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
+#define HID_USAGE_PRESSURE             ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
 #define HID_USAGE_X_TILT               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
 #define HID_USAGE_Y_TILT               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
 #define HID_USAGE_FINGER               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
@@ -465,6 +466,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                        wacom_retrieve_report_data(intf, features);
                                i++;
                                break;
+
+                       case HID_USAGE_PRESSURE:
+                               if (pen) {
+                                       features->pressure_max =
+                                               get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
+                               }
+                               break;
                        }
                        break;
 
--
Quoted 2 lines

1.8.5.3

#5 lore raw

PATCH 3/4 Input: wacom: References to 'wacom->data' should use 'unsigned char*'

In reply to Jason Gerecke

'wacom->data' contains raw binary data and can lead to unexpected behavior if a byte under examination happens to have its MSB set.

---
 drivers/input/tablet/wacom_wac.c | 27 +++++++++------------------
 1 file changed, 9 insertions(+), 18 deletions(-)
drivers/input/tablet/wacom_wac.c +9 -18
index 05f371d..9ff5613 100644
@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom)
 
 static int wacom_dtu_irq(struct wacom_wac *wacom)
 {
-	struct wacom_features *features = &wacom->features;
-	char *data = wacom->data;
+	unsigned char *data = wacom->data;
 	struct input_dev *input = wacom->input;
-	int prox = data[1] & 0x20, pressure;
+	int prox = data[1] & 0x20;
 
 	dev_dbg(input->dev.parent,
 		"%s: received report #%d", __func__, data[0]);
@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
 	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
 	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
 	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-	pressure = ((data[7] & 0x01) << 8) | data[6];
-	if (pressure < 0)
-		pressure = features->pressure_max + pressure + 1;
-	input_report_abs(input, ABS_PRESSURE, pressure);
+	input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
 	input_report_key(input, BTN_TOUCH, data[1] & 0x05);
 	if (!prox) /* out-prox */
 		wacom->id[0] = 0;
@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2)
 static int wacom_24hdt_irq(struct wacom_wac *wacom)
 {
 	struct input_dev *input = wacom->input;
-	char *data = wacom->data;
+	unsigned char *data = wacom->data;
 	int i;
 	int current_num_contacts = data[61];
 	int contacts_to_send = 0;
@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
 	struct input_dev *input = wacom->input;
-	char *data = wacom->data;
+	unsigned char *data = wacom->data;
 	int i;
 	int current_num_contacts = data[2];
 	int contacts_to_send = 0;
@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 
 static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
-	char *data = wacom->data;
+	unsigned char *data = wacom->data;
 	struct input_dev *input = wacom->input;
 	bool prox;
 	int x = 0, y = 0;
@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 
 static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
-	struct wacom_features *features = &wacom->features;
-	char *data = wacom->data;
+	unsigned char *data = wacom->data;
 	struct input_dev *input = wacom->input;
-	int pressure;
 	bool prox = data[1] & 0x20;
 
 	if (!wacom->shared->stylus_in_proximity) /* first in prox */
@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
 		input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
 		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
 		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-		pressure = ((data[7] & 0x01) << 8) | data[6];
-		if (pressure < 0)
-			pressure = features->pressure_max + pressure + 1;
-		input_report_abs(input, ABS_PRESSURE, pressure);
+		input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
 		input_report_key(input, BTN_TOUCH, data[1] & 0x05);
 		input_report_key(input, wacom->tool[0], prox);
 		return 1;
@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 {
-	char *data = wacom->data;
+	unsigned char *data = wacom->data;
 
 	dev_dbg(wacom->input->dev.parent,
 		"%s: received report #%d\n", __func__, data[0]);
Signature · 1 line
1.8.5.3

A message that is not in the archive (sent off-list or not yet received): 1391107728-1306-3-git-send-email-killertofu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

Tested-by Aaron Skomra
#7 lore raw

Re: [PATCH 3/4] Input: wacom: References to 'wacom->data' should use 'unsigned char*'

Quoted 108 lines · Jason Gerecke

'wacom->data' contains raw binary data and can lead to unexpected behavior if a byte under examination happens to have its MSB set.

---
 drivers/input/tablet/wacom_wac.c | 27 +++++++++------------------
 1 file changed, 9 insertions(+), 18 deletions(-)
drivers/input/tablet/wacom_wac.c +3 -7
index 05f371d..9ff5613 100644
@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom)
 
 static int wacom_dtu_irq(struct wacom_wac *wacom)
 {
-       struct wacom_features *features = &wacom->features;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int prox = data[1] & 0x20, pressure;
+       int prox = data[1] & 0x20;
 
        dev_dbg(input->dev.parent,
                "%s: received report #%d", __func__, data[0]);
@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
        input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
        input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
        input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-       pressure = ((data[7] & 0x01) << 8) | data[6];
-       if (pressure < 0)
-               pressure = features->pressure_max + pressure + 1;
-       input_report_abs(input, ABS_PRESSURE, pressure);
+       input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) |
 data[6]);
        input_report_key(input, BTN_TOUCH, data[1] & 0x05);
        if (!prox) /* out-prox */
                wacom->id[0] = 0;
drivers/input/tablet/wacom_wac.c +3 -3
@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2)
 static int wacom_24hdt_irq(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        int i;
        int current_num_contacts = data[61];
        int contacts_to_send = 0;
@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        int i;
        int current_num_contacts = data[2];
        int contacts_to_send = 0;
@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac
 *wacom)
 
 static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
        bool prox;
        int x = 0, y = 0;
drivers/input/tablet/wacom_wac.c +1 -3
@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac
 *wacom, size_t len)
 
 static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
-       struct wacom_features *features = &wacom->features;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int pressure;
        bool prox = data[1] & 0x20;
 
        if (!wacom->shared->stylus_in_proximity) /* first in prox */
drivers/input/tablet/wacom_wac.c +1 -4
@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
                input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
                input_report_abs(input, ABS_X, le16_to_cpup((__le16
 *)&data[2]));
                input_report_abs(input, ABS_Y, le16_to_cpup((__le16
 *)&data[4]));
-               pressure = ((data[7] & 0x01) << 8) | data[6];
-               if (pressure < 0)
-                       pressure = features->pressure_max + pressure + 1;
-               input_report_abs(input, ABS_PRESSURE, pressure);
+               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) <<
 8) | data[6]);
                input_report_key(input, BTN_TOUCH, data[1] & 0x05);
                input_report_key(input, wacom->tool[0], prox);
                return 1;
drivers/input/tablet/wacom_wac.c +1 -2
@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 {
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
 
        dev_dbg(wacom->input->dev.parent,
                "%s: received report #%d\n", __func__, data[0]);
--

1.8.5.3

Signature · 3 lines
Aaron Skomra
[email protected]
503-208-5430

------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool. Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer Customize your own dashboards, set traffic alerts and generate reports. Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk

Tested-by Aaron Skomra on v1 3/4
#8 lore raw

Re: [PATCH 3/4] Input: wacom: References to 'wacom->data' should use 'unsigned char*'

In reply to Jason Gerecke
Quoted 98 lines · Jason Gerecke

'wacom->data' contains raw binary data and can lead to unexpected behavior if a byte under examination happens to have its MSB set.

---
 drivers/input/tablet/wacom_wac.c | 27 +++++++++------------------
 1 file changed, 9 insertions(+), 18 deletions(-)
drivers/input/tablet/wacom_wac.c +9 -19
index 05f371d..9ff5613 100644
@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom)
 
 static int wacom_dtu_irq(struct wacom_wac *wacom)
 {
-       struct wacom_features *features = &wacom->features;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int prox = data[1] & 0x20, pressure;
+       int prox = data[1] & 0x20;
 
        dev_dbg(input->dev.parent,
                "%s: received report #%d", __func__, data[0]);
@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
        input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
        input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
        input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-       pressure = ((data[7] & 0x01) << 8) | data[6];
-       if (pressure < 0)
-               pressure = features->pressure_max + pressure + 1;
-       input_report_abs(input, ABS_PRESSURE, pressure);
+       input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
        input_report_key(input, BTN_TOUCH, data[1] & 0x05);
        if (!prox) /* out-prox */
                wacom->id[0] = 0;
@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2)
 static int wacom_24hdt_irq(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        int i;
        int current_num_contacts = data[61];
        int contacts_to_send = 0;
@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        int i;
        int current_num_contacts = data[2];
        int contacts_to_send = 0;
@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 
 static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
        bool prox;
        int x = 0, y = 0;
@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 
 static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
-       struct wacom_features *features = &wacom->features;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int pressure;
        bool prox = data[1] & 0x20;
 
        if (!wacom->shared->stylus_in_proximity) /* first in prox */
@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
                input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
                input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
                input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-               pressure = ((data[7] & 0x01) << 8) | data[6];
-               if (pressure < 0)
-                       pressure = features->pressure_max + pressure + 1;
-               input_report_abs(input, ABS_PRESSURE, pressure);
+               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
                input_report_key(input, BTN_TOUCH, data[1] & 0x05);
                input_report_key(input, wacom->tool[0], prox);
                return 1;
@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 {
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
 
        dev_dbg(wacom->input->dev.parent,
                "%s: received report #%d\n", __func__, data[0]);
--
Quoted 2 lines

1.8.5.3

#9 lore raw

PATCH 4/4 Input: wacom: Handle 1024 pressure levels in wacom_tpc_pen

In reply to Jason Gerecke

Some tablet PC sensors (e.g. the 0xEC found in the Thinkpad Yoga) report more than 256 pressure levels and will experience wraparound unless the full range is read.

---
 drivers/input/tablet/wacom_wac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/tablet/wacom_wac.c +1 -1
index 9ff5613..ae1437b 100644
@@ -1087,7 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
 		input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
 		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
 		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-		input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
+		input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
 		input_report_key(input, BTN_TOUCH, data[1] & 0x05);
 		input_report_key(input, wacom->tool[0], prox);
 		return 1;
Signature · 1 line
1.8.5.3

A message that is not in the archive (sent off-list or not yet received): 1391107728-1306-4-git-send-email-killertofu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

Tested-by Aaron Skomra
#11 lore raw

Re: [PATCH 4/4] Input: wacom: Handle 1024 pressure levels in wacom_tpc_pen

Quoted 31 lines · Jason Gerecke

Some tablet PC sensors (e.g. the 0xEC found in the Thinkpad Yoga) report more than 256 pressure levels and will experience wraparound unless the full range is read.

---
 drivers/input/tablet/wacom_wac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/tablet/wacom_wac.c +1 -1
index 9ff5613..ae1437b 100644
@@ -1087,7 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
                input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
                input_report_abs(input, ABS_X, le16_to_cpup((__le16
 *)&data[2]));
                input_report_abs(input, ABS_Y, le16_to_cpup((__le16
 *)&data[4]));
-               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) <<
 8) | data[6]);
+               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) <<
8) | data[6]);
                input_report_key(input, BTN_TOUCH, data[1] & 0x05);
                input_report_key(input, wacom->tool[0], prox);
                return 1;

--
1.8.5.3

Signature · 3 lines
Aaron Skomra
[email protected]
503-208-5430

------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool. Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer Customize your own dashboards, set traffic alerts and generate reports. Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk

Tested-by Aaron Skomra on v1 4/4
#12 lore raw

Re: [PATCH 4/4] Input: wacom: Handle 1024 pressure levels in wacom_tpc_pen

In reply to Jason Gerecke
Quoted 23 lines · Jason Gerecke

Some tablet PC sensors (e.g. the 0xEC found in the Thinkpad Yoga) report more than 256 pressure levels and will experience wraparound unless the full range is read.

---
 drivers/input/tablet/wacom_wac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/tablet/wacom_wac.c +1 -2
index 9ff5613..ae1437b 100644
@@ -1087,7 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
                input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
                input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
                input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
+               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
                input_report_key(input, BTN_TOUCH, data[1] & 0x05);
                input_report_key(input, wacom->tool[0], prox);
                return 1;
--
Quoted 2 lines

1.8.5.3

Tested-by Aaron Skomra on v1 1/4
#13 lore raw
In reply to Jason Gerecke
Quoted 311 lines · Jason Gerecke

A HID Usage is a 32-bit value: an upper 16-bit "page" and a lower 16-bit ID. While the two halves are normally reported seperately, only the combination uniquely idenfifes a particular HID Usage.

The existing code performs the comparison in two steps, first performing a switch on the ID and then verifying the page within each case. While this works fine, it is very akward to handle two Usages that share a single ID, such as HID_USAGE_PRESSURE and HID_USAGE_X because the case statement can only have a single identifier.

To work around this, we now check the full 32-bit HID Usage directly rather than first checking the ID and then the page. This allows the switch statement to have distinct cases for e.g. HID_USAGE_PRESSURE and HID_USAGE_X.

---
 drivers/input/tablet/wacom_sys.c | 237 ++++++++++++++++++---------------------
 1 file changed, 109 insertions(+), 128 deletions(-)
drivers/input/tablet/wacom_sys.c +109 -129
index b16ebef..5be6177 100644
@@ -22,23 +22,17 @@
 #define HID_USAGE_PAGE_DIGITIZER       0x0d
 #define HID_USAGE_PAGE_DESKTOP         0x01
 #define HID_USAGE                      0x09
-#define HID_USAGE_X                    0x30
-#define HID_USAGE_Y                    0x31
-#define HID_USAGE_X_TILT               0x3d
-#define HID_USAGE_Y_TILT               0x3e
-#define HID_USAGE_FINGER               0x22
-#define HID_USAGE_STYLUS               0x20
-#define HID_USAGE_CONTACTMAX           0x55
+#define HID_USAGE_X                    ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
+#define HID_USAGE_Y                    ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
+#define HID_USAGE_X_TILT               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
+#define HID_USAGE_Y_TILT               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
+#define HID_USAGE_FINGER               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
+#define HID_USAGE_STYLUS               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
+#define HID_USAGE_CONTACTMAX           ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
 #define HID_COLLECTION                 0xa1
 #define HID_COLLECTION_LOGICAL         0x02
 #define HID_COLLECTION_END             0xc0
 
-enum {
-       WCM_UNDEFINED = 0,
-       WCM_DESKTOP,
-       WCM_DIGITIZER,
-};
-
 struct hid_descriptor {
        struct usb_descriptor_header header;
        __le16   bcdHID;
@@ -305,7 +299,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
        char limit = 0;
        /* result has to be defined as int for some devices */
        int result = 0, touch_max = 0;
-       int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+       int i = 0, page = 0, finger = 0, pen = 0;
        unsigned char *report;
 
        report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
@@ -332,134 +326,121 @@ static int wacom_parse_hid(struct usb_interface *intf,
 
                switch (report[i]) {
                case HID_USAGE_PAGE:
-                       switch (report[i + 1]) {
-                       case HID_USAGE_PAGE_DIGITIZER:
-                               usage = WCM_DIGITIZER;
-                               i++;
-                               break;
-
-                       case HID_USAGE_PAGE_DESKTOP:
-                               usage = WCM_DESKTOP;
-                               i++;
-                               break;
-                       }
+                       page = report[i + 1];
+                       i++;
                        break;
 
                case HID_USAGE:
-                       switch (report[i + 1]) {
+                       switch (page << 16 | report[i + 1]) {
                        case HID_USAGE_X:
-                               if (usage == WCM_DESKTOP) {
-                                       if (finger) {
-                                               features->device_type = BTN_TOOL_FINGER;
-                                               /* touch device at least supports one touch point */
-                                               touch_max = 1;
-                                               switch (features->type) {
-                                               case TABLETPC2FG:
-                                                       features->pktlen = WACOM_PKGLEN_TPC2FG;
-                                                       break;
-
-                                               case MTSCREEN:
-                                               case WACOM_24HDT:
-                                                       features->pktlen = WACOM_PKGLEN_MTOUCH;
-                                                       break;
-
-                                               case MTTPC:
-                                                       features->pktlen = WACOM_PKGLEN_MTTPC;
-                                                       break;
-
-                                               case BAMBOO_PT:
-                                                       features->pktlen = WACOM_PKGLEN_BBTOUCH;
-                                                       break;
-
-                                               default:
-                                                       features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-                                                       break;
-                                               }
-
-                                               switch (features->type) {
-                                               case BAMBOO_PT:
-                                                       features->x_phy =
-                                                               get_unaligned_le16(&report[i + 5]);
-                                                       features->x_max =
-                                                               get_unaligned_le16(&report[i + 8]);
-                                                       i += 15;
-                                                       break;
-
-                                               case WACOM_24HDT:
-                                                       features->x_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->x_phy =
-                                                               get_unaligned_le16(&report[i + 8]);
-                                                       features->unit = report[i - 1];
-                                                       features->unitExpo = report[i - 3];
-                                                       i += 12;
-                                                       break;
-
-                                               default:
-                                                       features->x_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->x_phy =
-                                                               get_unaligned_le16(&report[i + 6]);
-                                                       features->unit = report[i + 9];
-                                                       features->unitExpo = report[i + 11];
-                                                       i += 12;
-                                                       break;
-                                               }
-                                       } else if (pen) {
-                                               /* penabled only accepts exact bytes of data */
-                                               if (features->type >= TABLETPC)
-                                                       features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-                                               features->device_type = BTN_TOOL_PEN;
+                               if (finger) {
+                                       features->device_type = BTN_TOOL_FINGER;
+                                       /* touch device at least supports one touch point */
+                                       touch_max = 1;
+                                       switch (features->type) {
+                                       case TABLETPC2FG:
+                                               features->pktlen = WACOM_PKGLEN_TPC2FG;
+                                               break;
+
+                                       case MTSCREEN:
+                                       case WACOM_24HDT:
+                                               features->pktlen = WACOM_PKGLEN_MTOUCH;
+                                               break;
+
+                                       case MTTPC:
+                                               features->pktlen = WACOM_PKGLEN_MTTPC;
+                                               break;
+
+                                       case BAMBOO_PT:
+                                               features->pktlen = WACOM_PKGLEN_BBTOUCH;
+                                               break;
+
+                                       default:
+                                               features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                               break;
+                                       }
+
+                                       switch (features->type) {
+                                       case BAMBOO_PT:
+                                               features->x_phy =
+                                                       get_unaligned_le16(&report[i + 5]);
+                                               features->x_max =
+                                                       get_unaligned_le16(&report[i + 8]);
+                                               i += 15;
+                                               break;
+
+                                       case WACOM_24HDT:
                                                features->x_max =
                                                        get_unaligned_le16(&report[i + 3]);
-                                               i += 4;
+                                               features->x_phy =
+                                                       get_unaligned_le16(&report[i + 8]);
+                                               features->unit = report[i - 1];
+                                               features->unitExpo = report[i - 3];
+                                               i += 12;
+                                               break;
+
+                                       default:
+                                               features->x_max =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->x_phy =
+                                                       get_unaligned_le16(&report[i + 6]);
+                                               features->unit = report[i + 9];
+                                               features->unitExpo = report[i + 11];
+                                               i += 12;
+                                               break;
                                        }
+                               } else if (pen) {
+                                       /* penabled only accepts exact bytes of data */
+                                       if (features->type >= TABLETPC)
+                                               features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                       features->device_type = BTN_TOOL_PEN;
+                                       features->x_max =
+                                               get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
                                }
                                break;
 
                        case HID_USAGE_Y:
-                               if (usage == WCM_DESKTOP) {
-                                       if (finger) {
-                                               switch (features->type) {
-                                               case TABLETPC2FG:
-                                               case MTSCREEN:
-                                               case MTTPC:
-                                                       features->y_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i + 6]);
-                                                       i += 7;
-                                                       break;
-
-                                               case WACOM_24HDT:
-                                                       features->y_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i - 2]);
-                                                       i += 7;
-                                                       break;
-
-                                               case BAMBOO_PT:
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->y_max =
-                                                               get_unaligned_le16(&report[i + 6]);
-                                                       i += 12;
-                                                       break;
-
-                                               default:
-                                                       features->y_max =
-                                                               features->x_max;
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       i += 4;
-                                                       break;
-                                               }
-                                       } else if (pen) {
+                               if (finger) {
+                                       switch (features->type) {
+                                       case TABLETPC2FG:
+                                       case MTSCREEN:
+                                       case MTTPC:
+                                               features->y_max =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->y_phy =
+                                                       get_unaligned_le16(&report[i + 6]);
+                                               i += 7;
+                                               break;
+
+                                       case WACOM_24HDT:
+                                               features->y_max =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->y_phy =
+                                                       get_unaligned_le16(&report[i - 2]);
+                                               i += 7;
+                                               break;
+
+                                       case BAMBOO_PT:
+                                               features->y_phy =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->y_max =
+                                                       get_unaligned_le16(&report[i + 6]);
+                                               i += 12;
+                                               break;
+
+                                       default:
                                                features->y_max =
+                                                       features->x_max;
+                                               features->y_phy =
                                                        get_unaligned_le16(&report[i + 3]);
                                                i += 4;
+                                               break;
                                        }
+                               } else if (pen) {
+                                       features->y_max =
+                                               get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
                                }
                                break;
 
@@ -489,7 +470,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
 
                case HID_COLLECTION_END:
                        /* reset UsagePage and Finger */
-                       finger = usage = 0;
+                       finger = page = 0;
                        break;
 
                case HID_COLLECTION:
--
Quoted 2 lines

1.8.5.3