aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tablet/wacom_sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r--drivers/input/tablet/wacom_sys.c244
1 files changed, 180 insertions, 64 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 79a0509882d4..cad5602d3ce4 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -28,6 +28,7 @@
28#define HID_USAGE_Y_TILT 0x3e 28#define HID_USAGE_Y_TILT 0x3e
29#define HID_USAGE_FINGER 0x22 29#define HID_USAGE_FINGER 0x22
30#define HID_USAGE_STYLUS 0x20 30#define HID_USAGE_STYLUS 0x20
31#define HID_USAGE_CONTACTMAX 0x55
31#define HID_COLLECTION 0xa1 32#define HID_COLLECTION 0xa1
32#define HID_COLLECTION_LOGICAL 0x02 33#define HID_COLLECTION_LOGICAL 0x02
33#define HID_COLLECTION_END 0xc0 34#define HID_COLLECTION_END 0xc0
@@ -204,6 +205,27 @@ static int wacom_parse_logical_collection(unsigned char *report,
204 return length; 205 return length;
205} 206}
206 207
208static void wacom_retrieve_report_data(struct usb_interface *intf,
209 struct wacom_features *features)
210{
211 int result = 0;
212 unsigned char *rep_data;
213
214 rep_data = kmalloc(2, GFP_KERNEL);
215 if (rep_data) {
216
217 rep_data[0] = 12;
218 result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
219 rep_data[0], &rep_data, 2,
220 WAC_MSG_RETRIES);
221
222 if (result >= 0 && rep_data[1] > 2)
223 features->touch_max = rep_data[1];
224
225 kfree(rep_data);
226 }
227}
228
207/* 229/*
208 * Interface Descriptor of wacom devices can be incomplete and 230 * Interface Descriptor of wacom devices can be incomplete and
209 * inconsistent so wacom_features table is used to store stylus 231 * inconsistent so wacom_features table is used to store stylus
@@ -236,6 +258,9 @@ static int wacom_parse_logical_collection(unsigned char *report,
236 * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical 258 * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical
237 * Collection. Instead they define a Logical Collection with a single 259 * Collection. Instead they define a Logical Collection with a single
238 * Logical Maximum for both X and Y. 260 * Logical Maximum for both X and Y.
261 *
262 * Intuos5 touch interface does not contain useful data. We deal with
263 * this after returning from this function.
239 */ 264 */
240static int wacom_parse_hid(struct usb_interface *intf, 265static int wacom_parse_hid(struct usb_interface *intf,
241 struct hid_descriptor *hid_desc, 266 struct hid_descriptor *hid_desc,
@@ -295,6 +320,10 @@ static int wacom_parse_hid(struct usb_interface *intf,
295 /* need to reset back */ 320 /* need to reset back */
296 features->pktlen = WACOM_PKGLEN_TPC2FG; 321 features->pktlen = WACOM_PKGLEN_TPC2FG;
297 } 322 }
323
324 if (features->type == MTSCREEN)
325 features->pktlen = WACOM_PKGLEN_MTOUCH;
326
298 if (features->type == BAMBOO_PT) { 327 if (features->type == BAMBOO_PT) {
299 /* need to reset back */ 328 /* need to reset back */
300 features->pktlen = WACOM_PKGLEN_BBTOUCH; 329 features->pktlen = WACOM_PKGLEN_BBTOUCH;
@@ -327,18 +356,15 @@ static int wacom_parse_hid(struct usb_interface *intf,
327 case HID_USAGE_Y: 356 case HID_USAGE_Y:
328 if (usage == WCM_DESKTOP) { 357 if (usage == WCM_DESKTOP) {
329 if (finger) { 358 if (finger) {
330 features->device_type = BTN_TOOL_FINGER; 359 int type = features->type;
331 if (features->type == TABLETPC2FG) { 360
332 /* need to reset back */ 361 if (type == TABLETPC2FG || type == MTSCREEN) {
333 features->pktlen = WACOM_PKGLEN_TPC2FG;
334 features->y_max = 362 features->y_max =
335 get_unaligned_le16(&report[i + 3]); 363 get_unaligned_le16(&report[i + 3]);
336 features->y_phy = 364 features->y_phy =
337 get_unaligned_le16(&report[i + 6]); 365 get_unaligned_le16(&report[i + 6]);
338 i += 7; 366 i += 7;
339 } else if (features->type == BAMBOO_PT) { 367 } else if (type == BAMBOO_PT) {
340 /* need to reset back */
341 features->pktlen = WACOM_PKGLEN_BBTOUCH;
342 features->y_phy = 368 features->y_phy =
343 get_unaligned_le16(&report[i + 3]); 369 get_unaligned_le16(&report[i + 3]);
344 features->y_max = 370 features->y_max =
@@ -352,10 +378,6 @@ static int wacom_parse_hid(struct usb_interface *intf,
352 i += 4; 378 i += 4;
353 } 379 }
354 } else if (pen) { 380 } else if (pen) {
355 /* penabled only accepts exact bytes of data */
356 if (features->type == TABLETPC2FG)
357 features->pktlen = WACOM_PKGLEN_GRAPHIRE;
358 features->device_type = BTN_TOOL_PEN;
359 features->y_max = 381 features->y_max =
360 get_unaligned_le16(&report[i + 3]); 382 get_unaligned_le16(&report[i + 3]);
361 i += 4; 383 i += 4;
@@ -377,6 +399,11 @@ static int wacom_parse_hid(struct usb_interface *intf,
377 pen = 1; 399 pen = 1;
378 i++; 400 i++;
379 break; 401 break;
402
403 case HID_USAGE_CONTACTMAX:
404 wacom_retrieve_report_data(intf, features);
405 i++;
406 break;
380 } 407 }
381 break; 408 break;
382 409
@@ -413,22 +440,29 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
413 if (!rep_data) 440 if (!rep_data)
414 return error; 441 return error;
415 442
416 /* ask to report tablet data if it is MT Tablet PC or 443 /* ask to report Wacom data */
417 * not a Tablet PC */ 444 if (features->device_type == BTN_TOOL_FINGER) {
418 if (features->type == TABLETPC2FG) { 445 /* if it is an MT Tablet PC touch */
419 do { 446 if (features->type == TABLETPC2FG ||
420 rep_data[0] = 3; 447 features->type == MTSCREEN) {
421 rep_data[1] = 4; 448 do {
422 rep_data[2] = 0; 449 rep_data[0] = 3;
423 rep_data[3] = 0; 450 rep_data[1] = 4;
424 report_id = 3; 451 rep_data[2] = 0;
425 error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, 452 rep_data[3] = 0;
426 report_id, rep_data, 4, 1); 453 report_id = 3;
427 if (error >= 0) 454 error = wacom_set_report(intf,
428 error = wacom_get_report(intf, 455 WAC_HID_FEATURE_REPORT,
429 WAC_HID_FEATURE_REPORT, 456 report_id,
430 report_id, rep_data, 4, 1); 457 rep_data, 4, 1);
431 } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); 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 }
432 } else if (features->type != TABLETPC && 466 } else if (features->type != TABLETPC &&
433 features->type != WIRELESS && 467 features->type != WIRELESS &&
434 features->device_type == BTN_TOOL_PEN) { 468 features->device_type == BTN_TOOL_PEN) {
@@ -450,7 +484,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
450} 484}
451 485
452static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, 486static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
453 struct wacom_features *features) 487 struct wacom_features *features)
454{ 488{
455 int error = 0; 489 int error = 0;
456 struct usb_host_interface *interface = intf->cur_altsetting; 490 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -478,16 +512,21 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
478 } 512 }
479 } 513 }
480 514
481 /* only Tablet PCs and Bamboo P&T need to retrieve the info */ 515 /* only devices that support touch need to retrieve the info */
482 if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && 516 if (features->type != TABLETPC &&
483 (features->type != BAMBOO_PT)) 517 features->type != TABLETPC2FG &&
518 features->type != BAMBOO_PT &&
519 features->type != MTSCREEN) {
484 goto out; 520 goto out;
521 }
485 522
486 if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { 523 error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc);
487 if (usb_get_extra_descriptor(&interface->endpoint[0], 524 if (error) {
488 HID_DEVICET_REPORT, &hid_desc)) { 525 error = usb_get_extra_descriptor(&interface->endpoint[0],
489 printk("wacom: can not retrieve extra class descriptor\n"); 526 HID_DEVICET_REPORT, &hid_desc);
490 error = 1; 527 if (error) {
528 dev_err(&intf->dev,
529 "can not retrieve extra class descriptor\n");
491 goto out; 530 goto out;
492 } 531 }
493 } 532 }
@@ -577,23 +616,39 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom)
577static int wacom_led_control(struct wacom *wacom) 616static int wacom_led_control(struct wacom *wacom)
578{ 617{
579 unsigned char *buf; 618 unsigned char *buf;
580 int retval, led = 0; 619 int retval;
581 620
582 buf = kzalloc(9, GFP_KERNEL); 621 buf = kzalloc(9, GFP_KERNEL);
583 if (!buf) 622 if (!buf)
584 return -ENOMEM; 623 return -ENOMEM;
585 624
586 if (wacom->wacom_wac.features.type == WACOM_21UX2 || 625 if (wacom->wacom_wac.features.type >= INTUOS5S &&
587 wacom->wacom_wac.features.type == WACOM_24HD) 626 wacom->wacom_wac.features.type <= INTUOS5L) {
588 led = (wacom->led.select[1] << 4) | 0x40; 627 /*
589 628 * Touch Ring and crop mark LED luminance may take on
590 led |= wacom->led.select[0] | 0x4; 629 * one of four values:
591 630 * 0 = Low; 1 = Medium; 2 = High; 3 = Off
592 buf[0] = WAC_CMD_LED_CONTROL; 631 */
593 buf[1] = led; 632 int ring_led = wacom->led.select[0] & 0x03;
594 buf[2] = wacom->led.llv; 633 int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03;
595 buf[3] = wacom->led.hlv; 634 int crop_lum = 0;
596 buf[4] = wacom->led.img_lum; 635
636 buf[0] = WAC_CMD_LED_CONTROL;
637 buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led);
638 }
639 else {
640 int led = wacom->led.select[0] | 0x4;
641
642 if (wacom->wacom_wac.features.type == WACOM_21UX2 ||
643 wacom->wacom_wac.features.type == WACOM_24HD)
644 led |= (wacom->led.select[1] << 4) | 0x40;
645
646 buf[0] = WAC_CMD_LED_CONTROL;
647 buf[1] = led;
648 buf[2] = wacom->led.llv;
649 buf[3] = wacom->led.hlv;
650 buf[4] = wacom->led.img_lum;
651 }
597 652
598 retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, 653 retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
599 buf, 9, WAC_CMD_RETRIES); 654 buf, 9, WAC_CMD_RETRIES);
@@ -786,6 +841,17 @@ static struct attribute_group intuos4_led_attr_group = {
786 .attrs = intuos4_led_attrs, 841 .attrs = intuos4_led_attrs,
787}; 842};
788 843
844static struct attribute *intuos5_led_attrs[] = {
845 &dev_attr_status0_luminance.attr,
846 &dev_attr_status_led0_select.attr,
847 NULL
848};
849
850static struct attribute_group intuos5_led_attr_group = {
851 .name = "wacom_led",
852 .attrs = intuos5_led_attrs,
853};
854
789static int wacom_initialize_leds(struct wacom *wacom) 855static int wacom_initialize_leds(struct wacom *wacom)
790{ 856{
791 int error; 857 int error;
@@ -815,6 +881,19 @@ static int wacom_initialize_leds(struct wacom *wacom)
815 &cintiq_led_attr_group); 881 &cintiq_led_attr_group);
816 break; 882 break;
817 883
884 case INTUOS5S:
885 case INTUOS5:
886 case INTUOS5L:
887 wacom->led.select[0] = 0;
888 wacom->led.select[1] = 0;
889 wacom->led.llv = 32;
890 wacom->led.hlv = 0;
891 wacom->led.img_lum = 0;
892
893 error = sysfs_create_group(&wacom->intf->dev.kobj,
894 &intuos5_led_attr_group);
895 break;
896
818 default: 897 default:
819 return 0; 898 return 0;
820 } 899 }
@@ -843,6 +922,13 @@ static void wacom_destroy_leds(struct wacom *wacom)
843 sysfs_remove_group(&wacom->intf->dev.kobj, 922 sysfs_remove_group(&wacom->intf->dev.kobj,
844 &cintiq_led_attr_group); 923 &cintiq_led_attr_group);
845 break; 924 break;
925
926 case INTUOS5S:
927 case INTUOS5:
928 case INTUOS5L:
929 sysfs_remove_group(&wacom->intf->dev.kobj,
930 &intuos5_led_attr_group);
931 break;
846 } 932 }
847} 933}
848 934
@@ -904,8 +990,10 @@ static int wacom_register_input(struct wacom *wacom)
904 int error; 990 int error;
905 991
906 input_dev = input_allocate_device(); 992 input_dev = input_allocate_device();
907 if (!input_dev) 993 if (!input_dev) {
908 return -ENOMEM; 994 error = -ENOMEM;
995 goto fail1;
996 }
909 997
910 input_dev->name = wacom_wac->name; 998 input_dev->name = wacom_wac->name;
911 input_dev->dev.parent = &intf->dev; 999 input_dev->dev.parent = &intf->dev;
@@ -915,14 +1003,20 @@ static int wacom_register_input(struct wacom *wacom)
915 input_set_drvdata(input_dev, wacom); 1003 input_set_drvdata(input_dev, wacom);
916 1004
917 wacom_wac->input = input_dev; 1005 wacom_wac->input = input_dev;
918 wacom_setup_input_capabilities(input_dev, wacom_wac); 1006 error = wacom_setup_input_capabilities(input_dev, wacom_wac);
1007 if (error)
1008 goto fail1;
919 1009
920 error = input_register_device(input_dev); 1010 error = input_register_device(input_dev);
921 if (error) { 1011 if (error)
922 input_free_device(input_dev); 1012 goto fail2;
923 wacom_wac->input = NULL;
924 }
925 1013
1014 return 0;
1015
1016fail2:
1017 input_free_device(input_dev);
1018 wacom_wac->input = NULL;
1019fail1:
926 return error; 1020 return error;
927} 1021}
928 1022
@@ -941,22 +1035,22 @@ static void wacom_wireless_work(struct work_struct *work)
941 wacom = usb_get_intfdata(usbdev->config->interface[1]); 1035 wacom = usb_get_intfdata(usbdev->config->interface[1]);
942 if (wacom->wacom_wac.input) 1036 if (wacom->wacom_wac.input)
943 input_unregister_device(wacom->wacom_wac.input); 1037 input_unregister_device(wacom->wacom_wac.input);
944 wacom->wacom_wac.input = 0; 1038 wacom->wacom_wac.input = NULL;
945 1039
946 /* Touch interface */ 1040 /* Touch interface */
947 wacom = usb_get_intfdata(usbdev->config->interface[2]); 1041 wacom = usb_get_intfdata(usbdev->config->interface[2]);
948 if (wacom->wacom_wac.input) 1042 if (wacom->wacom_wac.input)
949 input_unregister_device(wacom->wacom_wac.input); 1043 input_unregister_device(wacom->wacom_wac.input);
950 wacom->wacom_wac.input = 0; 1044 wacom->wacom_wac.input = NULL;
951 1045
952 if (wacom_wac->pid == 0) { 1046 if (wacom_wac->pid == 0) {
953 printk(KERN_INFO "wacom: wireless tablet disconnected\n"); 1047 dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
954 } else { 1048 } else {
955 const struct usb_device_id *id = wacom_ids; 1049 const struct usb_device_id *id = wacom_ids;
956 1050
957 printk(KERN_INFO 1051 dev_info(&wacom->intf->dev,
958 "wacom: wireless tablet connected with PID %x\n", 1052 "wireless tablet connected with PID %x\n",
959 wacom_wac->pid); 1053 wacom_wac->pid);
960 1054
961 while (id->match_flags) { 1055 while (id->match_flags) {
962 if (id->idVendor == USB_VENDOR_ID_WACOM && 1056 if (id->idVendor == USB_VENDOR_ID_WACOM &&
@@ -966,8 +1060,8 @@ static void wacom_wireless_work(struct work_struct *work)
966 } 1060 }
967 1061
968 if (!id->match_flags) { 1062 if (!id->match_flags) {
969 printk(KERN_INFO 1063 dev_info(&wacom->intf->dev,
970 "wacom: ignorning unknown PID.\n"); 1064 "ignoring unknown PID.\n");
971 return; 1065 return;
972 } 1066 }
973 1067
@@ -1038,11 +1132,33 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
1038 1132
1039 endpoint = &intf->cur_altsetting->endpoint[0].desc; 1133 endpoint = &intf->cur_altsetting->endpoint[0].desc;
1040 1134
1041 /* Retrieve the physical and logical size for OEM devices */ 1135 /* Retrieve the physical and logical size for touch devices */
1042 error = wacom_retrieve_hid_descriptor(intf, features); 1136 error = wacom_retrieve_hid_descriptor(intf, features);
1043 if (error) 1137 if (error)
1044 goto fail3; 1138 goto fail3;
1045 1139
1140 /*
1141 * Intuos5 has no useful data about its touch interface in its
1142 * HID descriptor. If this is the touch interface (wMaxPacketSize
1143 * of WACOM_PKGLEN_BBTOUCH3), override the table values.
1144 */
1145 if (features->type >= INTUOS5S && features->type <= INTUOS5L) {
1146 if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
1147 features->device_type = BTN_TOOL_FINGER;
1148 features->pktlen = WACOM_PKGLEN_BBTOUCH3;
1149
1150 features->x_phy =
1151 (features->x_max * 100) / features->x_resolution;
1152 features->y_phy =
1153 (features->y_max * 100) / features->y_resolution;
1154
1155 features->x_max = 4096;
1156 features->y_max = 4096;
1157 } else {
1158 features->device_type = BTN_TOOL_PEN;
1159 }
1160 }
1161
1046 wacom_setup_device_quirks(features); 1162 wacom_setup_device_quirks(features);
1047 1163
1048 strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); 1164 strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));