aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorPrzemo Firszt <przemo@firszt.eu>2012-07-31 13:27:56 -0400
committerJiri Kosina <jkosina@suse.cz>2012-08-15 04:29:11 -0400
commite3c399ee4afebda7fd0a96a748e665a26853c246 (patch)
treec0b5350e8c42b0999cd1b2a96015a3e17959a78a /drivers/hid
parent530a76c14f40012354074a02254b41cb171e122f (diff)
HID: wacom: OLEDs control over sysfs for Intuos4
Thsi patch adds ability to control OLED micro displays on Wacom Intuos4 Wireless. The OLEDS are exposed as /sys/class/hidraw/hidraw*/device/oled{No]_img where No. is 0 to 7 Setting an image: dd bs=256 if=img_file of=/sys/class/hidraw/hidraw{No}/device/oled0_img The image has to contain 256 bytes (64x32px 1 bit). More detailed description in Documentation/ABI/testing/sysfs-driver-wacom Signed-off-by: Przemo Firszt <przemo@firszt.eu> Acked-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wacom.c143
1 files changed, 143 insertions, 0 deletions
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
37struct wacom_data { 39struct 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
74static 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
118static 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
155err:
156 return;
157}
158
72static void wacom_leds_set_brightness(struct led_classdev *led_dev, 159static 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,
318static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, 407static 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) \
411static 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 \
426static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL, \
427 wacom_oled##OLED_ID##_store)
428
429WACOM_STORE(0);
430WACOM_STORE(1);
431WACOM_STORE(2);
432WACOM_STORE(3);
433WACOM_STORE(4);
434WACOM_STORE(5);
435WACOM_STORE(6);
436WACOM_STORE(7);
437
321static int wacom_gr_parse_report(struct hid_device *hdev, 438static 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
847OLED_INIT(0);
848OLED_INIT(1);
849OLED_INIT(2);
850OLED_INIT(3);
851OLED_INIT(4);
852OLED_INIT(5);
853OLED_INIT(6);
854OLED_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