]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/hid/hid-lenovo-tpkbd.c
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
[karo-tx-linux.git] / drivers / hid / hid-lenovo-tpkbd.c
1 /*
2  *  HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
3  *
4  *  Copyright (c) 2012 Bernhard Seibold
5  */
6
7 /*
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  */
13
14 #include <linux/module.h>
15 #include <linux/sysfs.h>
16 #include <linux/device.h>
17 #include <linux/usb.h>
18 #include <linux/hid.h>
19 #include <linux/input.h>
20 #include <linux/leds.h>
21 #include "usbhid/usbhid.h"
22
23 #include "hid-ids.h"
24
25 /* This is only used for the trackpoint part of the driver, hence _tp */
26 struct tpkbd_data_pointer {
27         int led_state;
28         struct led_classdev led_mute;
29         struct led_classdev led_micmute;
30         int press_to_select;
31         int dragging;
32         int release_to_select;
33         int select_right;
34         int sensitivity;
35         int press_speed;
36 };
37
38 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
39
40 static int tpkbd_input_mapping(struct hid_device *hdev,
41                 struct hid_input *hi, struct hid_field *field,
42                 struct hid_usage *usage, unsigned long **bit, int *max)
43 {
44         struct usbhid_device *uhdev;
45
46         uhdev = (struct usbhid_device *) hdev->driver_data;
47         if (uhdev->ifnum == 1 && usage->hid == (HID_UP_BUTTON | 0x0010)) {
48                 map_key_clear(KEY_MICMUTE);
49                 return 1;
50         }
51         return 0;
52 }
53
54 #undef map_key_clear
55
56 static int tpkbd_features_set(struct hid_device *hdev)
57 {
58         struct hid_report *report;
59         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
60
61         report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
62
63         report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
64         report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
65         report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
66         report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
67         report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
68         report->field[2]->value[0] = data_pointer->sensitivity;
69         report->field[3]->value[0] = data_pointer->press_speed;
70
71         hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
72         return 0;
73 }
74
75 static ssize_t pointer_press_to_select_show(struct device *dev,
76                 struct device_attribute *attr,
77                 char *buf)
78 {
79         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
80         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
81
82         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
83 }
84
85 static ssize_t pointer_press_to_select_store(struct device *dev,
86                 struct device_attribute *attr,
87                 const char *buf,
88                 size_t count)
89 {
90         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
91         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
92         int value;
93
94         if (kstrtoint(buf, 10, &value))
95                 return -EINVAL;
96         if (value < 0 || value > 1)
97                 return -EINVAL;
98
99         data_pointer->press_to_select = value;
100         tpkbd_features_set(hdev);
101
102         return count;
103 }
104
105 static ssize_t pointer_dragging_show(struct device *dev,
106                 struct device_attribute *attr,
107                 char *buf)
108 {
109         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
110         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
111
112         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
113 }
114
115 static ssize_t pointer_dragging_store(struct device *dev,
116                 struct device_attribute *attr,
117                 const char *buf,
118                 size_t count)
119 {
120         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
121         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
122         int value;
123
124         if (kstrtoint(buf, 10, &value))
125                 return -EINVAL;
126         if (value < 0 || value > 1)
127                 return -EINVAL;
128
129         data_pointer->dragging = value;
130         tpkbd_features_set(hdev);
131
132         return count;
133 }
134
135 static ssize_t pointer_release_to_select_show(struct device *dev,
136                 struct device_attribute *attr,
137                 char *buf)
138 {
139         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
140         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
141
142         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
143 }
144
145 static ssize_t pointer_release_to_select_store(struct device *dev,
146                 struct device_attribute *attr,
147                 const char *buf,
148                 size_t count)
149 {
150         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
151         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
152         int value;
153
154         if (kstrtoint(buf, 10, &value))
155                 return -EINVAL;
156         if (value < 0 || value > 1)
157                 return -EINVAL;
158
159         data_pointer->release_to_select = value;
160         tpkbd_features_set(hdev);
161
162         return count;
163 }
164
165 static ssize_t pointer_select_right_show(struct device *dev,
166                 struct device_attribute *attr,
167                 char *buf)
168 {
169         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
170         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
171
172         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
173 }
174
175 static ssize_t pointer_select_right_store(struct device *dev,
176                 struct device_attribute *attr,
177                 const char *buf,
178                 size_t count)
179 {
180         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
181         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
182         int value;
183
184         if (kstrtoint(buf, 10, &value))
185                 return -EINVAL;
186         if (value < 0 || value > 1)
187                 return -EINVAL;
188
189         data_pointer->select_right = value;
190         tpkbd_features_set(hdev);
191
192         return count;
193 }
194
195 static ssize_t pointer_sensitivity_show(struct device *dev,
196                 struct device_attribute *attr,
197                 char *buf)
198 {
199         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
200         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
201
202         return snprintf(buf, PAGE_SIZE, "%u\n",
203                 data_pointer->sensitivity);
204 }
205
206 static ssize_t pointer_sensitivity_store(struct device *dev,
207                 struct device_attribute *attr,
208                 const char *buf,
209                 size_t count)
210 {
211         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
212         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
213         int value;
214
215         if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
216                 return -EINVAL;
217
218         data_pointer->sensitivity = value;
219         tpkbd_features_set(hdev);
220
221         return count;
222 }
223
224 static ssize_t pointer_press_speed_show(struct device *dev,
225                 struct device_attribute *attr,
226                 char *buf)
227 {
228         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
229         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
230
231         return snprintf(buf, PAGE_SIZE, "%u\n",
232                 data_pointer->press_speed);
233 }
234
235 static ssize_t pointer_press_speed_store(struct device *dev,
236                 struct device_attribute *attr,
237                 const char *buf,
238                 size_t count)
239 {
240         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
241         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
242         int value;
243
244         if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
245                 return -EINVAL;
246
247         data_pointer->press_speed = value;
248         tpkbd_features_set(hdev);
249
250         return count;
251 }
252
253 static struct device_attribute dev_attr_pointer_press_to_select =
254         __ATTR(press_to_select, S_IWUSR | S_IRUGO,
255                         pointer_press_to_select_show,
256                         pointer_press_to_select_store);
257
258 static struct device_attribute dev_attr_pointer_dragging =
259         __ATTR(dragging, S_IWUSR | S_IRUGO,
260                         pointer_dragging_show,
261                         pointer_dragging_store);
262
263 static struct device_attribute dev_attr_pointer_release_to_select =
264         __ATTR(release_to_select, S_IWUSR | S_IRUGO,
265                         pointer_release_to_select_show,
266                         pointer_release_to_select_store);
267
268 static struct device_attribute dev_attr_pointer_select_right =
269         __ATTR(select_right, S_IWUSR | S_IRUGO,
270                         pointer_select_right_show,
271                         pointer_select_right_store);
272
273 static struct device_attribute dev_attr_pointer_sensitivity =
274         __ATTR(sensitivity, S_IWUSR | S_IRUGO,
275                         pointer_sensitivity_show,
276                         pointer_sensitivity_store);
277
278 static struct device_attribute dev_attr_pointer_press_speed =
279         __ATTR(press_speed, S_IWUSR | S_IRUGO,
280                         pointer_press_speed_show,
281                         pointer_press_speed_store);
282
283 static struct attribute *tpkbd_attributes_pointer[] = {
284         &dev_attr_pointer_press_to_select.attr,
285         &dev_attr_pointer_dragging.attr,
286         &dev_attr_pointer_release_to_select.attr,
287         &dev_attr_pointer_select_right.attr,
288         &dev_attr_pointer_sensitivity.attr,
289         &dev_attr_pointer_press_speed.attr,
290         NULL
291 };
292
293 static const struct attribute_group tpkbd_attr_group_pointer = {
294         .attrs = tpkbd_attributes_pointer,
295 };
296
297 static enum led_brightness tpkbd_led_brightness_get(
298                         struct led_classdev *led_cdev)
299 {
300         struct device *dev = led_cdev->dev->parent;
301         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
302         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
303         int led_nr = 0;
304
305         if (led_cdev == &data_pointer->led_micmute)
306                 led_nr = 1;
307
308         return data_pointer->led_state & (1 << led_nr)
309                                 ? LED_FULL
310                                 : LED_OFF;
311 }
312
313 static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
314                         enum led_brightness value)
315 {
316         struct device *dev = led_cdev->dev->parent;
317         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
318         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
319         struct hid_report *report;
320         int led_nr = 0;
321
322         if (led_cdev == &data_pointer->led_micmute)
323                 led_nr = 1;
324
325         if (value == LED_OFF)
326                 data_pointer->led_state &= ~(1 << led_nr);
327         else
328                 data_pointer->led_state |= 1 << led_nr;
329
330         report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
331         report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
332         report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
333         hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
334 }
335
336 static int tpkbd_probe_tp(struct hid_device *hdev)
337 {
338         struct device *dev = &hdev->dev;
339         struct tpkbd_data_pointer *data_pointer;
340         size_t name_sz = strlen(dev_name(dev)) + 16;
341         char *name_mute, *name_micmute;
342         int i, ret;
343
344         /* Validate required reports. */
345         for (i = 0; i < 4; i++) {
346                 if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
347                         return -ENODEV;
348         }
349         if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
350                 return -ENODEV;
351
352         if (sysfs_create_group(&hdev->dev.kobj,
353                                 &tpkbd_attr_group_pointer)) {
354                 hid_warn(hdev, "Could not create sysfs group\n");
355         }
356
357         data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL);
358         if (data_pointer == NULL) {
359                 hid_err(hdev, "Could not allocate memory for driver data\n");
360                 return -ENOMEM;
361         }
362
363         // set same default values as windows driver
364         data_pointer->sensitivity = 0xa0;
365         data_pointer->press_speed = 0x38;
366
367         name_mute = kzalloc(name_sz, GFP_KERNEL);
368         if (name_mute == NULL) {
369                 hid_err(hdev, "Could not allocate memory for led data\n");
370                 ret = -ENOMEM;
371                 goto err;
372         }
373         snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
374
375         name_micmute = kzalloc(name_sz, GFP_KERNEL);
376         if (name_micmute == NULL) {
377                 hid_err(hdev, "Could not allocate memory for led data\n");
378                 ret = -ENOMEM;
379                 goto err2;
380         }
381         snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
382
383         hid_set_drvdata(hdev, data_pointer);
384
385         data_pointer->led_mute.name = name_mute;
386         data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
387         data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
388         data_pointer->led_mute.dev = dev;
389         led_classdev_register(dev, &data_pointer->led_mute);
390
391         data_pointer->led_micmute.name = name_micmute;
392         data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
393         data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
394         data_pointer->led_micmute.dev = dev;
395         led_classdev_register(dev, &data_pointer->led_micmute);
396
397         tpkbd_features_set(hdev);
398
399         return 0;
400
401 err2:
402         kfree(name_mute);
403 err:
404         kfree(data_pointer);
405         return ret;
406 }
407
408 static int tpkbd_probe(struct hid_device *hdev,
409                 const struct hid_device_id *id)
410 {
411         int ret;
412         struct usbhid_device *uhdev;
413
414         ret = hid_parse(hdev);
415         if (ret) {
416                 hid_err(hdev, "hid_parse failed\n");
417                 goto err;
418         }
419
420         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
421         if (ret) {
422                 hid_err(hdev, "hid_hw_start failed\n");
423                 goto err;
424         }
425
426         uhdev = (struct usbhid_device *) hdev->driver_data;
427
428         if (uhdev->ifnum == 1) {
429                 ret = tpkbd_probe_tp(hdev);
430                 if (ret)
431                         goto err_hid;
432         }
433
434         return 0;
435 err_hid:
436         hid_hw_stop(hdev);
437 err:
438         return ret;
439 }
440
441 static void tpkbd_remove_tp(struct hid_device *hdev)
442 {
443         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
444
445         sysfs_remove_group(&hdev->dev.kobj,
446                         &tpkbd_attr_group_pointer);
447
448         led_classdev_unregister(&data_pointer->led_micmute);
449         led_classdev_unregister(&data_pointer->led_mute);
450
451         hid_set_drvdata(hdev, NULL);
452         kfree(data_pointer->led_micmute.name);
453         kfree(data_pointer->led_mute.name);
454         kfree(data_pointer);
455 }
456
457 static void tpkbd_remove(struct hid_device *hdev)
458 {
459         struct usbhid_device *uhdev;
460
461         uhdev = (struct usbhid_device *) hdev->driver_data;
462         if (uhdev->ifnum == 1)
463                 tpkbd_remove_tp(hdev);
464
465         hid_hw_stop(hdev);
466 }
467
468 static const struct hid_device_id tpkbd_devices[] = {
469         { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
470         { }
471 };
472
473 MODULE_DEVICE_TABLE(hid, tpkbd_devices);
474
475 static struct hid_driver tpkbd_driver = {
476         .name = "lenovo_tpkbd",
477         .id_table = tpkbd_devices,
478         .input_mapping = tpkbd_input_mapping,
479         .probe = tpkbd_probe,
480         .remove = tpkbd_remove,
481 };
482 module_hid_driver(tpkbd_driver);
483
484 MODULE_LICENSE("GPL");