diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-driver-wacom | 13 | ||||
-rw-r--r-- | drivers/hid/hid-wacom.c | 143 |
2 files changed, 156 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom index 8d55a83d6921..7fc781048b79 100644 --- a/Documentation/ABI/testing/sysfs-driver-wacom +++ b/Documentation/ABI/testing/sysfs-driver-wacom | |||
@@ -1,3 +1,16 @@ | |||
1 | WWhat: /sys/class/hidraw/hidraw*/device/oled*_img | ||
2 | Date: June 2012 | ||
3 | Contact: linux-bluetooth@vger.kernel.org | ||
4 | Description: | ||
5 | The /sys/class/hidraw/hidraw*/device/oled*_img files control | ||
6 | OLED mocro displays on Intuos4 Wireless tablet. Accepted image | ||
7 | has to contain 256 bytes (64x32 px 1 bit colour). The format | ||
8 | is the same as PBM image 62x32px without header (64 bits per | ||
9 | horizontal line, 32 lines). An example of setting OLED No. 0: | ||
10 | dd bs=256 count=1 if=img_file of=[path to oled0_img]/oled0_img | ||
11 | The attribute is read only and no local copy of the image is | ||
12 | stored. | ||
13 | |||
1 | What: /sys/class/hidraw/hidraw*/device/speed | 14 | What: /sys/class/hidraw/hidraw*/device/speed |
2 | Date: April 2010 | 15 | Date: April 2010 |
3 | Kernel Version: 2.6.35 | 16 | Kernel Version: 2.6.35 |
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 848842e0df14..0f02358888a9 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #define PAD_DEVICE_ID 0x0F | 33 | #define PAD_DEVICE_ID 0x0F |
34 | 34 | ||
35 | #define WAC_CMD_LED_CONTROL 0x20 | 35 | #define WAC_CMD_LED_CONTROL 0x20 |
36 | #define WAC_CMD_ICON_START_STOP 0x21 | ||
37 | #define WAC_CMD_ICON_TRANSFER 0x26 | ||
36 | 38 | ||
37 | struct wacom_data { | 39 | struct wacom_data { |
38 | __u16 tool; | 40 | __u16 tool; |
@@ -69,6 +71,91 @@ static enum power_supply_property wacom_ac_props[] = { | |||
69 | POWER_SUPPLY_PROP_SCOPE, | 71 | POWER_SUPPLY_PROP_SCOPE, |
70 | }; | 72 | }; |
71 | 73 | ||
74 | static void wacom_scramble(__u8 *image) | ||
75 | { | ||
76 | __u16 mask; | ||
77 | __u16 s1; | ||
78 | __u16 s2; | ||
79 | __u16 r1 ; | ||
80 | __u16 r2 ; | ||
81 | __u16 r; | ||
82 | __u8 buf[256]; | ||
83 | int i, w, x, y, z; | ||
84 | |||
85 | for (x = 0; x < 32; x++) { | ||
86 | for (y = 0; y < 8; y++) | ||
87 | buf[(8 * x) + (7 - y)] = image[(8 * x) + y]; | ||
88 | } | ||
89 | |||
90 | /* Change 76543210 into GECA6420 as required by Intuos4 WL | ||
91 | * HGFEDCBA HFDB7531 | ||
92 | */ | ||
93 | for (x = 0; x < 4; x++) { | ||
94 | for (y = 0; y < 4; y++) { | ||
95 | for (z = 0; z < 8; z++) { | ||
96 | mask = 0x0001; | ||
97 | r1 = 0; | ||
98 | r2 = 0; | ||
99 | i = (x << 6) + (y << 4) + z; | ||
100 | s1 = buf[i]; | ||
101 | s2 = buf[i+8]; | ||
102 | for (w = 0; w < 8; w++) { | ||
103 | r1 |= (s1 & mask); | ||
104 | r2 |= (s2 & mask); | ||
105 | s1 <<= 1; | ||
106 | s2 <<= 1; | ||
107 | mask <<= 2; | ||
108 | } | ||
109 | r = r1 | (r2 << 1); | ||
110 | i = (x << 6) + (y << 4) + (z << 1); | ||
111 | image[i] = 0xFF & r; | ||
112 | image[i+1] = (0xFF00 & r) >> 8; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static void wacom_set_image(struct hid_device *hdev, const char *image, | ||
119 | __u8 icon_no) | ||
120 | { | ||
121 | __u8 rep_data[68]; | ||
122 | __u8 p[256]; | ||
123 | int ret, i, j; | ||
124 | |||
125 | for (i = 0; i < 256; i++) | ||
126 | p[i] = image[i]; | ||
127 | |||
128 | rep_data[0] = WAC_CMD_ICON_START_STOP; | ||
129 | rep_data[1] = 0; | ||
130 | ret = hdev->hid_output_raw_report(hdev, rep_data, 2, | ||
131 | HID_FEATURE_REPORT); | ||
132 | if (ret < 0) | ||
133 | goto err; | ||
134 | |||
135 | rep_data[0] = WAC_CMD_ICON_TRANSFER; | ||
136 | rep_data[1] = icon_no & 0x07; | ||
137 | |||
138 | wacom_scramble(p); | ||
139 | |||
140 | for (i = 0; i < 4; i++) { | ||
141 | for (j = 0; j < 64; j++) | ||
142 | rep_data[j + 3] = p[(i << 6) + j]; | ||
143 | |||
144 | rep_data[2] = i; | ||
145 | ret = hdev->hid_output_raw_report(hdev, rep_data, 67, | ||
146 | HID_FEATURE_REPORT); | ||
147 | } | ||
148 | |||
149 | rep_data[0] = WAC_CMD_ICON_START_STOP; | ||
150 | rep_data[1] = 0; | ||
151 | |||
152 | ret = hdev->hid_output_raw_report(hdev, rep_data, 2, | ||
153 | HID_FEATURE_REPORT); | ||
154 | |||
155 | err: | ||
156 | return; | ||
157 | } | ||
158 | |||
72 | static void wacom_leds_set_brightness(struct led_classdev *led_dev, | 159 | static void wacom_leds_set_brightness(struct led_classdev *led_dev, |
73 | enum led_brightness value) | 160 | enum led_brightness value) |
74 | { | 161 | { |
@@ -93,6 +180,8 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev, | |||
93 | buf[1] = led; | 180 | buf[1] = led; |
94 | buf[2] = value >> 2; | 181 | buf[2] = value >> 2; |
95 | buf[3] = value; | 182 | buf[3] = value; |
183 | /* use fixed brightness for OLEDs */ | ||
184 | buf[4] = 0x08; | ||
96 | hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT); | 185 | hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT); |
97 | kfree(buf); | 186 | kfree(buf); |
98 | } | 187 | } |
@@ -318,6 +407,34 @@ static ssize_t wacom_store_speed(struct device *dev, | |||
318 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, | 407 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, |
319 | wacom_show_speed, wacom_store_speed); | 408 | wacom_show_speed, wacom_store_speed); |
320 | 409 | ||
410 | #define WACOM_STORE(OLED_ID) \ | ||
411 | static ssize_t wacom_oled##OLED_ID##_store(struct device *dev, \ | ||
412 | struct device_attribute *attr, \ | ||
413 | const char *buf, size_t count) \ | ||
414 | { \ | ||
415 | struct hid_device *hdev = container_of(dev, struct hid_device, \ | ||
416 | dev); \ | ||
417 | \ | ||
418 | if (count != 256) \ | ||
419 | return -EINVAL; \ | ||
420 | \ | ||
421 | wacom_set_image(hdev, buf, OLED_ID); \ | ||
422 | \ | ||
423 | return count; \ | ||
424 | } \ | ||
425 | \ | ||
426 | static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL, \ | ||
427 | wacom_oled##OLED_ID##_store) | ||
428 | |||
429 | WACOM_STORE(0); | ||
430 | WACOM_STORE(1); | ||
431 | WACOM_STORE(2); | ||
432 | WACOM_STORE(3); | ||
433 | WACOM_STORE(4); | ||
434 | WACOM_STORE(5); | ||
435 | WACOM_STORE(6); | ||
436 | WACOM_STORE(7); | ||
437 | |||
321 | static int wacom_gr_parse_report(struct hid_device *hdev, | 438 | static int wacom_gr_parse_report(struct hid_device *hdev, |
322 | struct wacom_data *wdata, | 439 | struct wacom_data *wdata, |
323 | struct input_dev *input, unsigned char *data) | 440 | struct input_dev *input, unsigned char *data) |
@@ -718,6 +835,24 @@ static int wacom_probe(struct hid_device *hdev, | |||
718 | hid_warn(hdev, | 835 | hid_warn(hdev, |
719 | "can't create sysfs speed attribute err: %d\n", ret); | 836 | "can't create sysfs speed attribute err: %d\n", ret); |
720 | 837 | ||
838 | #define OLED_INIT(OLED_ID) \ | ||
839 | do { \ | ||
840 | ret = device_create_file(&hdev->dev, \ | ||
841 | &dev_attr_oled##OLED_ID##_img); \ | ||
842 | if (ret) \ | ||
843 | hid_warn(hdev, \ | ||
844 | "can't create sysfs oled attribute, err: %d\n", ret);\ | ||
845 | } while (0) | ||
846 | |||
847 | OLED_INIT(0); | ||
848 | OLED_INIT(1); | ||
849 | OLED_INIT(2); | ||
850 | OLED_INIT(3); | ||
851 | OLED_INIT(4); | ||
852 | OLED_INIT(5); | ||
853 | OLED_INIT(6); | ||
854 | OLED_INIT(7); | ||
855 | |||
721 | wdata->features = 0; | 856 | wdata->features = 0; |
722 | wacom_set_features(hdev, 1); | 857 | wacom_set_features(hdev, 1); |
723 | 858 | ||
@@ -782,6 +917,14 @@ static void wacom_remove(struct hid_device *hdev) | |||
782 | struct wacom_data *wdata = hid_get_drvdata(hdev); | 917 | struct wacom_data *wdata = hid_get_drvdata(hdev); |
783 | 918 | ||
784 | wacom_destroy_leds(hdev); | 919 | wacom_destroy_leds(hdev); |
920 | device_remove_file(&hdev->dev, &dev_attr_oled0_img); | ||
921 | device_remove_file(&hdev->dev, &dev_attr_oled1_img); | ||
922 | device_remove_file(&hdev->dev, &dev_attr_oled2_img); | ||
923 | device_remove_file(&hdev->dev, &dev_attr_oled3_img); | ||
924 | device_remove_file(&hdev->dev, &dev_attr_oled4_img); | ||
925 | device_remove_file(&hdev->dev, &dev_attr_oled5_img); | ||
926 | device_remove_file(&hdev->dev, &dev_attr_oled6_img); | ||
927 | device_remove_file(&hdev->dev, &dev_attr_oled7_img); | ||
785 | device_remove_file(&hdev->dev, &dev_attr_speed); | 928 | device_remove_file(&hdev->dev, &dev_attr_speed); |
786 | hid_hw_stop(hdev); | 929 | hid_hw_stop(hdev); |
787 | 930 | ||