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/hid.h>
18 #include <linux/input.h>
19 #include <linux/leds.h>
23 /* This is only used for the trackpoint part of the driver, hence _tp */
24 struct tpkbd_data_pointer
{
26 struct led_classdev led_mute
;
27 struct led_classdev led_micmute
;
30 int release_to_select
;
36 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
38 static int tpkbd_input_mapping(struct hid_device
*hdev
,
39 struct hid_input
*hi
, struct hid_field
*field
,
40 struct hid_usage
*usage
, unsigned long **bit
, int *max
)
42 if (usage
->hid
== (HID_UP_BUTTON
| 0x0010)) {
43 /* mark the device as pointer */
44 hid_set_drvdata(hdev
, (void *)1);
45 map_key_clear(KEY_MICMUTE
);
53 static int tpkbd_features_set(struct hid_device
*hdev
)
55 struct hid_report
*report
;
56 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
58 report
= hdev
->report_enum
[HID_FEATURE_REPORT
].report_id_hash
[4];
60 report
->field
[0]->value
[0] = data_pointer
->press_to_select
? 0x01 : 0x02;
61 report
->field
[0]->value
[0] |= data_pointer
->dragging
? 0x04 : 0x08;
62 report
->field
[0]->value
[0] |= data_pointer
->release_to_select
? 0x10 : 0x20;
63 report
->field
[0]->value
[0] |= data_pointer
->select_right
? 0x80 : 0x40;
64 report
->field
[1]->value
[0] = 0x03; // unknown setting, imitate windows driver
65 report
->field
[2]->value
[0] = data_pointer
->sensitivity
;
66 report
->field
[3]->value
[0] = data_pointer
->press_speed
;
68 hid_hw_request(hdev
, report
, HID_REQ_SET_REPORT
);
72 static ssize_t
pointer_press_to_select_show(struct device
*dev
,
73 struct device_attribute
*attr
,
76 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
77 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
79 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->press_to_select
);
82 static ssize_t
pointer_press_to_select_store(struct device
*dev
,
83 struct device_attribute
*attr
,
87 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
88 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
91 if (kstrtoint(buf
, 10, &value
))
93 if (value
< 0 || value
> 1)
96 data_pointer
->press_to_select
= value
;
97 tpkbd_features_set(hdev
);
102 static ssize_t
pointer_dragging_show(struct device
*dev
,
103 struct device_attribute
*attr
,
106 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
107 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
109 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->dragging
);
112 static ssize_t
pointer_dragging_store(struct device
*dev
,
113 struct device_attribute
*attr
,
117 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
118 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
121 if (kstrtoint(buf
, 10, &value
))
123 if (value
< 0 || value
> 1)
126 data_pointer
->dragging
= value
;
127 tpkbd_features_set(hdev
);
132 static ssize_t
pointer_release_to_select_show(struct device
*dev
,
133 struct device_attribute
*attr
,
136 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
137 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
139 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->release_to_select
);
142 static ssize_t
pointer_release_to_select_store(struct device
*dev
,
143 struct device_attribute
*attr
,
147 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
148 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
151 if (kstrtoint(buf
, 10, &value
))
153 if (value
< 0 || value
> 1)
156 data_pointer
->release_to_select
= value
;
157 tpkbd_features_set(hdev
);
162 static ssize_t
pointer_select_right_show(struct device
*dev
,
163 struct device_attribute
*attr
,
166 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
167 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
169 return snprintf(buf
, PAGE_SIZE
, "%u\n", data_pointer
->select_right
);
172 static ssize_t
pointer_select_right_store(struct device
*dev
,
173 struct device_attribute
*attr
,
177 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
178 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
181 if (kstrtoint(buf
, 10, &value
))
183 if (value
< 0 || value
> 1)
186 data_pointer
->select_right
= value
;
187 tpkbd_features_set(hdev
);
192 static ssize_t
pointer_sensitivity_show(struct device
*dev
,
193 struct device_attribute
*attr
,
196 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
197 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
199 return snprintf(buf
, PAGE_SIZE
, "%u\n",
200 data_pointer
->sensitivity
);
203 static ssize_t
pointer_sensitivity_store(struct device
*dev
,
204 struct device_attribute
*attr
,
208 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
209 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
212 if (kstrtoint(buf
, 10, &value
) || value
< 1 || value
> 255)
215 data_pointer
->sensitivity
= value
;
216 tpkbd_features_set(hdev
);
221 static ssize_t
pointer_press_speed_show(struct device
*dev
,
222 struct device_attribute
*attr
,
225 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
226 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
228 return snprintf(buf
, PAGE_SIZE
, "%u\n",
229 data_pointer
->press_speed
);
232 static ssize_t
pointer_press_speed_store(struct device
*dev
,
233 struct device_attribute
*attr
,
237 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
238 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
241 if (kstrtoint(buf
, 10, &value
) || value
< 1 || value
> 255)
244 data_pointer
->press_speed
= value
;
245 tpkbd_features_set(hdev
);
250 static struct device_attribute dev_attr_pointer_press_to_select
=
251 __ATTR(press_to_select
, S_IWUSR
| S_IRUGO
,
252 pointer_press_to_select_show
,
253 pointer_press_to_select_store
);
255 static struct device_attribute dev_attr_pointer_dragging
=
256 __ATTR(dragging
, S_IWUSR
| S_IRUGO
,
257 pointer_dragging_show
,
258 pointer_dragging_store
);
260 static struct device_attribute dev_attr_pointer_release_to_select
=
261 __ATTR(release_to_select
, S_IWUSR
| S_IRUGO
,
262 pointer_release_to_select_show
,
263 pointer_release_to_select_store
);
265 static struct device_attribute dev_attr_pointer_select_right
=
266 __ATTR(select_right
, S_IWUSR
| S_IRUGO
,
267 pointer_select_right_show
,
268 pointer_select_right_store
);
270 static struct device_attribute dev_attr_pointer_sensitivity
=
271 __ATTR(sensitivity
, S_IWUSR
| S_IRUGO
,
272 pointer_sensitivity_show
,
273 pointer_sensitivity_store
);
275 static struct device_attribute dev_attr_pointer_press_speed
=
276 __ATTR(press_speed
, S_IWUSR
| S_IRUGO
,
277 pointer_press_speed_show
,
278 pointer_press_speed_store
);
280 static struct attribute
*tpkbd_attributes_pointer
[] = {
281 &dev_attr_pointer_press_to_select
.attr
,
282 &dev_attr_pointer_dragging
.attr
,
283 &dev_attr_pointer_release_to_select
.attr
,
284 &dev_attr_pointer_select_right
.attr
,
285 &dev_attr_pointer_sensitivity
.attr
,
286 &dev_attr_pointer_press_speed
.attr
,
290 static const struct attribute_group tpkbd_attr_group_pointer
= {
291 .attrs
= tpkbd_attributes_pointer
,
294 static enum led_brightness
tpkbd_led_brightness_get(
295 struct led_classdev
*led_cdev
)
297 struct device
*dev
= led_cdev
->dev
->parent
;
298 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
299 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
302 if (led_cdev
== &data_pointer
->led_micmute
)
305 return data_pointer
->led_state
& (1 << led_nr
)
310 static void tpkbd_led_brightness_set(struct led_classdev
*led_cdev
,
311 enum led_brightness value
)
313 struct device
*dev
= led_cdev
->dev
->parent
;
314 struct hid_device
*hdev
= container_of(dev
, struct hid_device
, dev
);
315 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
316 struct hid_report
*report
;
319 if (led_cdev
== &data_pointer
->led_micmute
)
322 if (value
== LED_OFF
)
323 data_pointer
->led_state
&= ~(1 << led_nr
);
325 data_pointer
->led_state
|= 1 << led_nr
;
327 report
= hdev
->report_enum
[HID_OUTPUT_REPORT
].report_id_hash
[3];
328 report
->field
[0]->value
[0] = (data_pointer
->led_state
>> 0) & 1;
329 report
->field
[0]->value
[1] = (data_pointer
->led_state
>> 1) & 1;
330 hid_hw_request(hdev
, report
, HID_REQ_SET_REPORT
);
333 static int tpkbd_probe_tp(struct hid_device
*hdev
)
335 struct device
*dev
= &hdev
->dev
;
336 struct tpkbd_data_pointer
*data_pointer
;
337 size_t name_sz
= strlen(dev_name(dev
)) + 16;
338 char *name_mute
, *name_micmute
;
341 /* Validate required reports. */
342 for (i
= 0; i
< 4; i
++) {
343 if (!hid_validate_values(hdev
, HID_FEATURE_REPORT
, 4, i
, 1))
346 if (!hid_validate_values(hdev
, HID_OUTPUT_REPORT
, 3, 0, 2))
349 if (sysfs_create_group(&hdev
->dev
.kobj
,
350 &tpkbd_attr_group_pointer
)) {
351 hid_warn(hdev
, "Could not create sysfs group\n");
354 data_pointer
= devm_kzalloc(&hdev
->dev
,
355 sizeof(struct tpkbd_data_pointer
),
357 if (data_pointer
== NULL
) {
358 hid_err(hdev
, "Could not allocate memory for driver data\n");
362 // set same default values as windows driver
363 data_pointer
->sensitivity
= 0xa0;
364 data_pointer
->press_speed
= 0x38;
366 name_mute
= devm_kzalloc(&hdev
->dev
, name_sz
, GFP_KERNEL
);
367 name_micmute
= devm_kzalloc(&hdev
->dev
, name_sz
, GFP_KERNEL
);
368 if (name_mute
== NULL
|| name_micmute
== NULL
) {
369 hid_err(hdev
, "Could not allocate memory for led data\n");
372 snprintf(name_mute
, name_sz
, "%s:amber:mute", dev_name(dev
));
373 snprintf(name_micmute
, name_sz
, "%s:amber:micmute", dev_name(dev
));
375 hid_set_drvdata(hdev
, data_pointer
);
377 data_pointer
->led_mute
.name
= name_mute
;
378 data_pointer
->led_mute
.brightness_get
= tpkbd_led_brightness_get
;
379 data_pointer
->led_mute
.brightness_set
= tpkbd_led_brightness_set
;
380 data_pointer
->led_mute
.dev
= dev
;
381 led_classdev_register(dev
, &data_pointer
->led_mute
);
383 data_pointer
->led_micmute
.name
= name_micmute
;
384 data_pointer
->led_micmute
.brightness_get
= tpkbd_led_brightness_get
;
385 data_pointer
->led_micmute
.brightness_set
= tpkbd_led_brightness_set
;
386 data_pointer
->led_micmute
.dev
= dev
;
387 led_classdev_register(dev
, &data_pointer
->led_micmute
);
389 tpkbd_features_set(hdev
);
394 static int tpkbd_probe(struct hid_device
*hdev
,
395 const struct hid_device_id
*id
)
399 ret
= hid_parse(hdev
);
401 hid_err(hdev
, "hid_parse failed\n");
405 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
407 hid_err(hdev
, "hid_hw_start failed\n");
411 if (hid_get_drvdata(hdev
)) {
412 hid_set_drvdata(hdev
, NULL
);
413 ret
= tpkbd_probe_tp(hdev
);
425 static void tpkbd_remove_tp(struct hid_device
*hdev
)
427 struct tpkbd_data_pointer
*data_pointer
= hid_get_drvdata(hdev
);
429 sysfs_remove_group(&hdev
->dev
.kobj
,
430 &tpkbd_attr_group_pointer
);
432 led_classdev_unregister(&data_pointer
->led_micmute
);
433 led_classdev_unregister(&data_pointer
->led_mute
);
435 hid_set_drvdata(hdev
, NULL
);
438 static void tpkbd_remove(struct hid_device
*hdev
)
440 if (hid_get_drvdata(hdev
))
441 tpkbd_remove_tp(hdev
);
446 static const struct hid_device_id tpkbd_devices
[] = {
447 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO
, USB_DEVICE_ID_LENOVO_TPKBD
) },
451 MODULE_DEVICE_TABLE(hid
, tpkbd_devices
);
453 static struct hid_driver tpkbd_driver
= {
454 .name
= "lenovo_tpkbd",
455 .id_table
= tpkbd_devices
,
456 .input_mapping
= tpkbd_input_mapping
,
457 .probe
= tpkbd_probe
,
458 .remove
= tpkbd_remove
,
460 module_hid_driver(tpkbd_driver
);
462 MODULE_LICENSE("GPL");