Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hid-lenovo-tpkbd.c
Go to the documentation of this file.
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 */
27  int led_state;
31  int dragging;
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)) {
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[] = {
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");