Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ping Cheng and committed by
Dmitry Torokhov
1963518b f393ee2b

+157 -45
+2 -2
drivers/input/tablet/wacom.h
··· 135 135 136 136 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); 137 137 void wacom_setup_device_quirks(struct wacom_features *features); 138 - void wacom_setup_input_capabilities(struct input_dev *input_dev, 139 - struct wacom_wac *wacom_wac); 138 + int wacom_setup_input_capabilities(struct input_dev *input_dev, 139 + struct wacom_wac *wacom_wac); 140 140 #endif
+53 -38
drivers/input/tablet/wacom_sys.c
··· 317 317 /* need to reset back */ 318 318 features->pktlen = WACOM_PKGLEN_TPC2FG; 319 319 } 320 + 321 + if (features->type == MTSCREEN) 322 + features->pktlen = WACOM_PKGLEN_MTOUCH; 323 + 320 324 if (features->type == BAMBOO_PT) { 321 325 /* need to reset back */ 322 326 features->pktlen = WACOM_PKGLEN_BBTOUCH; ··· 353 349 case HID_USAGE_Y: 354 350 if (usage == WCM_DESKTOP) { 355 351 if (finger) { 356 - features->device_type = BTN_TOOL_FINGER; 357 - if (features->type == TABLETPC2FG) { 358 - /* need to reset back */ 359 - features->pktlen = WACOM_PKGLEN_TPC2FG; 352 + int type = features->type; 353 + 354 + if (type == TABLETPC2FG || type == MTSCREEN) { 360 355 features->y_max = 361 356 get_unaligned_le16(&report[i + 3]); 362 357 features->y_phy = 363 358 get_unaligned_le16(&report[i + 6]); 364 359 i += 7; 365 - } else if (features->type == BAMBOO_PT) { 366 - /* need to reset back */ 367 - features->pktlen = WACOM_PKGLEN_BBTOUCH; 360 + } else if (type == BAMBOO_PT) { 368 361 features->y_phy = 369 362 get_unaligned_le16(&report[i + 3]); 370 363 features->y_max = ··· 375 374 i += 4; 376 375 } 377 376 } else if (pen) { 378 - /* penabled only accepts exact bytes of data */ 379 - if (features->type == TABLETPC2FG) 380 - features->pktlen = WACOM_PKGLEN_GRAPHIRE; 381 - features->device_type = BTN_TOOL_PEN; 382 377 features->y_max = 383 378 get_unaligned_le16(&report[i + 3]); 384 379 i += 4; ··· 437 440 if (!rep_data) 438 441 return error; 439 442 440 - /* ask to report tablet data if it is MT Tablet PC or 441 - * not a Tablet PC */ 442 - if (features->type == TABLETPC2FG) { 443 - do { 444 - rep_data[0] = 3; 445 - rep_data[1] = 4; 446 - rep_data[2] = 0; 447 - rep_data[3] = 0; 448 - report_id = 3; 449 - error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, 450 - report_id, rep_data, 4, 1); 451 - if (error >= 0) 452 - error = wacom_get_report(intf, 453 - WAC_HID_FEATURE_REPORT, 454 - report_id, rep_data, 4, 1); 455 - } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); 443 + /* ask to report Wacom data */ 444 + if (features->device_type == BTN_TOOL_FINGER) { 445 + /* if it is an MT Tablet PC touch */ 446 + if (features->type == TABLETPC2FG || 447 + features->type == MTSCREEN) { 448 + do { 449 + rep_data[0] = 3; 450 + rep_data[1] = 4; 451 + rep_data[2] = 0; 452 + rep_data[3] = 0; 453 + report_id = 3; 454 + error = wacom_set_report(intf, 455 + WAC_HID_FEATURE_REPORT, 456 + report_id, 457 + rep_data, 4, 1); 458 + if (error >= 0) 459 + error = wacom_get_report(intf, 460 + WAC_HID_FEATURE_REPORT, 461 + report_id, 462 + rep_data, 4, 1); 463 + } while ((error < 0 || rep_data[1] != 4) && 464 + limit++ < WAC_MSG_RETRIES); 465 + } 456 466 } else if (features->type != TABLETPC && 457 467 features->type != WIRELESS && 458 468 features->device_type == BTN_TOOL_PEN) { ··· 481 477 } 482 478 483 479 static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, 484 - struct wacom_features *features) 480 + struct wacom_features *features) 485 481 { 486 482 int error = 0; 487 483 struct usb_host_interface *interface = intf->cur_altsetting; ··· 509 505 } 510 506 } 511 507 512 - /* only Tablet PCs and Bamboo P&T need to retrieve the info */ 513 - if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && 514 - (features->type != BAMBOO_PT)) 508 + /* only devices that support touch need to retrieve the info */ 509 + if (features->type != TABLETPC && 510 + features->type != TABLETPC2FG && 511 + features->type != BAMBOO_PT && 512 + features->type != MTSCREEN) { 515 513 goto out; 514 + } 516 515 517 516 if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { 518 517 if (usb_get_extra_descriptor(&interface->endpoint[0], ··· 985 978 int error; 986 979 987 980 input_dev = input_allocate_device(); 988 - if (!input_dev) 989 - return -ENOMEM; 981 + if (!input_dev) { 982 + error = -ENOMEM; 983 + goto fail1; 984 + } 990 985 991 986 input_dev->name = wacom_wac->name; 992 987 input_dev->dev.parent = &intf->dev; ··· 998 989 input_set_drvdata(input_dev, wacom); 999 990 1000 991 wacom_wac->input = input_dev; 1001 - wacom_setup_input_capabilities(input_dev, wacom_wac); 992 + error = wacom_setup_input_capabilities(input_dev, wacom_wac); 993 + if (error) 994 + goto fail1; 1002 995 1003 996 error = input_register_device(input_dev); 1004 - if (error) { 1005 - input_free_device(input_dev); 1006 - wacom_wac->input = NULL; 1007 - } 997 + if (error) 998 + goto fail2; 1008 999 1000 + return 0; 1001 + 1002 + fail2: 1003 + input_free_device(input_dev); 1004 + wacom_wac->input = NULL; 1005 + fail1: 1009 1006 return error; 1010 1007 } 1011 1008
+94 -5
drivers/input/tablet/wacom_wac.c
··· 768 768 return 1; 769 769 } 770 770 771 + static 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 + 790 + static 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 + 771 837 static int wacom_tpc_mt_touch(struct wacom_wac *wacom) 772 838 { 773 839 struct input_dev *input = wacom->input; ··· 871 805 struct input_dev *input = wacom->input; 872 806 bool prox; 873 807 int x = 0, y = 0; 808 + 809 + if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) 810 + return 0; 874 811 875 812 if (!wacom->shared->stylus_in_proximity) { 876 813 if (len == WACOM_PKGLEN_TPC1FG) { ··· 942 873 943 874 switch (len) { 944 875 case WACOM_PKGLEN_TPC1FG: 945 - return wacom_tpc_single_touch(wacom, len); 876 + return wacom_tpc_single_touch(wacom, len); 946 877 947 878 case WACOM_PKGLEN_TPC2FG: 948 - return wacom_tpc_mt_touch(wacom); 879 + return wacom_tpc_mt_touch(wacom); 949 880 950 881 default: 951 882 switch (data[0]) { ··· 953 884 case WACOM_REPORT_TPCHID: 954 885 case WACOM_REPORT_TPCST: 955 886 return wacom_tpc_single_touch(wacom, len); 887 + 888 + case WACOM_REPORT_TPCMT: 889 + return wacom_mt_touch(wacom); 956 890 957 891 case WACOM_REPORT_PENABLED: 958 892 return wacom_tpc_pen(wacom); ··· 1236 1164 1237 1165 case TABLETPC: 1238 1166 case TABLETPC2FG: 1167 + case MTSCREEN: 1239 1168 sync = wacom_tpc_irq(wacom_wac, len); 1240 1169 break; 1241 1170 ··· 1310 1237 /* these device have multiple inputs */ 1311 1238 if (features->type == TABLETPC || features->type == TABLETPC2FG || 1312 1239 features->type == BAMBOO_PT || features->type == WIRELESS || 1313 - (features->type >= INTUOS5S && features->type <= INTUOS5L)) 1240 + (features->type >= INTUOS5S && features->type <= INTUOS5L) || 1241 + features->type == MTSCREEN) 1314 1242 features->quirks |= WACOM_QUIRK_MULTI_INPUT; 1315 1243 1316 1244 /* quirk for bamboo touch with 2 low res touches */ ··· 1342 1268 return (logical_max * 100) / physical_max; 1343 1269 } 1344 1270 1345 - void wacom_setup_input_capabilities(struct input_dev *input_dev, 1346 - struct wacom_wac *wacom_wac) 1271 + int wacom_setup_input_capabilities(struct input_dev *input_dev, 1272 + struct wacom_wac *wacom_wac) 1347 1273 { 1348 1274 struct wacom_features *features = &wacom_wac->features; 1349 1275 int i; ··· 1539 1465 break; 1540 1466 1541 1467 case TABLETPC2FG: 1468 + case MTSCREEN: 1542 1469 if (features->device_type == BTN_TOOL_FINGER) { 1470 + 1471 + wacom_wac->slots = kmalloc(features->touch_max * 1472 + sizeof(int), 1473 + GFP_KERNEL); 1474 + if (!wacom_wac->slots) 1475 + return -ENOMEM; 1476 + 1477 + for (i = 0; i < features->touch_max; i++) 1478 + wacom_wac->slots[i] = -1; 1543 1479 1544 1480 input_mt_init_slots(input_dev, features->touch_max); 1545 1481 input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, ··· 1636 1552 } 1637 1553 break; 1638 1554 } 1555 + return 0; 1639 1556 } 1640 1557 1641 1558 static const struct wacom_features wacom_features_0x00 = ··· 1869 1784 { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 1870 1785 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 1871 1786 .touch_max = 2 }; 1787 + static const struct wacom_features wacom_features_0xE5 = 1788 + { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255, 1789 + 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 1872 1790 static const struct wacom_features wacom_features_0xE6 = 1873 1791 { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, 1874 1792 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ··· 2050 1962 { USB_DEVICE_WACOM(0x9F) }, 2051 1963 { USB_DEVICE_WACOM(0xE2) }, 2052 1964 { USB_DEVICE_WACOM(0xE3) }, 1965 + { USB_DEVICE_WACOM(0xE5) }, 2053 1966 { USB_DEVICE_WACOM(0xE6) }, 2054 1967 { USB_DEVICE_WACOM(0xEC) }, 2055 1968 { USB_DEVICE_WACOM(0x47) },
+8
drivers/input/tablet/wacom_wac.h
··· 25 25 #define WACOM_PKGLEN_BBTOUCH3 64 26 26 #define WACOM_PKGLEN_BBPEN 10 27 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 33 /* device IDs */ 30 34 #define STYLUS_DEVICE_ID 0x02 ··· 45 41 #define WACOM_REPORT_INTUOS5PAD 3 46 42 #define WACOM_REPORT_TPC1FG 6 47 43 #define WACOM_REPORT_TPC2FG 13 44 + #define WACOM_REPORT_TPCMT 13 48 45 #define WACOM_REPORT_TPCHID 15 49 46 #define WACOM_REPORT_TPCST 16 50 47 ··· 81 76 WACOM_MO, 82 77 TABLETPC, 83 78 TABLETPC2FG, 79 + MTSCREEN, 84 80 MAX_TYPE 85 81 }; 86 82 ··· 124 118 struct input_dev *input; 125 119 int pid; 126 120 int battery_capacity; 121 + int num_contacts_left; 122 + int *slots; 127 123 }; 128 124 129 125 #endif