hid-lenovo-tpkbd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
  3. *
  4. * Copyright (c) 2012 Bernhard Seibold
  5. */
  6. /*
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the Free
  9. * Software Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/sysfs.h>
  14. #include <linux/device.h>
  15. #include <linux/hid.h>
  16. #include <linux/input.h>
  17. #include <linux/leds.h>
  18. #include "hid-ids.h"
  19. /* This is only used for the trackpoint part of the driver, hence _tp */
  20. struct tpkbd_data_pointer {
  21. int led_state;
  22. struct led_classdev led_mute;
  23. struct led_classdev led_micmute;
  24. int press_to_select;
  25. int dragging;
  26. int release_to_select;
  27. int select_right;
  28. int sensitivity;
  29. int press_speed;
  30. };
  31. #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
  32. static int tpkbd_input_mapping(struct hid_device *hdev,
  33. struct hid_input *hi, struct hid_field *field,
  34. struct hid_usage *usage, unsigned long **bit, int *max)
  35. {
  36. if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
  37. /* mark the device as pointer */
  38. hid_set_drvdata(hdev, (void *)1);
  39. map_key_clear(KEY_MICMUTE);
  40. return 1;
  41. }
  42. return 0;
  43. }
  44. #undef map_key_clear
  45. static int tpkbd_features_set(struct hid_device *hdev)
  46. {
  47. struct hid_report *report;
  48. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  49. report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
  50. report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02;
  51. report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08;
  52. report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
  53. report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40;
  54. report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
  55. report->field[2]->value[0] = data_pointer->sensitivity;
  56. report->field[3]->value[0] = data_pointer->press_speed;
  57. hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
  58. return 0;
  59. }
  60. static ssize_t pointer_press_to_select_show(struct device *dev,
  61. struct device_attribute *attr,
  62. char *buf)
  63. {
  64. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  65. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  66. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
  67. }
  68. static ssize_t pointer_press_to_select_store(struct device *dev,
  69. struct device_attribute *attr,
  70. const char *buf,
  71. size_t count)
  72. {
  73. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  74. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  75. int value;
  76. if (kstrtoint(buf, 10, &value))
  77. return -EINVAL;
  78. if (value < 0 || value > 1)
  79. return -EINVAL;
  80. data_pointer->press_to_select = value;
  81. tpkbd_features_set(hdev);
  82. return count;
  83. }
  84. static ssize_t pointer_dragging_show(struct device *dev,
  85. struct device_attribute *attr,
  86. char *buf)
  87. {
  88. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  89. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  90. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
  91. }
  92. static ssize_t pointer_dragging_store(struct device *dev,
  93. struct device_attribute *attr,
  94. const char *buf,
  95. size_t count)
  96. {
  97. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  98. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  99. int value;
  100. if (kstrtoint(buf, 10, &value))
  101. return -EINVAL;
  102. if (value < 0 || value > 1)
  103. return -EINVAL;
  104. data_pointer->dragging = value;
  105. tpkbd_features_set(hdev);
  106. return count;
  107. }
  108. static ssize_t pointer_release_to_select_show(struct device *dev,
  109. struct device_attribute *attr,
  110. char *buf)
  111. {
  112. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  113. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  114. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
  115. }
  116. static ssize_t pointer_release_to_select_store(struct device *dev,
  117. struct device_attribute *attr,
  118. const char *buf,
  119. size_t count)
  120. {
  121. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  122. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  123. int value;
  124. if (kstrtoint(buf, 10, &value))
  125. return -EINVAL;
  126. if (value < 0 || value > 1)
  127. return -EINVAL;
  128. data_pointer->release_to_select = value;
  129. tpkbd_features_set(hdev);
  130. return count;
  131. }
  132. static ssize_t pointer_select_right_show(struct device *dev,
  133. struct device_attribute *attr,
  134. char *buf)
  135. {
  136. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  137. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  138. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
  139. }
  140. static ssize_t pointer_select_right_store(struct device *dev,
  141. struct device_attribute *attr,
  142. const char *buf,
  143. size_t count)
  144. {
  145. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  146. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  147. int value;
  148. if (kstrtoint(buf, 10, &value))
  149. return -EINVAL;
  150. if (value < 0 || value > 1)
  151. return -EINVAL;
  152. data_pointer->select_right = value;
  153. tpkbd_features_set(hdev);
  154. return count;
  155. }
  156. static ssize_t pointer_sensitivity_show(struct device *dev,
  157. struct device_attribute *attr,
  158. char *buf)
  159. {
  160. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  161. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  162. return snprintf(buf, PAGE_SIZE, "%u\n",
  163. data_pointer->sensitivity);
  164. }
  165. static ssize_t pointer_sensitivity_store(struct device *dev,
  166. struct device_attribute *attr,
  167. const char *buf,
  168. size_t count)
  169. {
  170. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  171. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  172. int value;
  173. if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
  174. return -EINVAL;
  175. data_pointer->sensitivity = value;
  176. tpkbd_features_set(hdev);
  177. return count;
  178. }
  179. static ssize_t pointer_press_speed_show(struct device *dev,
  180. struct device_attribute *attr,
  181. char *buf)
  182. {
  183. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  184. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  185. return snprintf(buf, PAGE_SIZE, "%u\n",
  186. data_pointer->press_speed);
  187. }
  188. static ssize_t pointer_press_speed_store(struct device *dev,
  189. struct device_attribute *attr,
  190. const char *buf,
  191. size_t count)
  192. {
  193. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  194. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  195. int value;
  196. if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
  197. return -EINVAL;
  198. data_pointer->press_speed = value;
  199. tpkbd_features_set(hdev);
  200. return count;
  201. }
  202. static struct device_attribute dev_attr_pointer_press_to_select =
  203. __ATTR(press_to_select, S_IWUSR | S_IRUGO,
  204. pointer_press_to_select_show,
  205. pointer_press_to_select_store);
  206. static struct device_attribute dev_attr_pointer_dragging =
  207. __ATTR(dragging, S_IWUSR | S_IRUGO,
  208. pointer_dragging_show,
  209. pointer_dragging_store);
  210. static struct device_attribute dev_attr_pointer_release_to_select =
  211. __ATTR(release_to_select, S_IWUSR | S_IRUGO,
  212. pointer_release_to_select_show,
  213. pointer_release_to_select_store);
  214. static struct device_attribute dev_attr_pointer_select_right =
  215. __ATTR(select_right, S_IWUSR | S_IRUGO,
  216. pointer_select_right_show,
  217. pointer_select_right_store);
  218. static struct device_attribute dev_attr_pointer_sensitivity =
  219. __ATTR(sensitivity, S_IWUSR | S_IRUGO,
  220. pointer_sensitivity_show,
  221. pointer_sensitivity_store);
  222. static struct device_attribute dev_attr_pointer_press_speed =
  223. __ATTR(press_speed, S_IWUSR | S_IRUGO,
  224. pointer_press_speed_show,
  225. pointer_press_speed_store);
  226. static struct attribute *tpkbd_attributes_pointer[] = {
  227. &dev_attr_pointer_press_to_select.attr,
  228. &dev_attr_pointer_dragging.attr,
  229. &dev_attr_pointer_release_to_select.attr,
  230. &dev_attr_pointer_select_right.attr,
  231. &dev_attr_pointer_sensitivity.attr,
  232. &dev_attr_pointer_press_speed.attr,
  233. NULL
  234. };
  235. static const struct attribute_group tpkbd_attr_group_pointer = {
  236. .attrs = tpkbd_attributes_pointer,
  237. };
  238. static enum led_brightness tpkbd_led_brightness_get(
  239. struct led_classdev *led_cdev)
  240. {
  241. struct device *dev = led_cdev->dev->parent;
  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 led_nr = 0;
  245. if (led_cdev == &data_pointer->led_micmute)
  246. led_nr = 1;
  247. return data_pointer->led_state & (1 << led_nr)
  248. ? LED_FULL
  249. : LED_OFF;
  250. }
  251. static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
  252. enum led_brightness value)
  253. {
  254. struct device *dev = led_cdev->dev->parent;
  255. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  256. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  257. struct hid_report *report;
  258. int led_nr = 0;
  259. if (led_cdev == &data_pointer->led_micmute)
  260. led_nr = 1;
  261. if (value == LED_OFF)
  262. data_pointer->led_state &= ~(1 << led_nr);
  263. else
  264. data_pointer->led_state |= 1 << led_nr;
  265. report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
  266. report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
  267. report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
  268. hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
  269. }
  270. static int tpkbd_probe_tp(struct hid_device *hdev)
  271. {
  272. struct device *dev = &hdev->dev;
  273. struct tpkbd_data_pointer *data_pointer;
  274. size_t name_sz = strlen(dev_name(dev)) + 16;
  275. char *name_mute, *name_micmute;
  276. int i;
  277. /* Validate required reports. */
  278. for (i = 0; i < 4; i++) {
  279. if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
  280. return -ENODEV;
  281. }
  282. if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
  283. return -ENODEV;
  284. if (sysfs_create_group(&hdev->dev.kobj,
  285. &tpkbd_attr_group_pointer)) {
  286. hid_warn(hdev, "Could not create sysfs group\n");
  287. }
  288. data_pointer = devm_kzalloc(&hdev->dev,
  289. sizeof(struct tpkbd_data_pointer),
  290. GFP_KERNEL);
  291. if (data_pointer == NULL) {
  292. hid_err(hdev, "Could not allocate memory for driver data\n");
  293. return -ENOMEM;
  294. }
  295. // set same default values as windows driver
  296. data_pointer->sensitivity = 0xa0;
  297. data_pointer->press_speed = 0x38;
  298. name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
  299. name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
  300. if (name_mute == NULL || name_micmute == NULL) {
  301. hid_err(hdev, "Could not allocate memory for led data\n");
  302. return -ENOMEM;
  303. }
  304. snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
  305. snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
  306. hid_set_drvdata(hdev, data_pointer);
  307. data_pointer->led_mute.name = name_mute;
  308. data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
  309. data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
  310. data_pointer->led_mute.dev = dev;
  311. led_classdev_register(dev, &data_pointer->led_mute);
  312. data_pointer->led_micmute.name = name_micmute;
  313. data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
  314. data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
  315. data_pointer->led_micmute.dev = dev;
  316. led_classdev_register(dev, &data_pointer->led_micmute);
  317. tpkbd_features_set(hdev);
  318. return 0;
  319. }
  320. static int tpkbd_probe(struct hid_device *hdev,
  321. const struct hid_device_id *id)
  322. {
  323. int ret;
  324. ret = hid_parse(hdev);
  325. if (ret) {
  326. hid_err(hdev, "hid_parse failed\n");
  327. goto err;
  328. }
  329. ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
  330. if (ret) {
  331. hid_err(hdev, "hid_hw_start failed\n");
  332. goto err;
  333. }
  334. if (hid_get_drvdata(hdev)) {
  335. hid_set_drvdata(hdev, NULL);
  336. ret = tpkbd_probe_tp(hdev);
  337. if (ret)
  338. goto err_hid;
  339. }
  340. return 0;
  341. err_hid:
  342. hid_hw_stop(hdev);
  343. err:
  344. return ret;
  345. }
  346. static void tpkbd_remove_tp(struct hid_device *hdev)
  347. {
  348. struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  349. sysfs_remove_group(&hdev->dev.kobj,
  350. &tpkbd_attr_group_pointer);
  351. led_classdev_unregister(&data_pointer->led_micmute);
  352. led_classdev_unregister(&data_pointer->led_mute);
  353. hid_set_drvdata(hdev, NULL);
  354. }
  355. static void tpkbd_remove(struct hid_device *hdev)
  356. {
  357. if (hid_get_drvdata(hdev))
  358. tpkbd_remove_tp(hdev);
  359. hid_hw_stop(hdev);
  360. }
  361. static const struct hid_device_id tpkbd_devices[] = {
  362. { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
  363. { }
  364. };
  365. MODULE_DEVICE_TABLE(hid, tpkbd_devices);
  366. static struct hid_driver tpkbd_driver = {
  367. .name = "lenovo_tpkbd",
  368. .id_table = tpkbd_devices,
  369. .input_mapping = tpkbd_input_mapping,
  370. .probe = tpkbd_probe,
  371. .remove = tpkbd_remove,
  372. };
  373. module_hid_driver(tpkbd_driver);
  374. MODULE_LICENSE("GPL");