xref: /openbmc/linux/drivers/hid/hid-lenovo.c (revision 82e6fdd6)
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 /*
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 2 of the License, or (at your option)
15  * any later version.
16  */
17 
18 #include <linux/module.h>
19 #include <linux/sysfs.h>
20 #include <linux/device.h>
21 #include <linux/hid.h>
22 #include <linux/input.h>
23 #include <linux/leds.h>
24 
25 #include "hid-ids.h"
26 
27 struct lenovo_drvdata_tpkbd {
28 	int led_state;
29 	struct led_classdev led_mute;
30 	struct led_classdev led_micmute;
31 	int press_to_select;
32 	int dragging;
33 	int release_to_select;
34 	int select_right;
35 	int sensitivity;
36 	int press_speed;
37 };
38 
39 struct lenovo_drvdata_cptkbd {
40 	u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
41 	bool fn_lock;
42 	int sensitivity;
43 };
44 
45 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
46 
47 static const __u8 lenovo_pro_dock_need_fixup_collection[] = {
48 	0x05, 0x88,		/* Usage Page (Vendor Usage Page 0x88)	*/
49 	0x09, 0x01,		/* Usage (Vendor Usage 0x01)		*/
50 	0xa1, 0x01,		/* Collection (Application)		*/
51 	0x85, 0x04,		/*  Report ID (4)			*/
52 	0x19, 0x00,		/*  Usage Minimum (0)			*/
53 	0x2a, 0xff, 0xff,	/*  Usage Maximum (65535)		*/
54 };
55 
56 static __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc,
57 		unsigned int *rsize)
58 {
59 	switch (hdev->product) {
60 	case USB_DEVICE_ID_LENOVO_TPPRODOCK:
61 		/* the fixups that need to be done:
62 		 *   - get a reasonable usage max for the vendor collection
63 		 *     0x8801 from the report ID 4
64 		 */
65 		if (*rsize >= 153 &&
66 		    memcmp(&rdesc[140], lenovo_pro_dock_need_fixup_collection,
67 			  sizeof(lenovo_pro_dock_need_fixup_collection)) == 0) {
68 			rdesc[151] = 0x01;
69 			rdesc[152] = 0x00;
70 		}
71 		break;
72 	}
73 	return rdesc;
74 }
75 
76 static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
77 		struct hid_input *hi, struct hid_field *field,
78 		struct hid_usage *usage, unsigned long **bit, int *max)
79 {
80 	if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
81 		/* This sub-device contains trackpoint, mark it */
82 		hid_set_drvdata(hdev, (void *)1);
83 		map_key_clear(KEY_MICMUTE);
84 		return 1;
85 	}
86 	return 0;
87 }
88 
89 static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
90 		struct hid_input *hi, struct hid_field *field,
91 		struct hid_usage *usage, unsigned long **bit, int *max)
92 {
93 	/* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
94 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
95 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
96 		switch (usage->hid & HID_USAGE) {
97 		case 0x00f1: /* Fn-F4: Mic mute */
98 			map_key_clear(KEY_MICMUTE);
99 			return 1;
100 		case 0x00f2: /* Fn-F5: Brightness down */
101 			map_key_clear(KEY_BRIGHTNESSDOWN);
102 			return 1;
103 		case 0x00f3: /* Fn-F6: Brightness up */
104 			map_key_clear(KEY_BRIGHTNESSUP);
105 			return 1;
106 		case 0x00f4: /* Fn-F7: External display (projector) */
107 			map_key_clear(KEY_SWITCHVIDEOMODE);
108 			return 1;
109 		case 0x00f5: /* Fn-F8: Wireless */
110 			map_key_clear(KEY_WLAN);
111 			return 1;
112 		case 0x00f6: /* Fn-F9: Control panel */
113 			map_key_clear(KEY_CONFIG);
114 			return 1;
115 		case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
116 			map_key_clear(KEY_SCALE);
117 			return 1;
118 		case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */
119 			/* NB: This mapping is invented in raw_event below */
120 			map_key_clear(KEY_FILE);
121 			return 1;
122 		case 0x00fa: /* Fn-Esc: Fn-lock toggle */
123 			map_key_clear(KEY_FN_ESC);
124 			return 1;
125 		case 0x00fb: /* Middle mouse button (in native mode) */
126 			map_key_clear(BTN_MIDDLE);
127 			return 1;
128 		}
129 	}
130 
131 	/* Compatibility middle/wheel mappings should be ignored */
132 	if (usage->hid == HID_GD_WHEEL)
133 		return -1;
134 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON &&
135 			(usage->hid & HID_USAGE) == 0x003)
136 		return -1;
137 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER &&
138 			(usage->hid & HID_USAGE) == 0x238)
139 		return -1;
140 
141 	/* Map wheel emulation reports: 0xffa1 = USB, 0xff10 = BT */
142 	if ((usage->hid & HID_USAGE_PAGE) == 0xff100000 ||
143 	    (usage->hid & HID_USAGE_PAGE) == 0xffa10000) {
144 		field->flags |= HID_MAIN_ITEM_RELATIVE | HID_MAIN_ITEM_VARIABLE;
145 		field->logical_minimum = -127;
146 		field->logical_maximum = 127;
147 
148 		switch (usage->hid & HID_USAGE) {
149 		case 0x0000:
150 			hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
151 			return 1;
152 		case 0x0001:
153 			hid_map_usage(hi, usage, bit, max, EV_REL, REL_WHEEL);
154 			return 1;
155 		default:
156 			return -1;
157 		}
158 	}
159 
160 	return 0;
161 }
162 
163 static int lenovo_input_mapping(struct hid_device *hdev,
164 		struct hid_input *hi, struct hid_field *field,
165 		struct hid_usage *usage, unsigned long **bit, int *max)
166 {
167 	switch (hdev->product) {
168 	case USB_DEVICE_ID_LENOVO_TPKBD:
169 		return lenovo_input_mapping_tpkbd(hdev, hi, field,
170 							usage, bit, max);
171 	case USB_DEVICE_ID_LENOVO_CUSBKBD:
172 	case USB_DEVICE_ID_LENOVO_CBTKBD:
173 		return lenovo_input_mapping_cptkbd(hdev, hi, field,
174 							usage, bit, max);
175 	default:
176 		return 0;
177 	}
178 }
179 
180 #undef map_key_clear
181 
182 /* Send a config command to the keyboard */
183 static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
184 			unsigned char byte2, unsigned char byte3)
185 {
186 	int ret;
187 	unsigned char *buf;
188 
189 	buf = kzalloc(3, GFP_KERNEL);
190 	if (!buf)
191 		return -ENOMEM;
192 
193 	buf[0] = 0x18;
194 	buf[1] = byte2;
195 	buf[2] = byte3;
196 
197 	switch (hdev->product) {
198 	case USB_DEVICE_ID_LENOVO_CUSBKBD:
199 		ret = hid_hw_raw_request(hdev, 0x13, buf, 3,
200 					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
201 		break;
202 	case USB_DEVICE_ID_LENOVO_CBTKBD:
203 		ret = hid_hw_output_report(hdev, buf, 3);
204 		break;
205 	default:
206 		ret = -EINVAL;
207 		break;
208 	}
209 
210 	kfree(buf);
211 
212 	return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
213 }
214 
215 static void lenovo_features_set_cptkbd(struct hid_device *hdev)
216 {
217 	int ret;
218 	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
219 
220 	ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
221 	if (ret)
222 		hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
223 
224 	ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity);
225 	if (ret)
226 		hid_err(hdev, "Sensitivity setting failed: %d\n", ret);
227 }
228 
229 static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
230 		struct device_attribute *attr,
231 		char *buf)
232 {
233 	struct hid_device *hdev = to_hid_device(dev);
234 	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
235 
236 	return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock);
237 }
238 
239 static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
240 		struct device_attribute *attr,
241 		const char *buf,
242 		size_t count)
243 {
244 	struct hid_device *hdev = to_hid_device(dev);
245 	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
246 	int value;
247 
248 	if (kstrtoint(buf, 10, &value))
249 		return -EINVAL;
250 	if (value < 0 || value > 1)
251 		return -EINVAL;
252 
253 	cptkbd_data->fn_lock = !!value;
254 	lenovo_features_set_cptkbd(hdev);
255 
256 	return count;
257 }
258 
259 static ssize_t attr_sensitivity_show_cptkbd(struct device *dev,
260 		struct device_attribute *attr,
261 		char *buf)
262 {
263 	struct hid_device *hdev = to_hid_device(dev);
264 	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
265 
266 	return snprintf(buf, PAGE_SIZE, "%u\n",
267 		cptkbd_data->sensitivity);
268 }
269 
270 static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
271 		struct device_attribute *attr,
272 		const char *buf,
273 		size_t count)
274 {
275 	struct hid_device *hdev = to_hid_device(dev);
276 	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
277 	int value;
278 
279 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
280 		return -EINVAL;
281 
282 	cptkbd_data->sensitivity = value;
283 	lenovo_features_set_cptkbd(hdev);
284 
285 	return count;
286 }
287 
288 
289 static struct device_attribute dev_attr_fn_lock_cptkbd =
290 	__ATTR(fn_lock, S_IWUSR | S_IRUGO,
291 			attr_fn_lock_show_cptkbd,
292 			attr_fn_lock_store_cptkbd);
293 
294 static struct device_attribute dev_attr_sensitivity_cptkbd =
295 	__ATTR(sensitivity, S_IWUSR | S_IRUGO,
296 			attr_sensitivity_show_cptkbd,
297 			attr_sensitivity_store_cptkbd);
298 
299 
300 static struct attribute *lenovo_attributes_cptkbd[] = {
301 	&dev_attr_fn_lock_cptkbd.attr,
302 	&dev_attr_sensitivity_cptkbd.attr,
303 	NULL
304 };
305 
306 static const struct attribute_group lenovo_attr_group_cptkbd = {
307 	.attrs = lenovo_attributes_cptkbd,
308 };
309 
310 static int lenovo_raw_event(struct hid_device *hdev,
311 			struct hid_report *report, u8 *data, int size)
312 {
313 	/*
314 	 * Compact USB keyboard's Fn-F12 report holds down many other keys, and
315 	 * its own key is outside the usage page range. Remove extra
316 	 * keypresses and remap to inside usage page.
317 	 */
318 	if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
319 			&& size == 3
320 			&& data[0] == 0x15
321 			&& data[1] == 0x94
322 			&& data[2] == 0x01)) {
323 		data[1] = 0x00;
324 		data[2] = 0x01;
325 	}
326 
327 	return 0;
328 }
329 
330 static int lenovo_event_cptkbd(struct hid_device *hdev,
331 		struct hid_field *field, struct hid_usage *usage, __s32 value)
332 {
333 	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
334 
335 	/* "wheel" scroll events */
336 	if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
337 			usage->code == REL_HWHEEL)) {
338 		/* Scroll events disable middle-click event */
339 		cptkbd_data->middlebutton_state = 2;
340 		return 0;
341 	}
342 
343 	/* Middle click events */
344 	if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
345 		if (value == 1) {
346 			cptkbd_data->middlebutton_state = 1;
347 		} else if (value == 0) {
348 			if (cptkbd_data->middlebutton_state == 1) {
349 				/* No scrolling inbetween, send middle-click */
350 				input_event(field->hidinput->input,
351 					EV_KEY, BTN_MIDDLE, 1);
352 				input_sync(field->hidinput->input);
353 				input_event(field->hidinput->input,
354 					EV_KEY, BTN_MIDDLE, 0);
355 				input_sync(field->hidinput->input);
356 			}
357 			cptkbd_data->middlebutton_state = 0;
358 		}
359 		return 1;
360 	}
361 
362 	return 0;
363 }
364 
365 static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
366 		struct hid_usage *usage, __s32 value)
367 {
368 	switch (hdev->product) {
369 	case USB_DEVICE_ID_LENOVO_CUSBKBD:
370 	case USB_DEVICE_ID_LENOVO_CBTKBD:
371 		return lenovo_event_cptkbd(hdev, field, usage, value);
372 	default:
373 		return 0;
374 	}
375 }
376 
377 static int lenovo_features_set_tpkbd(struct hid_device *hdev)
378 {
379 	struct hid_report *report;
380 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
381 
382 	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
383 
384 	report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
385 	report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
386 	report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
387 	report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
388 	report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
389 	report->field[2]->value[0] = data_pointer->sensitivity;
390 	report->field[3]->value[0] = data_pointer->press_speed;
391 
392 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
393 	return 0;
394 }
395 
396 static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
397 		struct device_attribute *attr,
398 		char *buf)
399 {
400 	struct hid_device *hdev = to_hid_device(dev);
401 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
402 
403 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
404 }
405 
406 static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
407 		struct device_attribute *attr,
408 		const char *buf,
409 		size_t count)
410 {
411 	struct hid_device *hdev = to_hid_device(dev);
412 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
413 	int value;
414 
415 	if (kstrtoint(buf, 10, &value))
416 		return -EINVAL;
417 	if (value < 0 || value > 1)
418 		return -EINVAL;
419 
420 	data_pointer->press_to_select = value;
421 	lenovo_features_set_tpkbd(hdev);
422 
423 	return count;
424 }
425 
426 static ssize_t attr_dragging_show_tpkbd(struct device *dev,
427 		struct device_attribute *attr,
428 		char *buf)
429 {
430 	struct hid_device *hdev = to_hid_device(dev);
431 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
432 
433 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
434 }
435 
436 static ssize_t attr_dragging_store_tpkbd(struct device *dev,
437 		struct device_attribute *attr,
438 		const char *buf,
439 		size_t count)
440 {
441 	struct hid_device *hdev = to_hid_device(dev);
442 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
443 	int value;
444 
445 	if (kstrtoint(buf, 10, &value))
446 		return -EINVAL;
447 	if (value < 0 || value > 1)
448 		return -EINVAL;
449 
450 	data_pointer->dragging = value;
451 	lenovo_features_set_tpkbd(hdev);
452 
453 	return count;
454 }
455 
456 static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
457 		struct device_attribute *attr,
458 		char *buf)
459 {
460 	struct hid_device *hdev = to_hid_device(dev);
461 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
462 
463 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
464 }
465 
466 static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
467 		struct device_attribute *attr,
468 		const char *buf,
469 		size_t count)
470 {
471 	struct hid_device *hdev = to_hid_device(dev);
472 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
473 	int value;
474 
475 	if (kstrtoint(buf, 10, &value))
476 		return -EINVAL;
477 	if (value < 0 || value > 1)
478 		return -EINVAL;
479 
480 	data_pointer->release_to_select = value;
481 	lenovo_features_set_tpkbd(hdev);
482 
483 	return count;
484 }
485 
486 static ssize_t attr_select_right_show_tpkbd(struct device *dev,
487 		struct device_attribute *attr,
488 		char *buf)
489 {
490 	struct hid_device *hdev = to_hid_device(dev);
491 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
492 
493 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
494 }
495 
496 static ssize_t attr_select_right_store_tpkbd(struct device *dev,
497 		struct device_attribute *attr,
498 		const char *buf,
499 		size_t count)
500 {
501 	struct hid_device *hdev = to_hid_device(dev);
502 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
503 	int value;
504 
505 	if (kstrtoint(buf, 10, &value))
506 		return -EINVAL;
507 	if (value < 0 || value > 1)
508 		return -EINVAL;
509 
510 	data_pointer->select_right = value;
511 	lenovo_features_set_tpkbd(hdev);
512 
513 	return count;
514 }
515 
516 static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
517 		struct device_attribute *attr,
518 		char *buf)
519 {
520 	struct hid_device *hdev = to_hid_device(dev);
521 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
522 
523 	return snprintf(buf, PAGE_SIZE, "%u\n",
524 		data_pointer->sensitivity);
525 }
526 
527 static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
528 		struct device_attribute *attr,
529 		const char *buf,
530 		size_t count)
531 {
532 	struct hid_device *hdev = to_hid_device(dev);
533 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
534 	int value;
535 
536 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
537 		return -EINVAL;
538 
539 	data_pointer->sensitivity = value;
540 	lenovo_features_set_tpkbd(hdev);
541 
542 	return count;
543 }
544 
545 static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
546 		struct device_attribute *attr,
547 		char *buf)
548 {
549 	struct hid_device *hdev = to_hid_device(dev);
550 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
551 
552 	return snprintf(buf, PAGE_SIZE, "%u\n",
553 		data_pointer->press_speed);
554 }
555 
556 static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
557 		struct device_attribute *attr,
558 		const char *buf,
559 		size_t count)
560 {
561 	struct hid_device *hdev = to_hid_device(dev);
562 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
563 	int value;
564 
565 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
566 		return -EINVAL;
567 
568 	data_pointer->press_speed = value;
569 	lenovo_features_set_tpkbd(hdev);
570 
571 	return count;
572 }
573 
574 static struct device_attribute dev_attr_press_to_select_tpkbd =
575 	__ATTR(press_to_select, S_IWUSR | S_IRUGO,
576 			attr_press_to_select_show_tpkbd,
577 			attr_press_to_select_store_tpkbd);
578 
579 static struct device_attribute dev_attr_dragging_tpkbd =
580 	__ATTR(dragging, S_IWUSR | S_IRUGO,
581 			attr_dragging_show_tpkbd,
582 			attr_dragging_store_tpkbd);
583 
584 static struct device_attribute dev_attr_release_to_select_tpkbd =
585 	__ATTR(release_to_select, S_IWUSR | S_IRUGO,
586 			attr_release_to_select_show_tpkbd,
587 			attr_release_to_select_store_tpkbd);
588 
589 static struct device_attribute dev_attr_select_right_tpkbd =
590 	__ATTR(select_right, S_IWUSR | S_IRUGO,
591 			attr_select_right_show_tpkbd,
592 			attr_select_right_store_tpkbd);
593 
594 static struct device_attribute dev_attr_sensitivity_tpkbd =
595 	__ATTR(sensitivity, S_IWUSR | S_IRUGO,
596 			attr_sensitivity_show_tpkbd,
597 			attr_sensitivity_store_tpkbd);
598 
599 static struct device_attribute dev_attr_press_speed_tpkbd =
600 	__ATTR(press_speed, S_IWUSR | S_IRUGO,
601 			attr_press_speed_show_tpkbd,
602 			attr_press_speed_store_tpkbd);
603 
604 static struct attribute *lenovo_attributes_tpkbd[] = {
605 	&dev_attr_press_to_select_tpkbd.attr,
606 	&dev_attr_dragging_tpkbd.attr,
607 	&dev_attr_release_to_select_tpkbd.attr,
608 	&dev_attr_select_right_tpkbd.attr,
609 	&dev_attr_sensitivity_tpkbd.attr,
610 	&dev_attr_press_speed_tpkbd.attr,
611 	NULL
612 };
613 
614 static const struct attribute_group lenovo_attr_group_tpkbd = {
615 	.attrs = lenovo_attributes_tpkbd,
616 };
617 
618 static enum led_brightness lenovo_led_brightness_get_tpkbd(
619 			struct led_classdev *led_cdev)
620 {
621 	struct device *dev = led_cdev->dev->parent;
622 	struct hid_device *hdev = to_hid_device(dev);
623 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
624 	int led_nr = 0;
625 
626 	if (led_cdev == &data_pointer->led_micmute)
627 		led_nr = 1;
628 
629 	return data_pointer->led_state & (1 << led_nr)
630 				? LED_FULL
631 				: LED_OFF;
632 }
633 
634 static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
635 			enum led_brightness value)
636 {
637 	struct device *dev = led_cdev->dev->parent;
638 	struct hid_device *hdev = to_hid_device(dev);
639 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
640 	struct hid_report *report;
641 	int led_nr = 0;
642 
643 	if (led_cdev == &data_pointer->led_micmute)
644 		led_nr = 1;
645 
646 	if (value == LED_OFF)
647 		data_pointer->led_state &= ~(1 << led_nr);
648 	else
649 		data_pointer->led_state |= 1 << led_nr;
650 
651 	report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
652 	report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
653 	report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
654 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
655 }
656 
657 static int lenovo_probe_tpkbd(struct hid_device *hdev)
658 {
659 	struct device *dev = &hdev->dev;
660 	struct lenovo_drvdata_tpkbd *data_pointer;
661 	size_t name_sz = strlen(dev_name(dev)) + 16;
662 	char *name_mute, *name_micmute;
663 	int i;
664 	int ret;
665 
666 	/*
667 	 * Only register extra settings against subdevice where input_mapping
668 	 * set drvdata to 1, i.e. the trackpoint.
669 	 */
670 	if (!hid_get_drvdata(hdev))
671 		return 0;
672 
673 	hid_set_drvdata(hdev, NULL);
674 
675 	/* Validate required reports. */
676 	for (i = 0; i < 4; i++) {
677 		if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
678 			return -ENODEV;
679 	}
680 	if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
681 		return -ENODEV;
682 
683 	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
684 	if (ret)
685 		hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
686 
687 	data_pointer = devm_kzalloc(&hdev->dev,
688 				    sizeof(struct lenovo_drvdata_tpkbd),
689 				    GFP_KERNEL);
690 	if (data_pointer == NULL) {
691 		hid_err(hdev, "Could not allocate memory for driver data\n");
692 		ret = -ENOMEM;
693 		goto err;
694 	}
695 
696 	// set same default values as windows driver
697 	data_pointer->sensitivity = 0xa0;
698 	data_pointer->press_speed = 0x38;
699 
700 	name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
701 	name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
702 	if (name_mute == NULL || name_micmute == NULL) {
703 		hid_err(hdev, "Could not allocate memory for led data\n");
704 		ret = -ENOMEM;
705 		goto err;
706 	}
707 	snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
708 	snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
709 
710 	hid_set_drvdata(hdev, data_pointer);
711 
712 	data_pointer->led_mute.name = name_mute;
713 	data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
714 	data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
715 	data_pointer->led_mute.dev = dev;
716 	led_classdev_register(dev, &data_pointer->led_mute);
717 
718 	data_pointer->led_micmute.name = name_micmute;
719 	data_pointer->led_micmute.brightness_get =
720 		lenovo_led_brightness_get_tpkbd;
721 	data_pointer->led_micmute.brightness_set =
722 		lenovo_led_brightness_set_tpkbd;
723 	data_pointer->led_micmute.dev = dev;
724 	led_classdev_register(dev, &data_pointer->led_micmute);
725 
726 	lenovo_features_set_tpkbd(hdev);
727 
728 	return 0;
729 err:
730 	sysfs_remove_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
731 	return ret;
732 }
733 
734 static int lenovo_probe_cptkbd(struct hid_device *hdev)
735 {
736 	int ret;
737 	struct lenovo_drvdata_cptkbd *cptkbd_data;
738 
739 	/* All the custom action happens on the USBMOUSE device for USB */
740 	if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
741 			&& hdev->type != HID_TYPE_USBMOUSE) {
742 		hid_dbg(hdev, "Ignoring keyboard half of device\n");
743 		return 0;
744 	}
745 
746 	cptkbd_data = devm_kzalloc(&hdev->dev,
747 					sizeof(*cptkbd_data),
748 					GFP_KERNEL);
749 	if (cptkbd_data == NULL) {
750 		hid_err(hdev, "can't alloc keyboard descriptor\n");
751 		return -ENOMEM;
752 	}
753 	hid_set_drvdata(hdev, cptkbd_data);
754 
755 	/*
756 	 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
757 	 * regular keys
758 	 */
759 	ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
760 	if (ret)
761 		hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
762 
763 	/* Switch middle button to native mode */
764 	ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
765 	if (ret)
766 		hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
767 
768 	/* Set keyboard settings to known state */
769 	cptkbd_data->middlebutton_state = 0;
770 	cptkbd_data->fn_lock = true;
771 	cptkbd_data->sensitivity = 0x05;
772 	lenovo_features_set_cptkbd(hdev);
773 
774 	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
775 	if (ret)
776 		hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
777 
778 	return 0;
779 }
780 
781 static int lenovo_probe(struct hid_device *hdev,
782 		const struct hid_device_id *id)
783 {
784 	int ret;
785 
786 	ret = hid_parse(hdev);
787 	if (ret) {
788 		hid_err(hdev, "hid_parse failed\n");
789 		goto err;
790 	}
791 
792 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
793 	if (ret) {
794 		hid_err(hdev, "hid_hw_start failed\n");
795 		goto err;
796 	}
797 
798 	switch (hdev->product) {
799 	case USB_DEVICE_ID_LENOVO_TPKBD:
800 		ret = lenovo_probe_tpkbd(hdev);
801 		break;
802 	case USB_DEVICE_ID_LENOVO_CUSBKBD:
803 	case USB_DEVICE_ID_LENOVO_CBTKBD:
804 		ret = lenovo_probe_cptkbd(hdev);
805 		break;
806 	default:
807 		ret = 0;
808 		break;
809 	}
810 	if (ret)
811 		goto err_hid;
812 
813 	return 0;
814 err_hid:
815 	hid_hw_stop(hdev);
816 err:
817 	return ret;
818 }
819 
820 static void lenovo_remove_tpkbd(struct hid_device *hdev)
821 {
822 	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
823 
824 	/*
825 	 * Only the trackpoint half of the keyboard has drvdata and stuff that
826 	 * needs unregistering.
827 	 */
828 	if (data_pointer == NULL)
829 		return;
830 
831 	sysfs_remove_group(&hdev->dev.kobj,
832 			&lenovo_attr_group_tpkbd);
833 
834 	led_classdev_unregister(&data_pointer->led_micmute);
835 	led_classdev_unregister(&data_pointer->led_mute);
836 
837 	hid_set_drvdata(hdev, NULL);
838 }
839 
840 static void lenovo_remove_cptkbd(struct hid_device *hdev)
841 {
842 	sysfs_remove_group(&hdev->dev.kobj,
843 			&lenovo_attr_group_cptkbd);
844 }
845 
846 static void lenovo_remove(struct hid_device *hdev)
847 {
848 	switch (hdev->product) {
849 	case USB_DEVICE_ID_LENOVO_TPKBD:
850 		lenovo_remove_tpkbd(hdev);
851 		break;
852 	case USB_DEVICE_ID_LENOVO_CUSBKBD:
853 	case USB_DEVICE_ID_LENOVO_CBTKBD:
854 		lenovo_remove_cptkbd(hdev);
855 		break;
856 	}
857 
858 	hid_hw_stop(hdev);
859 }
860 
861 static int lenovo_input_configured(struct hid_device *hdev,
862 		struct hid_input *hi)
863 {
864 	switch (hdev->product) {
865 		case USB_DEVICE_ID_LENOVO_TPKBD:
866 		case USB_DEVICE_ID_LENOVO_CUSBKBD:
867 		case USB_DEVICE_ID_LENOVO_CBTKBD:
868 			if (test_bit(EV_REL, hi->input->evbit)) {
869 				/* set only for trackpoint device */
870 				__set_bit(INPUT_PROP_POINTER, hi->input->propbit);
871 				__set_bit(INPUT_PROP_POINTING_STICK,
872 						hi->input->propbit);
873 			}
874 			break;
875 	}
876 
877 	return 0;
878 }
879 
880 
881 static const struct hid_device_id lenovo_devices[] = {
882 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
883 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
884 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
885 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
886 	{ }
887 };
888 
889 MODULE_DEVICE_TABLE(hid, lenovo_devices);
890 
891 static struct hid_driver lenovo_driver = {
892 	.name = "lenovo",
893 	.id_table = lenovo_devices,
894 	.input_configured = lenovo_input_configured,
895 	.input_mapping = lenovo_input_mapping,
896 	.probe = lenovo_probe,
897 	.remove = lenovo_remove,
898 	.raw_event = lenovo_raw_event,
899 	.event = lenovo_event,
900 	.report_fixup = lenovo_report_fixup,
901 };
902 module_hid_driver(lenovo_driver);
903 
904 MODULE_LICENSE("GPL");
905