2 * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
4 * Copyright (c) 2012 Bernhard Seibold
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)
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"
25 /* This is only used for the trackpoint part of the driver, hence _tp */
26 struct tpkbd_data_pointer
{
28 struct led_classdev led_mute
;
29 struct led_classdev led_micmute
;
32 int release_to_select
;
38 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
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
)
44 struct usbhid_device
*uhdev
;
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
);
56 static int tpkbd_features_set(struct hid_device
*hdev
)
58 struct hid_report
*report
;
59 struct tpkbd_data_pointer
*data_pointer
;
61 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
62 report
= hdev
->report_enum
[HID_FEATURE_REPORT
].report_id_hash
[4];
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
;
72 usbhid_submit_report(hdev
, report
, USB_DIR_OUT
);
76 static ssize_t
pointer_press_to_select_show(struct device
*dev
,
77 struct device_attribute
*attr
,
80 struct hid_device
*hdev
;
81 struct tpkbd_data_pointer
*data_pointer
;
83 hdev
= container_of(dev
, struct hid_device
, dev
);
87 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
89 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->press_to_select
);
92 static ssize_t
pointer_press_to_select_store(struct device
*dev
,
93 struct device_attribute
*attr
,
97 struct hid_device
*hdev
;
98 struct tpkbd_data_pointer
*data_pointer
;
101 hdev
= container_of(dev
, struct hid_device
, dev
);
105 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
107 if (kstrtoint(buf
, 10, &value
))
109 if (value
< 0 || value
> 1)
112 data_pointer
->press_to_select
= value
;
113 tpkbd_features_set(hdev
);
118 static ssize_t
pointer_dragging_show(struct device
*dev
,
119 struct device_attribute
*attr
,
122 struct hid_device
*hdev
;
123 struct tpkbd_data_pointer
*data_pointer
;
125 hdev
= container_of(dev
, struct hid_device
, dev
);
129 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
131 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->dragging
);
134 static ssize_t
pointer_dragging_store(struct device
*dev
,
135 struct device_attribute
*attr
,
139 struct hid_device
*hdev
;
140 struct tpkbd_data_pointer
*data_pointer
;
143 hdev
= container_of(dev
, struct hid_device
, dev
);
147 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
149 if (kstrtoint(buf
, 10, &value
))
151 if (value
< 0 || value
> 1)
154 data_pointer
->dragging
= value
;
155 tpkbd_features_set(hdev
);
160 static ssize_t
pointer_release_to_select_show(struct device
*dev
,
161 struct device_attribute
*attr
,
164 struct hid_device
*hdev
;
165 struct tpkbd_data_pointer
*data_pointer
;
167 hdev
= container_of(dev
, struct hid_device
, dev
);
171 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
173 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->release_to_select
);
176 static ssize_t
pointer_release_to_select_store(struct device
*dev
,
177 struct device_attribute
*attr
,
181 struct hid_device
*hdev
;
182 struct tpkbd_data_pointer
*data_pointer
;
185 hdev
= container_of(dev
, struct hid_device
, dev
);
189 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
191 if (kstrtoint(buf
, 10, &value
))
193 if (value
< 0 || value
> 1)
196 data_pointer
->release_to_select
= value
;
197 tpkbd_features_set(hdev
);
202 static ssize_t
pointer_select_right_show(struct device
*dev
,
203 struct device_attribute
*attr
,
206 struct hid_device
*hdev
;
207 struct tpkbd_data_pointer
*data_pointer
;
209 hdev
= container_of(dev
, struct hid_device
, dev
);
213 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
215 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->select_right
);
218 static ssize_t
pointer_select_right_store(struct device
*dev
,
219 struct device_attribute
*attr
,
223 struct hid_device
*hdev
;
224 struct tpkbd_data_pointer
*data_pointer
;
227 hdev
= container_of(dev
, struct hid_device
, dev
);
231 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
233 if (kstrtoint(buf
, 10, &value
))
235 if (value
< 0 || value
> 1)
238 data_pointer
->select_right
= value
;
239 tpkbd_features_set(hdev
);
244 static ssize_t
pointer_sensitivity_show(struct device
*dev
,
245 struct device_attribute
*attr
,
248 struct hid_device
*hdev
;
249 struct tpkbd_data_pointer
*data_pointer
;
251 hdev
= container_of(dev
, struct hid_device
, dev
);
255 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
257 return snprintf(buf
, PAGE_SIZE
, "%u\n",
258 data_pointer
->sensitivity
);
261 static ssize_t
pointer_sensitivity_store(struct device
*dev
,
262 struct device_attribute
*attr
,
266 struct hid_device
*hdev
;
267 struct tpkbd_data_pointer
*data_pointer
;
270 hdev
= container_of(dev
, struct hid_device
, dev
);
274 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
276 if (kstrtoint(buf
, 10, &value
) || value
< 1 || value
> 255)
279 data_pointer
->sensitivity
= value
;
280 tpkbd_features_set(hdev
);
285 static ssize_t
pointer_press_speed_show(struct device
*dev
,
286 struct device_attribute
*attr
,
289 struct hid_device
*hdev
;
290 struct tpkbd_data_pointer
*data_pointer
;
292 hdev
= container_of(dev
, struct hid_device
, dev
);
296 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
298 return snprintf(buf
, PAGE_SIZE
, "%u\n",
299 data_pointer
->press_speed
);
302 static ssize_t
pointer_press_speed_store(struct device
*dev
,
303 struct device_attribute
*attr
,
307 struct hid_device
*hdev
;
308 struct tpkbd_data_pointer
*data_pointer
;
311 hdev
= container_of(dev
, struct hid_device
, dev
);
315 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
317 if (kstrtoint(buf
, 10, &value
) || value
< 1 || value
> 255)
320 data_pointer
->press_speed
= value
;
321 tpkbd_features_set(hdev
);
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
);
331 static struct device_attribute dev_attr_pointer_dragging
=
332 __ATTR(dragging
, S_IWUSR
| S_IRUGO
,
333 pointer_dragging_show
,
334 pointer_dragging_store
);
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
);
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
);
346 static struct device_attribute dev_attr_pointer_sensitivity
=
347 __ATTR(sensitivity
, S_IWUSR
| S_IRUGO
,
348 pointer_sensitivity_show
,
349 pointer_sensitivity_store
);
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
);
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
,
366 static const struct attribute_group tpkbd_attr_group_pointer
= {
367 .attrs
= tpkbd_attributes_pointer
,
370 static enum led_brightness
tpkbd_led_brightness_get(
371 struct led_classdev
*led_cdev
)
374 struct hid_device
*hdev
;
375 struct tpkbd_data_pointer
*data_pointer
;
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
);
382 if (led_cdev
== &data_pointer
->led_micmute
)
385 return data_pointer
->led_state
& (1 << led_nr
)
390 static void tpkbd_led_brightness_set(struct led_classdev
*led_cdev
,
391 enum led_brightness value
)
394 struct hid_device
*hdev
;
395 struct hid_report
*report
;
396 struct tpkbd_data_pointer
*data_pointer
;
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
);
403 if (led_cdev
== &data_pointer
->led_micmute
)
406 if (value
== LED_OFF
)
407 data_pointer
->led_state
&= ~(1 << led_nr
);
409 data_pointer
->led_state
|= 1 << led_nr
;
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
);
417 static int tpkbd_probe_tp(struct hid_device
*hdev
)
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
;
425 if (sysfs_create_group(&hdev
->dev
.kobj
,
426 &tpkbd_attr_group_pointer
)) {
427 hid_warn(hdev
, "Could not create sysfs group\n");
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");
436 // set same default values as windows driver
437 data_pointer
->sensitivity
= 0xa0;
438 data_pointer
->press_speed
= 0x38;
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");
446 snprintf(name_mute
, name_sz
, "%s:amber:mute", dev_name(dev
));
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");
454 snprintf(name_micmute
, name_sz
, "%s:amber:micmute", dev_name(dev
));
456 hid_set_drvdata(hdev
, data_pointer
);
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
);
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
);
470 tpkbd_features_set(hdev
);
481 static int tpkbd_probe(struct hid_device
*hdev
,
482 const struct hid_device_id
*id
)
485 struct usbhid_device
*uhdev
;
487 ret
= hid_parse(hdev
);
489 hid_err(hdev
, "hid_parse failed\n");
493 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
495 hid_err(hdev
, "hid_hw_start failed\n");
499 uhdev
= (struct usbhid_device
*) hdev
->driver_data
;
501 if (uhdev
->ifnum
== 1)
502 return tpkbd_probe_tp(hdev
);
509 static void tpkbd_remove_tp(struct hid_device
*hdev
)
511 struct tpkbd_data_pointer
*data_pointer
;
513 sysfs_remove_group(&hdev
->dev
.kobj
,
514 &tpkbd_attr_group_pointer
);
516 data_pointer
= (struct tpkbd_data_pointer
*) hid_get_drvdata(hdev
);
518 led_classdev_unregister(&data_pointer
->led_micmute
);
519 led_classdev_unregister(&data_pointer
->led_mute
);
521 hid_set_drvdata(hdev
, NULL
);
522 kfree(data_pointer
->led_micmute
.name
);
523 kfree(data_pointer
->led_mute
.name
);
527 static void tpkbd_remove(struct hid_device
*hdev
)
529 struct usbhid_device
*uhdev
;
531 uhdev
= (struct usbhid_device
*) hdev
->driver_data
;
532 if (uhdev
->ifnum
== 1)
533 tpkbd_remove_tp(hdev
);
538 static const struct hid_device_id tpkbd_devices
[] = {
539 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO
, USB_DEVICE_ID_LENOVO_TPKBD
) },
543 MODULE_DEVICE_TABLE(hid
, tpkbd_devices
);
545 static struct hid_driver tpkbd_driver
= {
546 .name
= "lenovo_tpkbd",
547 .id_table
= tpkbd_devices
,
548 .input_mapping
= tpkbd_input_mapping
,
549 .probe
= tpkbd_probe
,
550 .remove
= tpkbd_remove
,
553 static int __init
tpkbd_init(void)
555 return hid_register_driver(&tpkbd_driver
);
558 static void __exit
tpkbd_exit(void)
560 hid_unregister_driver(&tpkbd_driver
);
563 module_init(tpkbd_init
);
564 module_exit(tpkbd_exit
);
566 MODULE_LICENSE("GPL");