aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-wacom64
-rw-r--r--Documentation/ABI/testing/sysfs-wacom10
-rw-r--r--drivers/input/tablet/wacom.h6
-rw-r--r--drivers/input/tablet/wacom_sys.c301
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 @@
1What: /sys/class/hidraw/hidraw*/device/speed
2Date: April 2010
3Kernel Version: 2.6.35
4Contact: linux-bluetooth@vger.kernel.org
5Description:
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
12What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
13Date: August 2011
14Contact: linux-input@vger.kernel.org
15Description:
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
22What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
23Date: August 2011
24Contact: linux-input@vger.kernel.org
25Description:
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
30What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
31Date: August 2011
32Contact: linux-input@vger.kernel.org
33Description:
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
38What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led_select
39Date: August 2011
40Contact: linux-input@vger.kernel.org
41Description:
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
47What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
48Date: August 2011
49Contact: linux-input@vger.kernel.org
50Description:
51 Writing to this file sets the overall luminance level (0..15)
52 of all eight button OLED displays.
53
54What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
55Date: August 2011
56Contact: linux-input@vger.kernel.org
57Description:
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 @@
1What: /sys/class/hidraw/hidraw*/device/speed
2Date: April 2010
3Kernel Version: 2.6.35
4Contact: linux-bluetooth@vger.kernel.org
5Description:
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
119extern const struct usb_device_id wacom_ids[]; 125extern 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
54static 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
60static 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
64static int usb_set_report(struct usb_interface *intf, unsigned char type, 78static 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
74static void wacom_sys_irq(struct urb *urb) 96static 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
493static 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
515static 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
550out:
551 kfree(buf);
552 return retval;
553}
554
555static 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
577static DEVICE_ATTR(status_led_select, S_IWUSR, NULL, wacom_led_select_store);
578
579static 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) \
600static 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} \
608static DEVICE_ATTR(name##_luminance, S_IWUSR, \
609 NULL, wacom_##name##_luminance_store)
610
611DEVICE_LUMINANCE_ATTR(status0, llv);
612DEVICE_LUMINANCE_ATTR(status1, hlv);
613DEVICE_LUMINANCE_ATTR(buttons, img_lum);
614
615static 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) \
634static 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} \
639static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR, \
640 NULL, wacom_btnimg##BUTTON_ID##_store)
641
642DEVICE_BTNIMG_ATTR(0);
643DEVICE_BTNIMG_ATTR(1);
644DEVICE_BTNIMG_ATTR(2);
645DEVICE_BTNIMG_ATTR(3);
646DEVICE_BTNIMG_ATTR(4);
647DEVICE_BTNIMG_ATTR(5);
648DEVICE_BTNIMG_ATTR(6);
649DEVICE_BTNIMG_ATTR(7);
650
651static 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
667static struct attribute_group wacom_led_attr_group = {
668 .name = "wacom_led",
669 .attrs = wacom_led_attrs,
670};
671
672static 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
698static 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
471static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) 707static 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