hid-lenovo.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*
  2. * HID driver for Lenovo:
  3. * - ThinkPad USB Keyboard with TrackPoint (tpkbd)
  4. * - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
  5. * - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
  6. *
  7. * Copyright (c) 2012 Bernhard Seibold
  8. * Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk>
  9. */
  10. /*
  11. * This program is free software; you can redistribute it and/or modify it
  12. * under the terms of the GNU General Public License as published by the Free
  13. * Software Foundation; either version 2 of the License, or (at your option)
  14. * any later version.
  15. */
  16. #include <linux/module.h>
  17. #include <linux/sysfs.h>
  18. #include <linux/device.h>
  19. #include <linux/hid.h>
  20. #include <linux/input.h>
  21. #include <linux/leds.h>
  22. #include "hid-ids.h"
  23. struct lenovo_drvdata_tpkbd {
  24. int led_state;
  25. struct led_classdev led_mute;
  26. struct led_classdev led_micmute;
  27. int press_to_select;
  28. int dragging;
  29. int release_to_select;
  30. int select_right;
  31. int sensitivity;
  32. int press_speed;
  33. };
  34. struct lenovo_drvdata_cptkbd {
  35. bool fn_lock;
  36. };
  37. #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
  38. static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
  39. struct hid_input *hi, struct hid_field *field,
  40. struct hid_usage *usage, unsigned long **bit, int *max)
  41. {
  42. if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
  43. /* This sub-device contains trackpoint, mark it */
  44. hid_set_drvdata(hdev, (void *)1);
  45. map_key_clear(KEY_MICMUTE);
  46. return 1;
  47. }
  48. return 0;
  49. }
  50. static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
  51. struct hid_input *hi, struct hid_field *field,
  52. struct hid_usage *usage, unsigned long **bit, int *max)
  53. {
  54. /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
  55. if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
  56. (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
  57. switch (usage->hid & HID_USAGE) {
  58. case 0x00f1: /* Fn-F4: Mic mute */
  59. map_key_clear(KEY_MICMUTE);
  60. return 1;
  61. case 0x00f2: /* Fn-F5: Brightness down */
  62. map_key_clear(KEY_BRIGHTNESSDOWN);
  63. return 1;
  64. case 0x00f3: /* Fn-F6: Brightness up */
  65. map_key_clear(KEY_BRIGHTNESSUP);
  66. return 1;
  67. case 0x00f4: /* Fn-F7: External display (projector) */
  68. map_key_clear(KEY_SWITCHVIDEOMODE);
  69. return 1;
  70. case 0x00f5: /* Fn-F8: Wireless */
  71. map_key_clear(KEY_WLAN);
  72. return 1;
  73. case 0x00f6: /* Fn-F9: Control panel */
  74. map_key_clear(KEY_CONFIG);
  75. return 1;
  76. case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
  77. map_key_clear(KEY_SCALE);
  78. return 1;
  79. case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */
  80. /* NB: This mapping is invented in raw_event below */
  81. map_key_clear(KEY_FILE);
  82. return 1;
  83. case 0x00fa: /* Fn-Esc: Fn-lock toggle */
  84. map_key_clear(KEY_FN_ESC);
  85. return 1;
  86. }
  87. }
  88. return 0;
  89. }
  90. static int lenovo_input_mapping(struct hid_device *hdev,
  91. struct hid_input *hi, struct hid_field *field,
  92. struct hid_usage *usage, unsigned long **bit, int *max)
  93. {
  94. switch (hdev->product) {
  95. case USB_DEVICE_ID_LENOVO_TPKBD:
  96. return lenovo_input_mapping_tpkbd(hdev, hi, field,
  97. usage, bit, max);
  98. case USB_DEVICE_ID_LENOVO_CUSBKBD:
  99. case USB_DEVICE_ID_LENOVO_CBTKBD:
  100. return lenovo_input_mapping_cptkbd(hdev, hi, field,
  101. usage, bit, max);
  102. default:
  103. return 0;
  104. }
  105. }
  106. #undef map_key_clear
  107. /* Send a config command to the keyboard */
  108. static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
  109. unsigned char byte2, unsigned char byte3)
  110. {
  111. int ret;
  112. unsigned char buf[] = {0x18, byte2, byte3};
  113. switch (hdev->product) {
  114. case USB_DEVICE_ID_LENOVO_CUSBKBD:
  115. ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf),
  116. HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
  117. break;
  118. case USB_DEVICE_ID_LENOVO_CBTKBD:
  119. ret = hid_hw_output_report(hdev, buf, sizeof(buf));
  120. break;
  121. default:
  122. ret = -EINVAL;
  123. break;
  124. }
  125. return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
  126. }
  127. static void lenovo_features_set_cptkbd(struct hid_device *hdev)
  128. {
  129. int ret;
  130. struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
  131. ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
  132. if (ret)
  133. hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
  134. }
  135. static ssize_t attr_fn_lock_show_cptkbd(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 lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
  141. return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock);
  142. }
  143. static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
  144. struct device_attribute *attr,
  145. const char *buf,
  146. size_t count)
  147. {
  148. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  149. struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
  150. int value;
  151. if (kstrtoint(buf, 10, &value))
  152. return -EINVAL;
  153. if (value < 0 || value > 1)
  154. return -EINVAL;
  155. cptkbd_data->fn_lock = !!value;
  156. lenovo_features_set_cptkbd(hdev);
  157. return count;
  158. }
  159. static struct device_attribute dev_attr_fn_lock_cptkbd =
  160. __ATTR(fn_lock, S_IWUSR | S_IRUGO,
  161. attr_fn_lock_show_cptkbd,
  162. attr_fn_lock_store_cptkbd);
  163. static struct attribute *lenovo_attributes_cptkbd[] = {
  164. &dev_attr_fn_lock_cptkbd.attr,
  165. NULL
  166. };
  167. static const struct attribute_group lenovo_attr_group_cptkbd = {
  168. .attrs = lenovo_attributes_cptkbd,
  169. };
  170. static int lenovo_raw_event(struct hid_device *hdev,
  171. struct hid_report *report, u8 *data, int size)
  172. {
  173. /*
  174. * Compact USB keyboard's Fn-F12 report holds down many other keys, and
  175. * its own key is outside the usage page range. Remove extra
  176. * keypresses and remap to inside usage page.
  177. */
  178. if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
  179. && size == 3
  180. && data[0] == 0x15
  181. && data[1] == 0x94
  182. && data[2] == 0x01)) {
  183. data[1] = 0x00;
  184. data[2] = 0x01;
  185. }
  186. return 0;
  187. }
  188. static int lenovo_features_set_tpkbd(struct hid_device *hdev)
  189. {
  190. struct hid_report *report;
  191. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  192. report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
  193. report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02;
  194. report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08;
  195. report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
  196. report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40;
  197. report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
  198. report->field[2]->value[0] = data_pointer->sensitivity;
  199. report->field[3]->value[0] = data_pointer->press_speed;
  200. hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
  201. return 0;
  202. }
  203. static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
  204. struct device_attribute *attr,
  205. char *buf)
  206. {
  207. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  208. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  209. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
  210. }
  211. static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
  212. struct device_attribute *attr,
  213. const char *buf,
  214. size_t count)
  215. {
  216. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  217. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  218. int value;
  219. if (kstrtoint(buf, 10, &value))
  220. return -EINVAL;
  221. if (value < 0 || value > 1)
  222. return -EINVAL;
  223. data_pointer->press_to_select = value;
  224. lenovo_features_set_tpkbd(hdev);
  225. return count;
  226. }
  227. static ssize_t attr_dragging_show_tpkbd(struct device *dev,
  228. struct device_attribute *attr,
  229. char *buf)
  230. {
  231. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  232. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  233. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
  234. }
  235. static ssize_t attr_dragging_store_tpkbd(struct device *dev,
  236. struct device_attribute *attr,
  237. const char *buf,
  238. size_t count)
  239. {
  240. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  241. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  242. int value;
  243. if (kstrtoint(buf, 10, &value))
  244. return -EINVAL;
  245. if (value < 0 || value > 1)
  246. return -EINVAL;
  247. data_pointer->dragging = value;
  248. lenovo_features_set_tpkbd(hdev);
  249. return count;
  250. }
  251. static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
  252. struct device_attribute *attr,
  253. char *buf)
  254. {
  255. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  256. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  257. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
  258. }
  259. static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
  260. struct device_attribute *attr,
  261. const char *buf,
  262. size_t count)
  263. {
  264. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  265. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  266. int value;
  267. if (kstrtoint(buf, 10, &value))
  268. return -EINVAL;
  269. if (value < 0 || value > 1)
  270. return -EINVAL;
  271. data_pointer->release_to_select = value;
  272. lenovo_features_set_tpkbd(hdev);
  273. return count;
  274. }
  275. static ssize_t attr_select_right_show_tpkbd(struct device *dev,
  276. struct device_attribute *attr,
  277. char *buf)
  278. {
  279. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  280. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  281. return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
  282. }
  283. static ssize_t attr_select_right_store_tpkbd(struct device *dev,
  284. struct device_attribute *attr,
  285. const char *buf,
  286. size_t count)
  287. {
  288. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  289. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  290. int value;
  291. if (kstrtoint(buf, 10, &value))
  292. return -EINVAL;
  293. if (value < 0 || value > 1)
  294. return -EINVAL;
  295. data_pointer->select_right = value;
  296. lenovo_features_set_tpkbd(hdev);
  297. return count;
  298. }
  299. static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
  300. struct device_attribute *attr,
  301. char *buf)
  302. {
  303. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  304. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  305. return snprintf(buf, PAGE_SIZE, "%u\n",
  306. data_pointer->sensitivity);
  307. }
  308. static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
  309. struct device_attribute *attr,
  310. const char *buf,
  311. size_t count)
  312. {
  313. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  314. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  315. int value;
  316. if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
  317. return -EINVAL;
  318. data_pointer->sensitivity = value;
  319. lenovo_features_set_tpkbd(hdev);
  320. return count;
  321. }
  322. static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
  323. struct device_attribute *attr,
  324. char *buf)
  325. {
  326. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  327. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  328. return snprintf(buf, PAGE_SIZE, "%u\n",
  329. data_pointer->press_speed);
  330. }
  331. static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
  332. struct device_attribute *attr,
  333. const char *buf,
  334. size_t count)
  335. {
  336. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  337. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  338. int value;
  339. if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
  340. return -EINVAL;
  341. data_pointer->press_speed = value;
  342. lenovo_features_set_tpkbd(hdev);
  343. return count;
  344. }
  345. static struct device_attribute dev_attr_press_to_select_tpkbd =
  346. __ATTR(press_to_select, S_IWUSR | S_IRUGO,
  347. attr_press_to_select_show_tpkbd,
  348. attr_press_to_select_store_tpkbd);
  349. static struct device_attribute dev_attr_dragging_tpkbd =
  350. __ATTR(dragging, S_IWUSR | S_IRUGO,
  351. attr_dragging_show_tpkbd,
  352. attr_dragging_store_tpkbd);
  353. static struct device_attribute dev_attr_release_to_select_tpkbd =
  354. __ATTR(release_to_select, S_IWUSR | S_IRUGO,
  355. attr_release_to_select_show_tpkbd,
  356. attr_release_to_select_store_tpkbd);
  357. static struct device_attribute dev_attr_select_right_tpkbd =
  358. __ATTR(select_right, S_IWUSR | S_IRUGO,
  359. attr_select_right_show_tpkbd,
  360. attr_select_right_store_tpkbd);
  361. static struct device_attribute dev_attr_sensitivity_tpkbd =
  362. __ATTR(sensitivity, S_IWUSR | S_IRUGO,
  363. attr_sensitivity_show_tpkbd,
  364. attr_sensitivity_store_tpkbd);
  365. static struct device_attribute dev_attr_press_speed_tpkbd =
  366. __ATTR(press_speed, S_IWUSR | S_IRUGO,
  367. attr_press_speed_show_tpkbd,
  368. attr_press_speed_store_tpkbd);
  369. static struct attribute *lenovo_attributes_tpkbd[] = {
  370. &dev_attr_press_to_select_tpkbd.attr,
  371. &dev_attr_dragging_tpkbd.attr,
  372. &dev_attr_release_to_select_tpkbd.attr,
  373. &dev_attr_select_right_tpkbd.attr,
  374. &dev_attr_sensitivity_tpkbd.attr,
  375. &dev_attr_press_speed_tpkbd.attr,
  376. NULL
  377. };
  378. static const struct attribute_group lenovo_attr_group_tpkbd = {
  379. .attrs = lenovo_attributes_tpkbd,
  380. };
  381. static enum led_brightness lenovo_led_brightness_get_tpkbd(
  382. struct led_classdev *led_cdev)
  383. {
  384. struct device *dev = led_cdev->dev->parent;
  385. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  386. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  387. int led_nr = 0;
  388. if (led_cdev == &data_pointer->led_micmute)
  389. led_nr = 1;
  390. return data_pointer->led_state & (1 << led_nr)
  391. ? LED_FULL
  392. : LED_OFF;
  393. }
  394. static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
  395. enum led_brightness value)
  396. {
  397. struct device *dev = led_cdev->dev->parent;
  398. struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  399. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  400. struct hid_report *report;
  401. int led_nr = 0;
  402. if (led_cdev == &data_pointer->led_micmute)
  403. led_nr = 1;
  404. if (value == LED_OFF)
  405. data_pointer->led_state &= ~(1 << led_nr);
  406. else
  407. data_pointer->led_state |= 1 << led_nr;
  408. report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
  409. report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
  410. report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
  411. hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
  412. }
  413. static int lenovo_probe_tpkbd(struct hid_device *hdev)
  414. {
  415. struct device *dev = &hdev->dev;
  416. struct lenovo_drvdata_tpkbd *data_pointer;
  417. size_t name_sz = strlen(dev_name(dev)) + 16;
  418. char *name_mute, *name_micmute;
  419. int i;
  420. int ret;
  421. /*
  422. * Only register extra settings against subdevice where input_mapping
  423. * set drvdata to 1, i.e. the trackpoint.
  424. */
  425. if (!hid_get_drvdata(hdev))
  426. return 0;
  427. hid_set_drvdata(hdev, NULL);
  428. /* Validate required reports. */
  429. for (i = 0; i < 4; i++) {
  430. if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
  431. return -ENODEV;
  432. }
  433. if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
  434. return -ENODEV;
  435. ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
  436. if (ret)
  437. hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
  438. data_pointer = devm_kzalloc(&hdev->dev,
  439. sizeof(struct lenovo_drvdata_tpkbd),
  440. GFP_KERNEL);
  441. if (data_pointer == NULL) {
  442. hid_err(hdev, "Could not allocate memory for driver data\n");
  443. return -ENOMEM;
  444. }
  445. // set same default values as windows driver
  446. data_pointer->sensitivity = 0xa0;
  447. data_pointer->press_speed = 0x38;
  448. name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
  449. name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
  450. if (name_mute == NULL || name_micmute == NULL) {
  451. hid_err(hdev, "Could not allocate memory for led data\n");
  452. return -ENOMEM;
  453. }
  454. snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
  455. snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
  456. hid_set_drvdata(hdev, data_pointer);
  457. data_pointer->led_mute.name = name_mute;
  458. data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
  459. data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
  460. data_pointer->led_mute.dev = dev;
  461. led_classdev_register(dev, &data_pointer->led_mute);
  462. data_pointer->led_micmute.name = name_micmute;
  463. data_pointer->led_micmute.brightness_get =
  464. lenovo_led_brightness_get_tpkbd;
  465. data_pointer->led_micmute.brightness_set =
  466. lenovo_led_brightness_set_tpkbd;
  467. data_pointer->led_micmute.dev = dev;
  468. led_classdev_register(dev, &data_pointer->led_micmute);
  469. lenovo_features_set_tpkbd(hdev);
  470. return 0;
  471. }
  472. static int lenovo_probe_cptkbd(struct hid_device *hdev)
  473. {
  474. int ret;
  475. struct lenovo_drvdata_cptkbd *cptkbd_data;
  476. /* All the custom action happens on the USBMOUSE device for USB */
  477. if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
  478. && hdev->type != HID_TYPE_USBMOUSE) {
  479. hid_dbg(hdev, "Ignoring keyboard half of device\n");
  480. return 0;
  481. }
  482. cptkbd_data = devm_kzalloc(&hdev->dev,
  483. sizeof(*cptkbd_data),
  484. GFP_KERNEL);
  485. if (cptkbd_data == NULL) {
  486. hid_err(hdev, "can't alloc keyboard descriptor\n");
  487. return -ENOMEM;
  488. }
  489. hid_set_drvdata(hdev, cptkbd_data);
  490. /*
  491. * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
  492. * regular keys
  493. */
  494. ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
  495. if (ret)
  496. hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
  497. /* Turn Fn-Lock on by default */
  498. cptkbd_data->fn_lock = true;
  499. lenovo_features_set_cptkbd(hdev);
  500. ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
  501. if (ret)
  502. hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
  503. return 0;
  504. }
  505. static int lenovo_probe(struct hid_device *hdev,
  506. const struct hid_device_id *id)
  507. {
  508. int ret;
  509. ret = hid_parse(hdev);
  510. if (ret) {
  511. hid_err(hdev, "hid_parse failed\n");
  512. goto err;
  513. }
  514. ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
  515. if (ret) {
  516. hid_err(hdev, "hid_hw_start failed\n");
  517. goto err;
  518. }
  519. switch (hdev->product) {
  520. case USB_DEVICE_ID_LENOVO_TPKBD:
  521. ret = lenovo_probe_tpkbd(hdev);
  522. break;
  523. case USB_DEVICE_ID_LENOVO_CUSBKBD:
  524. case USB_DEVICE_ID_LENOVO_CBTKBD:
  525. ret = lenovo_probe_cptkbd(hdev);
  526. break;
  527. default:
  528. ret = 0;
  529. break;
  530. }
  531. if (ret)
  532. goto err_hid;
  533. return 0;
  534. err_hid:
  535. hid_hw_stop(hdev);
  536. err:
  537. return ret;
  538. }
  539. static void lenovo_remove_tpkbd(struct hid_device *hdev)
  540. {
  541. struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
  542. /*
  543. * Only the trackpoint half of the keyboard has drvdata and stuff that
  544. * needs unregistering.
  545. */
  546. if (data_pointer == NULL)
  547. return;
  548. sysfs_remove_group(&hdev->dev.kobj,
  549. &lenovo_attr_group_tpkbd);
  550. led_classdev_unregister(&data_pointer->led_micmute);
  551. led_classdev_unregister(&data_pointer->led_mute);
  552. hid_set_drvdata(hdev, NULL);
  553. }
  554. static void lenovo_remove_cptkbd(struct hid_device *hdev)
  555. {
  556. sysfs_remove_group(&hdev->dev.kobj,
  557. &lenovo_attr_group_cptkbd);
  558. }
  559. static void lenovo_remove(struct hid_device *hdev)
  560. {
  561. switch (hdev->product) {
  562. case USB_DEVICE_ID_LENOVO_TPKBD:
  563. lenovo_remove_tpkbd(hdev);
  564. break;
  565. case USB_DEVICE_ID_LENOVO_CUSBKBD:
  566. case USB_DEVICE_ID_LENOVO_CBTKBD:
  567. lenovo_remove_cptkbd(hdev);
  568. break;
  569. }
  570. hid_hw_stop(hdev);
  571. }
  572. static const struct hid_device_id lenovo_devices[] = {
  573. { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
  574. { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
  575. { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
  576. { }
  577. };
  578. MODULE_DEVICE_TABLE(hid, lenovo_devices);
  579. static struct hid_driver lenovo_driver = {
  580. .name = "lenovo",
  581. .id_table = lenovo_devices,
  582. .input_mapping = lenovo_input_mapping,
  583. .probe = lenovo_probe,
  584. .remove = lenovo_remove,
  585. .raw_event = lenovo_raw_event,
  586. };
  587. module_hid_driver(lenovo_driver);
  588. MODULE_LICENSE("GPL");