]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/hid/hid-lenovo.c
drm/i915: Fix scaler init during CRTC HW state readout
[karo-tx-linux.git] / drivers / hid / hid-lenovo.c
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");