aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorPing Cheng <pinglinux@gmail.com>2012-04-30 00:09:18 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-04-30 00:13:53 -0400
commit1963518b9b1b8019d33b4b08deee6f873ffa2730 (patch)
tree5bcdd926950a9b75799232f7f5b6dd3d95905a7f /drivers/input
parentf393ee2b814e3291c12565000210b3cf10aa5c1d (diff)
Input: wacom - add 0xE5 (MT device) support
Main part of patch is adding support for a new Wacom MT touch packet and labels these devices using MTSCREEN type. Other items of interest: Delete some duplicate code in HID parsing for Y info since its already done in X path. In wacom_query_tablet_data(), only invoke the set report that requests tablets to send Wacom Touch packets for Finger interfaces. Mostly, this is to make code intent clear. Tested-by: Jason Gerecke <killertofu@gmail.com> Signed-off-by: Chris Bagwell <chris@cnpbagwell.com> Signed-off-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/tablet/wacom.h4
-rw-r--r--drivers/input/tablet/wacom_sys.c91
-rw-r--r--drivers/input/tablet/wacom_wac.c99
-rw-r--r--drivers/input/tablet/wacom_wac.h8
4 files changed, 157 insertions, 45 deletions
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index b4842d0e61dd..b79d45198d82 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -135,6 +135,6 @@ extern const struct usb_device_id wacom_ids[];
135 135
136void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); 136void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
137void wacom_setup_device_quirks(struct wacom_features *features); 137void wacom_setup_device_quirks(struct wacom_features *features);
138void wacom_setup_input_capabilities(struct input_dev *input_dev, 138int wacom_setup_input_capabilities(struct input_dev *input_dev,
139 struct wacom_wac *wacom_wac); 139 struct wacom_wac *wacom_wac);
140#endif 140#endif
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index be13223793fb..86b96f94cd84 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -317,6 +317,10 @@ static int wacom_parse_hid(struct usb_interface *intf,
317 /* need to reset back */ 317 /* need to reset back */
318 features->pktlen = WACOM_PKGLEN_TPC2FG; 318 features->pktlen = WACOM_PKGLEN_TPC2FG;
319 } 319 }
320
321 if (features->type == MTSCREEN)
322 features->pktlen = WACOM_PKGLEN_MTOUCH;
323
320 if (features->type == BAMBOO_PT) { 324 if (features->type == BAMBOO_PT) {
321 /* need to reset back */ 325 /* need to reset back */
322 features->pktlen = WACOM_PKGLEN_BBTOUCH; 326 features->pktlen = WACOM_PKGLEN_BBTOUCH;
@@ -349,18 +353,15 @@ static int wacom_parse_hid(struct usb_interface *intf,
349 case HID_USAGE_Y: 353 case HID_USAGE_Y:
350 if (usage == WCM_DESKTOP) { 354 if (usage == WCM_DESKTOP) {
351 if (finger) { 355 if (finger) {
352 features->device_type = BTN_TOOL_FINGER; 356 int type = features->type;
353 if (features->type == TABLETPC2FG) { 357
354 /* need to reset back */ 358 if (type == TABLETPC2FG || type == MTSCREEN) {
355 features->pktlen = WACOM_PKGLEN_TPC2FG;
356 features->y_max = 359 features->y_max =
357 get_unaligned_le16(&report[i + 3]); 360 get_unaligned_le16(&report[i + 3]);
358 features->y_phy = 361 features->y_phy =
359 get_unaligned_le16(&report[i + 6]); 362 get_unaligned_le16(&report[i + 6]);
360 i += 7; 363 i += 7;
361 } else if (features->type == BAMBOO_PT) { 364 } else if (type == BAMBOO_PT) {
362 /* need to reset back */
363 features->pktlen = WACOM_PKGLEN_BBTOUCH;
364 features->y_phy = 365 features->y_phy =
365 get_unaligned_le16(&report[i + 3]); 366 get_unaligned_le16(&report[i + 3]);
366 features->y_max = 367 features->y_max =
@@ -374,10 +375,6 @@ static int wacom_parse_hid(struct usb_interface *intf,
374 i += 4; 375 i += 4;
375 } 376 }
376 } else if (pen) { 377 } else if (pen) {
377 /* penabled only accepts exact bytes of data */
378 if (features->type == TABLETPC2FG)
379 features->pktlen = WACOM_PKGLEN_GRAPHIRE;
380 features->device_type = BTN_TOOL_PEN;
381 features->y_max = 378 features->y_max =
382 get_unaligned_le16(&report[i + 3]); 379 get_unaligned_le16(&report[i + 3]);
383 i += 4; 380 i += 4;
@@ -440,22 +437,29 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
440 if (!rep_data) 437 if (!rep_data)
441 return error; 438 return error;
442 439
443 /* ask to report tablet data if it is MT Tablet PC or 440 /* ask to report Wacom data */
444 * not a Tablet PC */ 441 if (features->device_type == BTN_TOOL_FINGER) {
445 if (features->type == TABLETPC2FG) { 442 /* if it is an MT Tablet PC touch */
446 do { 443 if (features->type == TABLETPC2FG ||
447 rep_data[0] = 3; 444 features->type == MTSCREEN) {
448 rep_data[1] = 4; 445 do {
449 rep_data[2] = 0; 446 rep_data[0] = 3;
450 rep_data[3] = 0; 447 rep_data[1] = 4;
451 report_id = 3; 448 rep_data[2] = 0;
452 error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, 449 rep_data[3] = 0;
453 report_id, rep_data, 4, 1); 450 report_id = 3;
454 if (error >= 0) 451 error = wacom_set_report(intf,
455 error = wacom_get_report(intf, 452 WAC_HID_FEATURE_REPORT,
456 WAC_HID_FEATURE_REPORT, 453 report_id,
457 report_id, rep_data, 4, 1); 454 rep_data, 4, 1);
458 } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); 455 if (error >= 0)
456 error = wacom_get_report(intf,
457 WAC_HID_FEATURE_REPORT,
458 report_id,
459 rep_data, 4, 1);
460 } while ((error < 0 || rep_data[1] != 4) &&
461 limit++ < WAC_MSG_RETRIES);
462 }
459 } else if (features->type != TABLETPC && 463 } else if (features->type != TABLETPC &&
460 features->type != WIRELESS && 464 features->type != WIRELESS &&
461 features->device_type == BTN_TOOL_PEN) { 465 features->device_type == BTN_TOOL_PEN) {
@@ -477,7 +481,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
477} 481}
478 482
479static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, 483static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
480 struct wacom_features *features) 484 struct wacom_features *features)
481{ 485{
482 int error = 0; 486 int error = 0;
483 struct usb_host_interface *interface = intf->cur_altsetting; 487 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -505,10 +509,13 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
505 } 509 }
506 } 510 }
507 511
508 /* only Tablet PCs and Bamboo P&T need to retrieve the info */ 512 /* only devices that support touch need to retrieve the info */
509 if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && 513 if (features->type != TABLETPC &&
510 (features->type != BAMBOO_PT)) 514 features->type != TABLETPC2FG &&
515 features->type != BAMBOO_PT &&
516 features->type != MTSCREEN) {
511 goto out; 517 goto out;
518 }
512 519
513 if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { 520 if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
514 if (usb_get_extra_descriptor(&interface->endpoint[0], 521 if (usb_get_extra_descriptor(&interface->endpoint[0],
@@ -978,8 +985,10 @@ static int wacom_register_input(struct wacom *wacom)
978 int error; 985 int error;
979 986
980 input_dev = input_allocate_device(); 987 input_dev = input_allocate_device();
981 if (!input_dev) 988 if (!input_dev) {
982 return -ENOMEM; 989 error = -ENOMEM;
990 goto fail1;
991 }
983 992
984 input_dev->name = wacom_wac->name; 993 input_dev->name = wacom_wac->name;
985 input_dev->dev.parent = &intf->dev; 994 input_dev->dev.parent = &intf->dev;
@@ -989,14 +998,20 @@ static int wacom_register_input(struct wacom *wacom)
989 input_set_drvdata(input_dev, wacom); 998 input_set_drvdata(input_dev, wacom);
990 999
991 wacom_wac->input = input_dev; 1000 wacom_wac->input = input_dev;
992 wacom_setup_input_capabilities(input_dev, wacom_wac); 1001 error = wacom_setup_input_capabilities(input_dev, wacom_wac);
1002 if (error)
1003 goto fail1;
993 1004
994 error = input_register_device(input_dev); 1005 error = input_register_device(input_dev);
995 if (error) { 1006 if (error)
996 input_free_device(input_dev); 1007 goto fail2;
997 wacom_wac->input = NULL; 1008
998 } 1009 return 0;
999 1010
1011fail2:
1012 input_free_device(input_dev);
1013 wacom_wac->input = NULL;
1014fail1:
1000 return error; 1015 return error;
1001} 1016}
1002 1017
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index e5cd0e57d178..10e5cf870359 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -768,6 +768,72 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
768 return 1; 768 return 1;
769} 769}
770 770
771static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
772{
773 int touch_max = wacom->features.touch_max;
774 int i;
775
776 if (!wacom->slots)
777 return -1;
778
779 for (i = 0; i < touch_max; ++i) {
780 if (wacom->slots[i] == contactid)
781 return i;
782 }
783 for (i = 0; i < touch_max; ++i) {
784 if (wacom->slots[i] == -1)
785 return i;
786 }
787 return -1;
788}
789
790static int wacom_mt_touch(struct wacom_wac *wacom)
791{
792 struct input_dev *input = wacom->input;
793 char *data = wacom->data;
794 int i;
795 int current_num_contacts = data[2];
796 int contacts_to_send = 0;
797
798 /*
799 * First packet resets the counter since only the first
800 * packet in series will have non-zero current_num_contacts.
801 */
802 if (current_num_contacts)
803 wacom->num_contacts_left = current_num_contacts;
804
805 /* There are at most 5 contacts per packet */
806 contacts_to_send = min(5, wacom->num_contacts_left);
807
808 for (i = 0; i < contacts_to_send; i++) {
809 int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3;
810 bool touch = data[offset] & 0x1;
811 int id = le16_to_cpup((__le16 *)&data[offset + 1]);
812 int slot = find_slot_from_contactid(wacom, id);
813
814 if (slot < 0)
815 continue;
816
817 input_mt_slot(input, slot);
818 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
819 if (touch) {
820 int x = le16_to_cpup((__le16 *)&data[offset + 7]);
821 int y = le16_to_cpup((__le16 *)&data[offset + 9]);
822 input_report_abs(input, ABS_MT_POSITION_X, x);
823 input_report_abs(input, ABS_MT_POSITION_Y, y);
824 }
825 wacom->slots[slot] = touch ? id : -1;
826 }
827
828 input_mt_report_pointer_emulation(input, true);
829
830 wacom->num_contacts_left -= contacts_to_send;
831 if (wacom->num_contacts_left < 0)
832 wacom->num_contacts_left = 0;
833
834 return 1;
835}
836
771static int wacom_tpc_mt_touch(struct wacom_wac *wacom) 837static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
772{ 838{
773 struct input_dev *input = wacom->input; 839 struct input_dev *input = wacom->input;
@@ -806,6 +872,9 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
806 bool prox; 872 bool prox;
807 int x = 0, y = 0; 873 int x = 0, y = 0;
808 874
875 if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
876 return 0;
877
809 if (!wacom->shared->stylus_in_proximity) { 878 if (!wacom->shared->stylus_in_proximity) {
810 if (len == WACOM_PKGLEN_TPC1FG) { 879 if (len == WACOM_PKGLEN_TPC1FG) {
811 prox = data[0] & 0x01; 880 prox = data[0] & 0x01;
@@ -873,10 +942,10 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
873 942
874 switch (len) { 943 switch (len) {
875 case WACOM_PKGLEN_TPC1FG: 944 case WACOM_PKGLEN_TPC1FG:
876 return wacom_tpc_single_touch(wacom, len); 945 return wacom_tpc_single_touch(wacom, len);
877 946
878 case WACOM_PKGLEN_TPC2FG: 947 case WACOM_PKGLEN_TPC2FG:
879 return wacom_tpc_mt_touch(wacom); 948 return wacom_tpc_mt_touch(wacom);
880 949
881 default: 950 default:
882 switch (data[0]) { 951 switch (data[0]) {
@@ -885,6 +954,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
885 case WACOM_REPORT_TPCST: 954 case WACOM_REPORT_TPCST:
886 return wacom_tpc_single_touch(wacom, len); 955 return wacom_tpc_single_touch(wacom, len);
887 956
957 case WACOM_REPORT_TPCMT:
958 return wacom_mt_touch(wacom);
959
888 case WACOM_REPORT_PENABLED: 960 case WACOM_REPORT_PENABLED:
889 return wacom_tpc_pen(wacom); 961 return wacom_tpc_pen(wacom);
890 } 962 }
@@ -1164,6 +1236,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
1164 1236
1165 case TABLETPC: 1237 case TABLETPC:
1166 case TABLETPC2FG: 1238 case TABLETPC2FG:
1239 case MTSCREEN:
1167 sync = wacom_tpc_irq(wacom_wac, len); 1240 sync = wacom_tpc_irq(wacom_wac, len);
1168 break; 1241 break;
1169 1242
@@ -1237,7 +1310,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
1237 /* these device have multiple inputs */ 1310 /* these device have multiple inputs */
1238 if (features->type == TABLETPC || features->type == TABLETPC2FG || 1311 if (features->type == TABLETPC || features->type == TABLETPC2FG ||
1239 features->type == BAMBOO_PT || features->type == WIRELESS || 1312 features->type == BAMBOO_PT || features->type == WIRELESS ||
1240 (features->type >= INTUOS5S && features->type <= INTUOS5L)) 1313 (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
1314 features->type == MTSCREEN)
1241 features->quirks |= WACOM_QUIRK_MULTI_INPUT; 1315 features->quirks |= WACOM_QUIRK_MULTI_INPUT;
1242 1316
1243 /* quirk for bamboo touch with 2 low res touches */ 1317 /* quirk for bamboo touch with 2 low res touches */
@@ -1268,8 +1342,8 @@ static unsigned int wacom_calculate_touch_res(unsigned int logical_max,
1268 return (logical_max * 100) / physical_max; 1342 return (logical_max * 100) / physical_max;
1269} 1343}
1270 1344
1271void wacom_setup_input_capabilities(struct input_dev *input_dev, 1345int wacom_setup_input_capabilities(struct input_dev *input_dev,
1272 struct wacom_wac *wacom_wac) 1346 struct wacom_wac *wacom_wac)
1273{ 1347{
1274 struct wacom_features *features = &wacom_wac->features; 1348 struct wacom_features *features = &wacom_wac->features;
1275 int i; 1349 int i;
@@ -1465,8 +1539,18 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1465 break; 1539 break;
1466 1540
1467 case TABLETPC2FG: 1541 case TABLETPC2FG:
1542 case MTSCREEN:
1468 if (features->device_type == BTN_TOOL_FINGER) { 1543 if (features->device_type == BTN_TOOL_FINGER) {
1469 1544
1545 wacom_wac->slots = kmalloc(features->touch_max *
1546 sizeof(int),
1547 GFP_KERNEL);
1548 if (!wacom_wac->slots)
1549 return -ENOMEM;
1550
1551 for (i = 0; i < features->touch_max; i++)
1552 wacom_wac->slots[i] = -1;
1553
1470 input_mt_init_slots(input_dev, features->touch_max); 1554 input_mt_init_slots(input_dev, features->touch_max);
1471 input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 1555 input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
1472 0, MT_TOOL_MAX, 0, 0); 1556 0, MT_TOOL_MAX, 0, 0);
@@ -1552,6 +1636,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
1552 } 1636 }
1553 break; 1637 break;
1554 } 1638 }
1639 return 0;
1555} 1640}
1556 1641
1557static const struct wacom_features wacom_features_0x00 = 1642static const struct wacom_features wacom_features_0x00 =
@@ -1784,6 +1869,9 @@ static const struct wacom_features wacom_features_0xE3 =
1784 { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 1869 { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255,
1785 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 1870 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
1786 .touch_max = 2 }; 1871 .touch_max = 2 };
1872static const struct wacom_features wacom_features_0xE5 =
1873 { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255,
1874 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
1787static const struct wacom_features wacom_features_0xE6 = 1875static const struct wacom_features wacom_features_0xE6 =
1788 { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, 1876 { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255,
1789 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 1877 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
@@ -1962,6 +2050,7 @@ const struct usb_device_id wacom_ids[] = {
1962 { USB_DEVICE_WACOM(0x9F) }, 2050 { USB_DEVICE_WACOM(0x9F) },
1963 { USB_DEVICE_WACOM(0xE2) }, 2051 { USB_DEVICE_WACOM(0xE2) },
1964 { USB_DEVICE_WACOM(0xE3) }, 2052 { USB_DEVICE_WACOM(0xE3) },
2053 { USB_DEVICE_WACOM(0xE5) },
1965 { USB_DEVICE_WACOM(0xE6) }, 2054 { USB_DEVICE_WACOM(0xE6) },
1966 { USB_DEVICE_WACOM(0xEC) }, 2055 { USB_DEVICE_WACOM(0xEC) },
1967 { USB_DEVICE_WACOM(0x47) }, 2056 { USB_DEVICE_WACOM(0x47) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 321269c1ac4c..78fbd3f42009 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,10 @@
25#define WACOM_PKGLEN_BBTOUCH3 64 25#define WACOM_PKGLEN_BBTOUCH3 64
26#define WACOM_PKGLEN_BBPEN 10 26#define WACOM_PKGLEN_BBPEN 10
27#define WACOM_PKGLEN_WIRELESS 32 27#define WACOM_PKGLEN_WIRELESS 32
28#define WACOM_PKGLEN_MTOUCH 62
29
30/* wacom data size per MT contact */
31#define WACOM_BYTES_PER_MT_PACKET 11
28 32
29/* device IDs */ 33/* device IDs */
30#define STYLUS_DEVICE_ID 0x02 34#define STYLUS_DEVICE_ID 0x02
@@ -41,6 +45,7 @@
41#define WACOM_REPORT_INTUOS5PAD 3 45#define WACOM_REPORT_INTUOS5PAD 3
42#define WACOM_REPORT_TPC1FG 6 46#define WACOM_REPORT_TPC1FG 6
43#define WACOM_REPORT_TPC2FG 13 47#define WACOM_REPORT_TPC2FG 13
48#define WACOM_REPORT_TPCMT 13
44#define WACOM_REPORT_TPCHID 15 49#define WACOM_REPORT_TPCHID 15
45#define WACOM_REPORT_TPCST 16 50#define WACOM_REPORT_TPCST 16
46 51
@@ -76,6 +81,7 @@ enum {
76 WACOM_MO, 81 WACOM_MO,
77 TABLETPC, 82 TABLETPC,
78 TABLETPC2FG, 83 TABLETPC2FG,
84 MTSCREEN,
79 MAX_TYPE 85 MAX_TYPE
80}; 86};
81 87
@@ -118,6 +124,8 @@ struct wacom_wac {
118 struct input_dev *input; 124 struct input_dev *input;
119 int pid; 125 int pid;
120 int battery_capacity; 126 int battery_capacity;
127 int num_contacts_left;
128 int *slots;
121}; 129};
122 130
123#endif 131#endif