]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/hid/hid-lenovo-tpkbd.c
77d2df04c97b0dbe6c34eb11b9e566ae07d5ae28
[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;
60
61         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
62         report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
63
64         report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
65         report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
66         report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
67         report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
68         report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
69         report->field[2]->value[0] = data_pointer->sensitivity;
70         report->field[3]->value[0] = data_pointer->press_speed;
71
72         usbhid_submit_report(hdev, report, USB_DIR_OUT);
73         return 0;
74 }
75
76 static ssize_t pointer_press_to_select_show(struct device *dev,
77                 struct device_attribute *attr,
78                 char *buf)
79 {
80         struct hid_device *hdev;
81         struct tpkbd_data_pointer *data_pointer;
82
83         hdev = container_of(dev, struct hid_device, dev);
84         if (hdev == NULL)
85                 return -ENODEV;
86
87         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
88
89         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
90 }
91
92 static ssize_t pointer_press_to_select_store(struct device *dev,
93                 struct device_attribute *attr,
94                 const char *buf,
95                 size_t count)
96 {
97         struct hid_device *hdev;
98         struct tpkbd_data_pointer *data_pointer;
99         int value;
100
101         hdev = container_of(dev, struct hid_device, dev);
102         if (hdev == NULL)
103                 return -ENODEV;
104
105         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
106
107         if (kstrtoint(buf, 10, &value))
108                 return -EINVAL;
109         if (value < 0 || value > 1)
110                 return -EINVAL;
111
112         data_pointer->press_to_select = value;
113         tpkbd_features_set(hdev);
114
115         return count;
116 }
117
118 static ssize_t pointer_dragging_show(struct device *dev,
119                 struct device_attribute *attr,
120                 char *buf)
121 {
122         struct hid_device *hdev;
123         struct tpkbd_data_pointer *data_pointer;
124
125         hdev = container_of(dev, struct hid_device, dev);
126         if (hdev == NULL)
127                 return -ENODEV;
128
129         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
130
131         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
132 }
133
134 static ssize_t pointer_dragging_store(struct device *dev,
135                 struct device_attribute *attr,
136                 const char *buf,
137                 size_t count)
138 {
139         struct hid_device *hdev;
140         struct tpkbd_data_pointer *data_pointer;
141         int value;
142
143         hdev = container_of(dev, struct hid_device, dev);
144         if (hdev == NULL)
145                 return -ENODEV;
146
147         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
148
149         if (kstrtoint(buf, 10, &value))
150                 return -EINVAL;
151         if (value < 0 || value > 1)
152                 return -EINVAL;
153
154         data_pointer->dragging = value;
155         tpkbd_features_set(hdev);
156
157         return count;
158 }
159
160 static ssize_t pointer_release_to_select_show(struct device *dev,
161                 struct device_attribute *attr,
162                 char *buf)
163 {
164         struct hid_device *hdev;
165         struct tpkbd_data_pointer *data_pointer;
166
167         hdev = container_of(dev, struct hid_device, dev);
168         if (hdev == NULL)
169                 return -ENODEV;
170
171         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
172
173         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
174 }
175
176 static ssize_t pointer_release_to_select_store(struct device *dev,
177                 struct device_attribute *attr,
178                 const char *buf,
179                 size_t count)
180 {
181         struct hid_device *hdev;
182         struct tpkbd_data_pointer *data_pointer;
183         int value;
184
185         hdev = container_of(dev, struct hid_device, dev);
186         if (hdev == NULL)
187                 return -ENODEV;
188
189         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
190
191         if (kstrtoint(buf, 10, &value))
192                 return -EINVAL;
193         if (value < 0 || value > 1)
194                 return -EINVAL;
195
196         data_pointer->release_to_select = value;
197         tpkbd_features_set(hdev);
198
199         return count;
200 }
201
202 static ssize_t pointer_select_right_show(struct device *dev,
203                 struct device_attribute *attr,
204                 char *buf)
205 {
206         struct hid_device *hdev;
207         struct tpkbd_data_pointer *data_pointer;
208
209         hdev = container_of(dev, struct hid_device, dev);
210         if (hdev == NULL)
211                 return -ENODEV;
212
213         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
214
215         return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
216 }
217
218 static ssize_t pointer_select_right_store(struct device *dev,
219                 struct device_attribute *attr,
220                 const char *buf,
221                 size_t count)
222 {
223         struct hid_device *hdev;
224         struct tpkbd_data_pointer *data_pointer;
225         int value;
226
227         hdev = container_of(dev, struct hid_device, dev);
228         if (hdev == NULL)
229                 return -ENODEV;
230
231         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
232
233         if (kstrtoint(buf, 10, &value))
234                 return -EINVAL;
235         if (value < 0 || value > 1)
236                 return -EINVAL;
237
238         data_pointer->select_right = value;
239         tpkbd_features_set(hdev);
240
241         return count;
242 }
243
244 static ssize_t pointer_sensitivity_show(struct device *dev,
245                 struct device_attribute *attr,
246                 char *buf)
247 {
248         struct hid_device *hdev;
249         struct tpkbd_data_pointer *data_pointer;
250
251         hdev = container_of(dev, struct hid_device, dev);
252         if (hdev == NULL)
253                 return -ENODEV;
254
255         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
256
257         return snprintf(buf, PAGE_SIZE, "%u\n",
258                 data_pointer->sensitivity);
259 }
260
261 static ssize_t pointer_sensitivity_store(struct device *dev,
262                 struct device_attribute *attr,
263                 const char *buf,
264                 size_t count)
265 {
266         struct hid_device *hdev;
267         struct tpkbd_data_pointer *data_pointer;
268         int value;
269
270         hdev = container_of(dev, struct hid_device, dev);
271         if (hdev == NULL)
272                 return -ENODEV;
273
274         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
275
276         if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
277                 return -EINVAL;
278
279         data_pointer->sensitivity = value;
280         tpkbd_features_set(hdev);
281
282         return count;
283 }
284
285 static ssize_t pointer_press_speed_show(struct device *dev,
286                 struct device_attribute *attr,
287                 char *buf)
288 {
289         struct hid_device *hdev;
290         struct tpkbd_data_pointer *data_pointer;
291
292         hdev = container_of(dev, struct hid_device, dev);
293         if (hdev == NULL)
294                 return -ENODEV;
295
296         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
297
298         return snprintf(buf, PAGE_SIZE, "%u\n",
299                 data_pointer->press_speed);
300 }
301
302 static ssize_t pointer_press_speed_store(struct device *dev,
303                 struct device_attribute *attr,
304                 const char *buf,
305                 size_t count)
306 {
307         struct hid_device *hdev;
308         struct tpkbd_data_pointer *data_pointer;
309         int value;
310
311         hdev = container_of(dev, struct hid_device, dev);
312         if (hdev == NULL)
313                 return -ENODEV;
314
315         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
316
317         if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
318                 return -EINVAL;
319
320         data_pointer->press_speed = value;
321         tpkbd_features_set(hdev);
322
323         return count;
324 }
325
326 static struct device_attribute dev_attr_pointer_press_to_select =
327         __ATTR(press_to_select, S_IWUSR | S_IRUGO,
328                         pointer_press_to_select_show,
329                         pointer_press_to_select_store);
330
331 static struct device_attribute dev_attr_pointer_dragging =
332         __ATTR(dragging, S_IWUSR | S_IRUGO,
333                         pointer_dragging_show,
334                         pointer_dragging_store);
335
336 static struct device_attribute dev_attr_pointer_release_to_select =
337         __ATTR(release_to_select, S_IWUSR | S_IRUGO,
338                         pointer_release_to_select_show,
339                         pointer_release_to_select_store);
340
341 static struct device_attribute dev_attr_pointer_select_right =
342         __ATTR(select_right, S_IWUSR | S_IRUGO,
343                         pointer_select_right_show,
344                         pointer_select_right_store);
345
346 static struct device_attribute dev_attr_pointer_sensitivity =
347         __ATTR(sensitivity, S_IWUSR | S_IRUGO,
348                         pointer_sensitivity_show,
349                         pointer_sensitivity_store);
350
351 static struct device_attribute dev_attr_pointer_press_speed =
352         __ATTR(press_speed, S_IWUSR | S_IRUGO,
353                         pointer_press_speed_show,
354                         pointer_press_speed_store);
355
356 static struct attribute *tpkbd_attributes_pointer[] = {
357         &dev_attr_pointer_press_to_select.attr,
358         &dev_attr_pointer_dragging.attr,
359         &dev_attr_pointer_release_to_select.attr,
360         &dev_attr_pointer_select_right.attr,
361         &dev_attr_pointer_sensitivity.attr,
362         &dev_attr_pointer_press_speed.attr,
363         NULL
364 };
365
366 static const struct attribute_group tpkbd_attr_group_pointer = {
367         .attrs = tpkbd_attributes_pointer,
368 };
369
370 static enum led_brightness tpkbd_led_brightness_get(
371                         struct led_classdev *led_cdev)
372 {
373         struct device *dev;
374         struct hid_device *hdev;
375         struct tpkbd_data_pointer *data_pointer;
376         int led_nr = 0;
377
378         dev = led_cdev->dev->parent;
379         hdev = container_of(dev, struct hid_device, dev);
380         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
381
382         if (led_cdev == &data_pointer->led_micmute)
383                 led_nr = 1;
384
385         return data_pointer->led_state & (1 << led_nr)
386                                 ? LED_FULL
387                                 : LED_OFF;
388 }
389
390 static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
391                         enum led_brightness value)
392 {
393         struct device *dev;
394         struct hid_device *hdev;
395         struct hid_report *report;
396         struct tpkbd_data_pointer *data_pointer;
397         int led_nr = 0;
398
399         dev = led_cdev->dev->parent;
400         hdev = container_of(dev, struct hid_device, dev);
401         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
402
403         if (led_cdev == &data_pointer->led_micmute)
404                 led_nr = 1;
405
406         if (value == LED_OFF)
407                 data_pointer->led_state &= ~(1 << led_nr);
408         else
409                 data_pointer->led_state |= 1 << led_nr;
410
411         report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
412         report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
413         report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
414         usbhid_submit_report(hdev, report, USB_DIR_OUT);
415 }
416
417 static int tpkbd_probe_tp(struct hid_device *hdev)
418 {
419         struct device *dev = &hdev->dev;
420         struct tpkbd_data_pointer *data_pointer;
421         size_t name_sz = strlen(dev_name(dev)) + 16;
422         char *name_mute, *name_micmute;
423         int ret;
424
425         if (sysfs_create_group(&hdev->dev.kobj,
426                                 &tpkbd_attr_group_pointer)) {
427                 hid_warn(hdev, "Could not create sysfs group\n");
428         }
429
430         data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL);
431         if (data_pointer == NULL) {
432                 hid_err(hdev, "Could not allocate memory for driver data\n");
433                 return -ENOMEM;
434         }
435
436         // set same default values as windows driver
437         data_pointer->sensitivity = 0xa0;
438         data_pointer->press_speed = 0x38;
439
440         name_mute = kzalloc(name_sz, GFP_KERNEL);
441         if (name_mute == NULL) {
442                 hid_err(hdev, "Could not allocate memory for led data\n");
443                 ret = -ENOMEM;
444                 goto err;
445         }
446         snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
447
448         name_micmute = kzalloc(name_sz, GFP_KERNEL);
449         if (name_micmute == NULL) {
450                 hid_err(hdev, "Could not allocate memory for led data\n");
451                 ret = -ENOMEM;
452                 goto err2;
453         }
454         snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
455
456         hid_set_drvdata(hdev, data_pointer);
457
458         data_pointer->led_mute.name = name_mute;
459         data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
460         data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
461         data_pointer->led_mute.dev = dev;
462         led_classdev_register(dev, &data_pointer->led_mute);
463
464         data_pointer->led_micmute.name = name_micmute;
465         data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
466         data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
467         data_pointer->led_micmute.dev = dev;
468         led_classdev_register(dev, &data_pointer->led_micmute);
469
470         tpkbd_features_set(hdev);
471
472         return 0;
473
474 err2:
475         kfree(name_mute);
476 err:
477         kfree(data_pointer);
478         return ret;
479 }
480
481 static int tpkbd_probe(struct hid_device *hdev,
482                 const struct hid_device_id *id)
483 {
484         int ret;
485         struct usbhid_device *uhdev;
486
487         ret = hid_parse(hdev);
488         if (ret) {
489                 hid_err(hdev, "hid_parse failed\n");
490                 goto err_free;
491         }
492
493         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
494         if (ret) {
495                 hid_err(hdev, "hid_hw_start failed\n");
496                 goto err_free;
497         }
498
499         uhdev = (struct usbhid_device *) hdev->driver_data;
500
501         if (uhdev->ifnum == 1)
502                 return tpkbd_probe_tp(hdev);
503
504         return 0;
505 err_free:
506         return ret;
507 }
508
509 static void tpkbd_remove_tp(struct hid_device *hdev)
510 {
511         struct tpkbd_data_pointer *data_pointer;
512
513         sysfs_remove_group(&hdev->dev.kobj,
514                         &tpkbd_attr_group_pointer);
515
516         data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
517
518         led_classdev_unregister(&data_pointer->led_micmute);
519         led_classdev_unregister(&data_pointer->led_mute);
520
521         hid_set_drvdata(hdev, NULL);
522         kfree(data_pointer);
523 }
524
525 static void tpkbd_remove(struct hid_device *hdev)
526 {
527         struct usbhid_device *uhdev;
528
529         uhdev = (struct usbhid_device *) hdev->driver_data;
530         if (uhdev->ifnum == 1)
531                 tpkbd_remove_tp(hdev);
532
533         hid_hw_stop(hdev);
534 }
535
536 static const struct hid_device_id tpkbd_devices[] = {
537         { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
538         { }
539 };
540
541 MODULE_DEVICE_TABLE(hid, tpkbd_devices);
542
543 static struct hid_driver tpkbd_driver = {
544         .name = "lenovo_tpkbd",
545         .id_table = tpkbd_devices,
546         .input_mapping = tpkbd_input_mapping,
547         .probe = tpkbd_probe,
548         .remove = tpkbd_remove,
549 };
550
551 static int __init tpkbd_init(void)
552 {
553         return hid_register_driver(&tpkbd_driver);
554 }
555
556 static void __exit tpkbd_exit(void)
557 {
558         hid_unregister_driver(&tpkbd_driver);
559 }
560
561 module_init(tpkbd_init);
562 module_exit(tpkbd_exit);
563
564 MODULE_LICENSE("GPL");