]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/hid/hid-lenovo-tpkbd.c
TTY: mn10300-serial, fix build breakage
[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         usbhid_submit_report(hdev, report, USB_DIR_OUT);
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         data_pointer = hid_get_drvdata(hdev);
232
233         return snprintf(buf, PAGE_SIZE, "%u\n",
234                 data_pointer->press_speed);
235 }
236
237 static ssize_t pointer_press_speed_store(struct device *dev,
238                 struct device_attribute *attr,
239                 const char *buf,
240                 size_t count)
241 {
242         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
243         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
244         int value;
245
246         if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
247                 return -EINVAL;
248
249         data_pointer->press_speed = value;
250         tpkbd_features_set(hdev);
251
252         return count;
253 }
254
255 static struct device_attribute dev_attr_pointer_press_to_select =
256         __ATTR(press_to_select, S_IWUSR | S_IRUGO,
257                         pointer_press_to_select_show,
258                         pointer_press_to_select_store);
259
260 static struct device_attribute dev_attr_pointer_dragging =
261         __ATTR(dragging, S_IWUSR | S_IRUGO,
262                         pointer_dragging_show,
263                         pointer_dragging_store);
264
265 static struct device_attribute dev_attr_pointer_release_to_select =
266         __ATTR(release_to_select, S_IWUSR | S_IRUGO,
267                         pointer_release_to_select_show,
268                         pointer_release_to_select_store);
269
270 static struct device_attribute dev_attr_pointer_select_right =
271         __ATTR(select_right, S_IWUSR | S_IRUGO,
272                         pointer_select_right_show,
273                         pointer_select_right_store);
274
275 static struct device_attribute dev_attr_pointer_sensitivity =
276         __ATTR(sensitivity, S_IWUSR | S_IRUGO,
277                         pointer_sensitivity_show,
278                         pointer_sensitivity_store);
279
280 static struct device_attribute dev_attr_pointer_press_speed =
281         __ATTR(press_speed, S_IWUSR | S_IRUGO,
282                         pointer_press_speed_show,
283                         pointer_press_speed_store);
284
285 static struct attribute *tpkbd_attributes_pointer[] = {
286         &dev_attr_pointer_press_to_select.attr,
287         &dev_attr_pointer_dragging.attr,
288         &dev_attr_pointer_release_to_select.attr,
289         &dev_attr_pointer_select_right.attr,
290         &dev_attr_pointer_sensitivity.attr,
291         &dev_attr_pointer_press_speed.attr,
292         NULL
293 };
294
295 static const struct attribute_group tpkbd_attr_group_pointer = {
296         .attrs = tpkbd_attributes_pointer,
297 };
298
299 static enum led_brightness tpkbd_led_brightness_get(
300                         struct led_classdev *led_cdev)
301 {
302         struct device *dev = led_cdev->dev->parent;
303         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
304         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
305         int led_nr = 0;
306
307         if (led_cdev == &data_pointer->led_micmute)
308                 led_nr = 1;
309
310         return data_pointer->led_state & (1 << led_nr)
311                                 ? LED_FULL
312                                 : LED_OFF;
313 }
314
315 static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
316                         enum led_brightness value)
317 {
318         struct device *dev = led_cdev->dev->parent;
319         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
320         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
321         struct hid_report *report;
322         int led_nr = 0;
323
324         if (led_cdev == &data_pointer->led_micmute)
325                 led_nr = 1;
326
327         if (value == LED_OFF)
328                 data_pointer->led_state &= ~(1 << led_nr);
329         else
330                 data_pointer->led_state |= 1 << led_nr;
331
332         report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
333         report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
334         report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
335         usbhid_submit_report(hdev, report, USB_DIR_OUT);
336 }
337
338 static int tpkbd_probe_tp(struct hid_device *hdev)
339 {
340         struct device *dev = &hdev->dev;
341         struct tpkbd_data_pointer *data_pointer;
342         size_t name_sz = strlen(dev_name(dev)) + 16;
343         char *name_mute, *name_micmute;
344         int ret;
345
346         if (sysfs_create_group(&hdev->dev.kobj,
347                                 &tpkbd_attr_group_pointer)) {
348                 hid_warn(hdev, "Could not create sysfs group\n");
349         }
350
351         data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL);
352         if (data_pointer == NULL) {
353                 hid_err(hdev, "Could not allocate memory for driver data\n");
354                 return -ENOMEM;
355         }
356
357         // set same default values as windows driver
358         data_pointer->sensitivity = 0xa0;
359         data_pointer->press_speed = 0x38;
360
361         name_mute = kzalloc(name_sz, GFP_KERNEL);
362         if (name_mute == NULL) {
363                 hid_err(hdev, "Could not allocate memory for led data\n");
364                 ret = -ENOMEM;
365                 goto err;
366         }
367         snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
368
369         name_micmute = kzalloc(name_sz, GFP_KERNEL);
370         if (name_micmute == NULL) {
371                 hid_err(hdev, "Could not allocate memory for led data\n");
372                 ret = -ENOMEM;
373                 goto err2;
374         }
375         snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
376
377         hid_set_drvdata(hdev, data_pointer);
378
379         data_pointer->led_mute.name = name_mute;
380         data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
381         data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
382         data_pointer->led_mute.dev = dev;
383         led_classdev_register(dev, &data_pointer->led_mute);
384
385         data_pointer->led_micmute.name = name_micmute;
386         data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
387         data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
388         data_pointer->led_micmute.dev = dev;
389         led_classdev_register(dev, &data_pointer->led_micmute);
390
391         tpkbd_features_set(hdev);
392
393         return 0;
394
395 err2:
396         kfree(name_mute);
397 err:
398         kfree(data_pointer);
399         return ret;
400 }
401
402 static int tpkbd_probe(struct hid_device *hdev,
403                 const struct hid_device_id *id)
404 {
405         int ret;
406         struct usbhid_device *uhdev;
407
408         ret = hid_parse(hdev);
409         if (ret) {
410                 hid_err(hdev, "hid_parse failed\n");
411                 goto err_free;
412         }
413
414         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
415         if (ret) {
416                 hid_err(hdev, "hid_hw_start failed\n");
417                 goto err_free;
418         }
419
420         uhdev = (struct usbhid_device *) hdev->driver_data;
421
422         if (uhdev->ifnum == 1)
423                 return tpkbd_probe_tp(hdev);
424
425         return 0;
426 err_free:
427         return ret;
428 }
429
430 static void tpkbd_remove_tp(struct hid_device *hdev)
431 {
432         struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
433
434         sysfs_remove_group(&hdev->dev.kobj,
435                         &tpkbd_attr_group_pointer);
436
437         led_classdev_unregister(&data_pointer->led_micmute);
438         led_classdev_unregister(&data_pointer->led_mute);
439
440         hid_set_drvdata(hdev, NULL);
441         kfree(data_pointer->led_micmute.name);
442         kfree(data_pointer->led_mute.name);
443         kfree(data_pointer);
444 }
445
446 static void tpkbd_remove(struct hid_device *hdev)
447 {
448         struct usbhid_device *uhdev;
449
450         uhdev = (struct usbhid_device *) hdev->driver_data;
451         if (uhdev->ifnum == 1)
452                 tpkbd_remove_tp(hdev);
453
454         hid_hw_stop(hdev);
455 }
456
457 static const struct hid_device_id tpkbd_devices[] = {
458         { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
459         { }
460 };
461
462 MODULE_DEVICE_TABLE(hid, tpkbd_devices);
463
464 static struct hid_driver tpkbd_driver = {
465         .name = "lenovo_tpkbd",
466         .id_table = tpkbd_devices,
467         .input_mapping = tpkbd_input_mapping,
468         .probe = tpkbd_probe,
469         .remove = tpkbd_remove,
470 };
471
472 static int __init tpkbd_init(void)
473 {
474         return hid_register_driver(&tpkbd_driver);
475 }
476
477 static void __exit tpkbd_exit(void)
478 {
479         hid_unregister_driver(&tpkbd_driver);
480 }
481
482 module_init(tpkbd_init);
483 module_exit(tpkbd_exit);
484
485 MODULE_LICENSE("GPL");