diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-driver-wacom | 64 | ||||
-rw-r--r-- | Documentation/ABI/testing/sysfs-wacom | 10 | ||||
-rw-r--r-- | drivers/input/tablet/wacom.h | 6 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 301 |
4 files changed, 341 insertions, 40 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom new file mode 100644 index 000000000000..dfe1d460cf54 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-wacom | |||
@@ -0,0 +1,64 @@ | |||
1 | What: /sys/class/hidraw/hidraw*/device/speed | ||
2 | Date: April 2010 | ||
3 | Kernel Version: 2.6.35 | ||
4 | Contact: linux-bluetooth@vger.kernel.org | ||
5 | Description: | ||
6 | The /sys/class/hidraw/hidraw*/device/speed file controls | ||
7 | reporting speed of Wacom bluetooth tablet. Reading from | ||
8 | this file returns 1 if tablet reports in high speed mode | ||
9 | or 0 otherwise. Writing to this file one of these values | ||
10 | switches reporting speed. | ||
11 | |||
12 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led | ||
13 | Date: August 2011 | ||
14 | Contact: linux-input@vger.kernel.org | ||
15 | Description: | ||
16 | Attribute group for control of the status LEDs and the OLED | ||
17 | displays found on the Wacom Intuos 4 M, L, and XL tablets. This | ||
18 | attribute group is not available for other Wacom tablets. | ||
19 | Therefore its presence implicitly signifies the presence of | ||
20 | said LEDs and OLED displays on the tablet device. | ||
21 | |||
22 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance | ||
23 | Date: August 2011 | ||
24 | Contact: linux-input@vger.kernel.org | ||
25 | Description: | ||
26 | Writing to this file sets the status LED luminance (0..127) | ||
27 | when the stylus does not touch the tablet surface, and no | ||
28 | button is pressed on the stylus. | ||
29 | |||
30 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance | ||
31 | Date: August 2011 | ||
32 | Contact: linux-input@vger.kernel.org | ||
33 | Description: | ||
34 | Writing to this file sets the status LED luminance (0..127) | ||
35 | when the stylus touches the tablet surface, or any button is | ||
36 | pressed on the stylus. | ||
37 | |||
38 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led_select | ||
39 | Date: August 2011 | ||
40 | Contact: linux-input@vger.kernel.org | ||
41 | Description: | ||
42 | Writing to this file sets which one of the four status LEDs is | ||
43 | active (0..3). The other three LEDs are always inactive. By | ||
44 | means of specifying "-1" it is possible to set all status LEDs | ||
45 | to inactive. | ||
46 | |||
47 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance | ||
48 | Date: August 2011 | ||
49 | Contact: linux-input@vger.kernel.org | ||
50 | Description: | ||
51 | Writing to this file sets the overall luminance level (0..15) | ||
52 | of all eight button OLED displays. | ||
53 | |||
54 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg | ||
55 | Date: August 2011 | ||
56 | Contact: linux-input@vger.kernel.org | ||
57 | Description: | ||
58 | When writing a 1024 byte raw image in Wacom Intuos 4 | ||
59 | interleaving format to the file, the image shows up on Button N | ||
60 | of the device. The image is a 64x32 pixel 4-bit gray image. The | ||
61 | 1024 byte binary is split up into 16x 64 byte chunks. Each 64 | ||
62 | byte chunk encodes the image data for two consecutive lines on | ||
63 | the display. The low nibble of each byte contains the first | ||
64 | line, and the high nibble contains the second line. | ||
diff --git a/Documentation/ABI/testing/sysfs-wacom b/Documentation/ABI/testing/sysfs-wacom deleted file mode 100644 index 1517976e25c4..000000000000 --- a/Documentation/ABI/testing/sysfs-wacom +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | What: /sys/class/hidraw/hidraw*/device/speed | ||
2 | Date: April 2010 | ||
3 | Kernel Version: 2.6.35 | ||
4 | Contact: linux-bluetooth@vger.kernel.org | ||
5 | Description: | ||
6 | The /sys/class/hidraw/hidraw*/device/speed file controls | ||
7 | reporting speed of wacom bluetooth tablet. Reading from | ||
8 | this file returns 1 if tablet reports in high speed mode | ||
9 | or 0 otherwise. Writing to this file one of these values | ||
10 | switches reporting speed. | ||
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 23317bd09c82..00332d66bc4b 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -114,6 +114,12 @@ struct wacom { | |||
114 | struct mutex lock; | 114 | struct mutex lock; |
115 | bool open; | 115 | bool open; |
116 | char phys[32]; | 116 | char phys[32]; |
117 | struct wacom_led { | ||
118 | u8 select; /* status led selector (0..3, -1=none) */ | ||
119 | u8 llv; /* status led brightness no button */ | ||
120 | u8 hlv; /* status led brightness button pressed */ | ||
121 | u8 img_lum; /* OLED matrix display brightness */ | ||
122 | } led; | ||
117 | }; | 123 | }; |
118 | 124 | ||
119 | extern const struct usb_device_id wacom_ids[]; | 125 | extern const struct usb_device_id wacom_ids[]; |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index d27c9d91630b..0eccf57df5cd 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -48,27 +48,49 @@ struct hid_descriptor { | |||
48 | /* defines to get/set USB message */ | 48 | /* defines to get/set USB message */ |
49 | #define USB_REQ_GET_REPORT 0x01 | 49 | #define USB_REQ_GET_REPORT 0x01 |
50 | #define USB_REQ_SET_REPORT 0x09 | 50 | #define USB_REQ_SET_REPORT 0x09 |
51 | |||
51 | #define WAC_HID_FEATURE_REPORT 0x03 | 52 | #define WAC_HID_FEATURE_REPORT 0x03 |
52 | #define WAC_MSG_RETRIES 5 | 53 | #define WAC_MSG_RETRIES 5 |
53 | 54 | ||
54 | static int usb_get_report(struct usb_interface *intf, unsigned char type, | 55 | #define WAC_CMD_LED_CONTROL 0x20 |
55 | unsigned char id, void *buf, int size) | 56 | #define WAC_CMD_ICON_START 0x21 |
57 | #define WAC_CMD_ICON_XFER 0x23 | ||
58 | #define WAC_CMD_RETRIES 10 | ||
59 | |||
60 | static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id, | ||
61 | void *buf, size_t size, unsigned int retries) | ||
56 | { | 62 | { |
57 | return usb_control_msg(interface_to_usbdev(intf), | 63 | struct usb_device *dev = interface_to_usbdev(intf); |
58 | usb_rcvctrlpipe(interface_to_usbdev(intf), 0), | 64 | int retval; |
59 | USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 65 | |
60 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | 66 | do { |
61 | buf, size, 100); | 67 | retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
68 | USB_REQ_GET_REPORT, | ||
69 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
70 | (type << 8) + id, | ||
71 | intf->altsetting[0].desc.bInterfaceNumber, | ||
72 | buf, size, 100); | ||
73 | } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); | ||
74 | |||
75 | return retval; | ||
62 | } | 76 | } |
63 | 77 | ||
64 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | 78 | static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id, |
65 | unsigned char id, void *buf, int size) | 79 | void *buf, size_t size, unsigned int retries) |
66 | { | 80 | { |
67 | return usb_control_msg(interface_to_usbdev(intf), | 81 | struct usb_device *dev = interface_to_usbdev(intf); |
68 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | 82 | int retval; |
69 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 83 | |
70 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | 84 | do { |
71 | buf, size, 1000); | 85 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
86 | USB_REQ_SET_REPORT, | ||
87 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
88 | (type << 8) + id, | ||
89 | intf->altsetting[0].desc.bInterfaceNumber, | ||
90 | buf, size, 1000); | ||
91 | } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); | ||
92 | |||
93 | return retval; | ||
72 | } | 94 | } |
73 | 95 | ||
74 | static void wacom_sys_irq(struct urb *urb) | 96 | static void wacom_sys_irq(struct urb *urb) |
@@ -333,23 +355,23 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
333 | rep_data[2] = 0; | 355 | rep_data[2] = 0; |
334 | rep_data[3] = 0; | 356 | rep_data[3] = 0; |
335 | report_id = 3; | 357 | report_id = 3; |
336 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | 358 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, |
337 | report_id, rep_data, 4); | 359 | report_id, rep_data, 4, 1); |
338 | if (error >= 0) | 360 | if (error >= 0) |
339 | error = usb_get_report(intf, | 361 | error = wacom_get_report(intf, |
340 | WAC_HID_FEATURE_REPORT, report_id, | 362 | WAC_HID_FEATURE_REPORT, |
341 | rep_data, 4); | 363 | report_id, rep_data, 4, 1); |
342 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); | 364 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); |
343 | } else if (features->type != TABLETPC) { | 365 | } else if (features->type != TABLETPC) { |
344 | do { | 366 | do { |
345 | rep_data[0] = 2; | 367 | rep_data[0] = 2; |
346 | rep_data[1] = 2; | 368 | rep_data[1] = 2; |
347 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | 369 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, |
348 | report_id, rep_data, 2); | 370 | report_id, rep_data, 2, 1); |
349 | if (error >= 0) | 371 | if (error >= 0) |
350 | error = usb_get_report(intf, | 372 | error = wacom_get_report(intf, |
351 | WAC_HID_FEATURE_REPORT, report_id, | 373 | WAC_HID_FEATURE_REPORT, |
352 | rep_data, 2); | 374 | report_id, rep_data, 2, 1); |
353 | } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES); | 375 | } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES); |
354 | } | 376 | } |
355 | 377 | ||
@@ -468,6 +490,220 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom) | |||
468 | } | 490 | } |
469 | } | 491 | } |
470 | 492 | ||
493 | static int wacom_led_control(struct wacom *wacom) | ||
494 | { | ||
495 | unsigned char *buf; | ||
496 | int retval; | ||
497 | |||
498 | buf = kzalloc(9, GFP_KERNEL); | ||
499 | if (!buf) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | buf[0] = WAC_CMD_LED_CONTROL; | ||
503 | buf[1] = wacom->led.select >= 0 ? wacom->led.select | 4 : 0; | ||
504 | buf[2] = wacom->led.llv; | ||
505 | buf[3] = wacom->led.hlv; | ||
506 | buf[4] = wacom->led.img_lum; | ||
507 | |||
508 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, | ||
509 | buf, 9, WAC_CMD_RETRIES); | ||
510 | kfree(buf); | ||
511 | |||
512 | return retval; | ||
513 | } | ||
514 | |||
515 | static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img) | ||
516 | { | ||
517 | unsigned char *buf; | ||
518 | int i, retval; | ||
519 | |||
520 | buf = kzalloc(259, GFP_KERNEL); | ||
521 | if (!buf) | ||
522 | return -ENOMEM; | ||
523 | |||
524 | /* Send 'start' command */ | ||
525 | buf[0] = WAC_CMD_ICON_START; | ||
526 | buf[1] = 1; | ||
527 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START, | ||
528 | buf, 2, WAC_CMD_RETRIES); | ||
529 | if (retval < 0) | ||
530 | goto out; | ||
531 | |||
532 | buf[0] = WAC_CMD_ICON_XFER; | ||
533 | buf[1] = button_id & 0x07; | ||
534 | for (i = 0; i < 4; i++) { | ||
535 | buf[2] = i; | ||
536 | memcpy(buf + 3, img + i * 256, 256); | ||
537 | |||
538 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER, | ||
539 | buf, 259, WAC_CMD_RETRIES); | ||
540 | if (retval < 0) | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | /* Send 'stop' */ | ||
545 | buf[0] = WAC_CMD_ICON_START; | ||
546 | buf[1] = 0; | ||
547 | wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START, | ||
548 | buf, 2, WAC_CMD_RETRIES); | ||
549 | |||
550 | out: | ||
551 | kfree(buf); | ||
552 | return retval; | ||
553 | } | ||
554 | |||
555 | static ssize_t wacom_led_select_store(struct device *dev, | ||
556 | struct device_attribute *attr, | ||
557 | const char *buf, size_t count) | ||
558 | { | ||
559 | struct wacom *wacom = dev_get_drvdata(dev); | ||
560 | unsigned int id; | ||
561 | int err; | ||
562 | |||
563 | err = kstrtouint(buf, 10, &id); | ||
564 | if (err) | ||
565 | return err; | ||
566 | |||
567 | mutex_lock(&wacom->lock); | ||
568 | |||
569 | wacom->led.select = id; | ||
570 | err = wacom_led_control(wacom); | ||
571 | |||
572 | mutex_unlock(&wacom->lock); | ||
573 | |||
574 | return err < 0 ? err : count; | ||
575 | } | ||
576 | |||
577 | static DEVICE_ATTR(status_led_select, S_IWUSR, NULL, wacom_led_select_store); | ||
578 | |||
579 | static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest, | ||
580 | const char *buf, size_t count) | ||
581 | { | ||
582 | unsigned int value; | ||
583 | int err; | ||
584 | |||
585 | err = kstrtouint(buf, 10, &value); | ||
586 | if (err) | ||
587 | return err; | ||
588 | |||
589 | mutex_lock(&wacom->lock); | ||
590 | |||
591 | *dest = value & 0x7f; | ||
592 | err = wacom_led_control(wacom); | ||
593 | |||
594 | mutex_unlock(&wacom->lock); | ||
595 | |||
596 | return err < 0 ? err : count; | ||
597 | } | ||
598 | |||
599 | #define DEVICE_LUMINANCE_ATTR(name, field) \ | ||
600 | static ssize_t wacom_##name##_luminance_store(struct device *dev, \ | ||
601 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
602 | { \ | ||
603 | struct wacom *wacom = dev_get_drvdata(dev); \ | ||
604 | \ | ||
605 | return wacom_luminance_store(wacom, &wacom->led.field, \ | ||
606 | buf, count); \ | ||
607 | } \ | ||
608 | static DEVICE_ATTR(name##_luminance, S_IWUSR, \ | ||
609 | NULL, wacom_##name##_luminance_store) | ||
610 | |||
611 | DEVICE_LUMINANCE_ATTR(status0, llv); | ||
612 | DEVICE_LUMINANCE_ATTR(status1, hlv); | ||
613 | DEVICE_LUMINANCE_ATTR(buttons, img_lum); | ||
614 | |||
615 | static ssize_t wacom_button_image_store(struct device *dev, int button_id, | ||
616 | const char *buf, size_t count) | ||
617 | { | ||
618 | struct wacom *wacom = dev_get_drvdata(dev); | ||
619 | int err; | ||
620 | |||
621 | if (count != 1024) | ||
622 | return -EINVAL; | ||
623 | |||
624 | mutex_lock(&wacom->lock); | ||
625 | |||
626 | err = wacom_led_putimage(wacom, button_id, buf); | ||
627 | |||
628 | mutex_unlock(&wacom->lock); | ||
629 | |||
630 | return err < 0 ? err : count; | ||
631 | } | ||
632 | |||
633 | #define DEVICE_BTNIMG_ATTR(BUTTON_ID) \ | ||
634 | static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev, \ | ||
635 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
636 | { \ | ||
637 | return wacom_button_image_store(dev, BUTTON_ID, buf, count); \ | ||
638 | } \ | ||
639 | static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR, \ | ||
640 | NULL, wacom_btnimg##BUTTON_ID##_store) | ||
641 | |||
642 | DEVICE_BTNIMG_ATTR(0); | ||
643 | DEVICE_BTNIMG_ATTR(1); | ||
644 | DEVICE_BTNIMG_ATTR(2); | ||
645 | DEVICE_BTNIMG_ATTR(3); | ||
646 | DEVICE_BTNIMG_ATTR(4); | ||
647 | DEVICE_BTNIMG_ATTR(5); | ||
648 | DEVICE_BTNIMG_ATTR(6); | ||
649 | DEVICE_BTNIMG_ATTR(7); | ||
650 | |||
651 | static struct attribute *wacom_led_attrs[] = { | ||
652 | &dev_attr_status0_luminance.attr, | ||
653 | &dev_attr_status1_luminance.attr, | ||
654 | &dev_attr_status_led_select.attr, | ||
655 | &dev_attr_buttons_luminance.attr, | ||
656 | &dev_attr_button0_rawimg.attr, | ||
657 | &dev_attr_button1_rawimg.attr, | ||
658 | &dev_attr_button2_rawimg.attr, | ||
659 | &dev_attr_button3_rawimg.attr, | ||
660 | &dev_attr_button4_rawimg.attr, | ||
661 | &dev_attr_button5_rawimg.attr, | ||
662 | &dev_attr_button6_rawimg.attr, | ||
663 | &dev_attr_button7_rawimg.attr, | ||
664 | NULL | ||
665 | }; | ||
666 | |||
667 | static struct attribute_group wacom_led_attr_group = { | ||
668 | .name = "wacom_led", | ||
669 | .attrs = wacom_led_attrs, | ||
670 | }; | ||
671 | |||
672 | static int wacom_initialize_leds(struct wacom *wacom) | ||
673 | { | ||
674 | int error; | ||
675 | |||
676 | if (wacom->wacom_wac.features.type >= INTUOS4 && | ||
677 | wacom->wacom_wac.features.type <= INTUOS4L) { | ||
678 | |||
679 | /* Initialize default values */ | ||
680 | wacom->led.select = 0; | ||
681 | wacom->led.llv = 30; | ||
682 | wacom->led.hlv = 20; | ||
683 | wacom->led.img_lum = 10; | ||
684 | wacom_led_control(wacom); | ||
685 | |||
686 | error = sysfs_create_group(&wacom->intf->dev.kobj, | ||
687 | &wacom_led_attr_group); | ||
688 | if (error) { | ||
689 | dev_err(&wacom->intf->dev, | ||
690 | "cannot create sysfs group err: %d\n", error); | ||
691 | return error; | ||
692 | } | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static void wacom_destroy_leds(struct wacom *wacom) | ||
699 | { | ||
700 | if (wacom->wacom_wac.features.type >= INTUOS4 && | ||
701 | wacom->wacom_wac.features.type <= INTUOS4L) { | ||
702 | sysfs_remove_group(&wacom->intf->dev.kobj, | ||
703 | &wacom_led_attr_group); | ||
704 | } | ||
705 | } | ||
706 | |||
471 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 707 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
472 | { | 708 | { |
473 | struct usb_device *dev = interface_to_usbdev(intf); | 709 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -556,16 +792,21 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
556 | wacom->irq->transfer_dma = wacom->data_dma; | 792 | wacom->irq->transfer_dma = wacom->data_dma; |
557 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 793 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
558 | 794 | ||
559 | error = input_register_device(input_dev); | 795 | error = wacom_initialize_leds(wacom); |
560 | if (error) | 796 | if (error) |
561 | goto fail4; | 797 | goto fail4; |
562 | 798 | ||
799 | error = input_register_device(input_dev); | ||
800 | if (error) | ||
801 | goto fail5; | ||
802 | |||
563 | /* Note that if query fails it is not a hard failure */ | 803 | /* Note that if query fails it is not a hard failure */ |
564 | wacom_query_tablet_data(intf, features); | 804 | wacom_query_tablet_data(intf, features); |
565 | 805 | ||
566 | usb_set_intfdata(intf, wacom); | 806 | usb_set_intfdata(intf, wacom); |
567 | return 0; | 807 | return 0; |
568 | 808 | ||
809 | fail5: wacom_destroy_leds(wacom); | ||
569 | fail4: wacom_remove_shared_data(wacom_wac); | 810 | fail4: wacom_remove_shared_data(wacom_wac); |
570 | fail3: usb_free_urb(wacom->irq); | 811 | fail3: usb_free_urb(wacom->irq); |
571 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); | 812 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); |
@@ -582,6 +823,7 @@ static void wacom_disconnect(struct usb_interface *intf) | |||
582 | 823 | ||
583 | usb_kill_urb(wacom->irq); | 824 | usb_kill_urb(wacom->irq); |
584 | input_unregister_device(wacom->wacom_wac.input); | 825 | input_unregister_device(wacom->wacom_wac.input); |
826 | wacom_destroy_leds(wacom); | ||
585 | usb_free_urb(wacom->irq); | 827 | usb_free_urb(wacom->irq); |
586 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, | 828 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, |
587 | wacom->wacom_wac.data, wacom->data_dma); | 829 | wacom->wacom_wac.data, wacom->data_dma); |
@@ -604,17 +846,16 @@ static int wacom_resume(struct usb_interface *intf) | |||
604 | { | 846 | { |
605 | struct wacom *wacom = usb_get_intfdata(intf); | 847 | struct wacom *wacom = usb_get_intfdata(intf); |
606 | struct wacom_features *features = &wacom->wacom_wac.features; | 848 | struct wacom_features *features = &wacom->wacom_wac.features; |
607 | int rv; | 849 | int rv = 0; |
608 | 850 | ||
609 | mutex_lock(&wacom->lock); | 851 | mutex_lock(&wacom->lock); |
610 | 852 | ||
611 | /* switch to wacom mode first */ | 853 | /* switch to wacom mode first */ |
612 | wacom_query_tablet_data(intf, features); | 854 | wacom_query_tablet_data(intf, features); |
855 | wacom_led_control(wacom); | ||
613 | 856 | ||
614 | if (wacom->open) | 857 | if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) |
615 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); | 858 | rv = -EIO; |
616 | else | ||
617 | rv = 0; | ||
618 | 859 | ||
619 | mutex_unlock(&wacom->lock); | 860 | mutex_unlock(&wacom->lock); |
620 | 861 | ||