aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerecke <killertofu@gmail.com>2016-10-19 21:03:43 -0400
committerJiri Kosina <jkosina@suse.cz>2016-10-20 03:53:57 -0400
commitc9c095874ab4446be6dec6755d8f68862fdeae48 (patch)
treef061b9cb23c96716801b2e9ee98af8d456faf40c
parent50066a042da5457ae5b6397425f0a7ca556231e3 (diff)
HID: wacom: generic: Support and use 'Custom HID' mode and usages
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> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/wacom_sys.c5
-rw-r--r--drivers/hid/wacom_wac.c37
-rw-r--r--drivers/hid/wacom_wac.h3
3 files changed, 39 insertions, 6 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 7b9bff2fad94..b2e2471bbef6 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,
166 } 166 }
167 break; 167 break;
168 168
169 case WACOM_HID_WD_DATAMODE:
170 wacom->wacom_wac.mode_report = field->report->id;
171 wacom->wacom_wac.mode_value = 2;
172 break;
173
169 case WACOM_HID_UP_G9: 174 case WACOM_HID_UP_G9:
170 case WACOM_HID_UP_G11: 175 case WACOM_HID_UP_G11:
171 if (field->report->id == 0x03 && 176 if (field->report->id == 0x03 &&
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 3f4ba53192c0..6c2f0e4baf7d 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)
1435 return 0; 1435 return 0;
1436} 1436}
1437 1437
1438static int wacom_equivalent_usage(int usage)
1439{
1440 if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) {
1441 int subpage = (usage & 0xFF00) << 8;
1442 int subusage = (usage & 0xFF);
1443
1444 if (subpage == WACOM_HID_SP_DIGITIZER ||
1445 subpage == WACOM_HID_SP_DIGITIZERINFO) {
1446 return usage;
1447 }
1448
1449 if (subpage == HID_UP_UNDEFINED)
1450 subpage = HID_UP_DIGITIZER;
1451
1452 return subpage | subusage;
1453 }
1454
1455 return usage;
1456}
1457
1438static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, 1458static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
1439 struct hid_field *field, __u8 type, __u16 code, int fuzz) 1459 struct hid_field *field, __u8 type, __u16 code, int fuzz)
1440{ 1460{
1441 int fmin = field->logical_minimum; 1461 int fmin = field->logical_minimum;
1442 int fmax = field->logical_maximum; 1462 int fmax = field->logical_maximum;
1463 unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
1443 int resolution_code = code; 1464 int resolution_code = code;
1444 1465
1445 if (usage->hid == HID_DG_TWIST) { 1466 if (equivalent_usage == HID_DG_TWIST) {
1446 resolution_code = ABS_RZ; 1467 resolution_code = ABS_RZ;
1447 } 1468 }
1448 1469
@@ -1472,8 +1493,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
1472 struct wacom *wacom = hid_get_drvdata(hdev); 1493 struct wacom *wacom = hid_get_drvdata(hdev);
1473 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1494 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1474 struct input_dev *input = wacom_wac->pen_input; 1495 struct input_dev *input = wacom_wac->pen_input;
1496 unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
1475 1497
1476 switch (usage->hid) { 1498 switch (equivalent_usage) {
1477 case HID_GD_X: 1499 case HID_GD_X:
1478 wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); 1500 wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
1479 break; 1501 break;
@@ -1524,8 +1546,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
1524 struct wacom *wacom = hid_get_drvdata(hdev); 1546 struct wacom *wacom = hid_get_drvdata(hdev);
1525 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1547 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1526 struct input_dev *input = wacom_wac->pen_input; 1548 struct input_dev *input = wacom_wac->pen_input;
1549 unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
1527 1550
1528 switch (usage->hid) { 1551 switch (equivalent_usage) {
1529 case HID_GD_Z: 1552 case HID_GD_Z:
1530 /* 1553 /*
1531 * HID_GD_Z "should increase as the control's position is 1554 * 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,
1597 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1620 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1598 struct input_dev *input = wacom_wac->touch_input; 1621 struct input_dev *input = wacom_wac->touch_input;
1599 unsigned touch_max = wacom_wac->features.touch_max; 1622 unsigned touch_max = wacom_wac->features.touch_max;
1623 unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
1600 1624
1601 switch (usage->hid) { 1625 switch (equivalent_usage) {
1602 case HID_GD_X: 1626 case HID_GD_X:
1603 if (touch_max == 1) 1627 if (touch_max == 1)
1604 wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); 1628 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,
1673{ 1697{
1674 struct wacom *wacom = hid_get_drvdata(hdev); 1698 struct wacom *wacom = hid_get_drvdata(hdev);
1675 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1699 struct wacom_wac *wacom_wac = &wacom->wacom_wac;
1700 unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
1676 1701
1677 switch (usage->hid) { 1702 switch (equivalent_usage) {
1678 case HID_GD_X: 1703 case HID_GD_X:
1679 wacom_wac->hid_data.x = value; 1704 wacom_wac->hid_data.x = value;
1680 break; 1705 break;
@@ -1697,7 +1722,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
1697 1722
1698 1723
1699 if (usage->usage_index + 1 == field->report_count) { 1724 if (usage->usage_index + 1 == field->report_count) {
1700 if (usage->hid == wacom_wac->hid_data.last_slot_field) 1725 if (equivalent_usage == wacom_wac->hid_data.last_slot_field)
1701 wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); 1726 wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
1702 } 1727 }
1703 1728
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index d2629c81c51a..ba914bad971f 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -85,7 +85,10 @@
85#define WACOM_DEVICETYPE_DIRECT 0x0010 85#define WACOM_DEVICETYPE_DIRECT 0x0010
86 86
87#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 87#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000
88#define WACOM_HID_SP_DIGITIZER 0x000d0000
89#define WACOM_HID_SP_DIGITIZERINFO 0x00100000
88#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) 90#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
91#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
89#define WACOM_HID_UP_G9 0xff090000 92#define WACOM_HID_UP_G9 0xff090000
90#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) 93#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
91#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) 94#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)