33
33
#include "hid-ids.h"
34
34
35
35
struct lenovo_drvdata {
36
+ u8 led_report [3 ]; /* Must be first for proper alignment */
36
37
int led_state ;
38
+ struct mutex led_report_mutex ;
37
39
struct led_classdev led_mute ;
38
40
struct led_classdev led_micmute ;
39
41
int press_to_select ;
@@ -48,6 +50,34 @@ struct lenovo_drvdata {
48
50
49
51
#define map_key_clear (c ) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
50
52
53
+ #define TP10UBKBD_LED_OUTPUT_REPORT 9
54
+
55
+ #define TP10UBKBD_FN_LOCK_LED 0x54
56
+ #define TP10UBKBD_MUTE_LED 0x64
57
+ #define TP10UBKBD_MICMUTE_LED 0x74
58
+
59
+ #define TP10UBKBD_LED_OFF 1
60
+ #define TP10UBKBD_LED_ON 2
61
+
62
+ static void lenovo_led_set_tp10ubkbd (struct hid_device * hdev , u8 led_code ,
63
+ enum led_brightness value )
64
+ {
65
+ struct lenovo_drvdata * data = hid_get_drvdata (hdev );
66
+ int ret ;
67
+
68
+ mutex_lock (& data -> led_report_mutex );
69
+
70
+ data -> led_report [0 ] = TP10UBKBD_LED_OUTPUT_REPORT ;
71
+ data -> led_report [1 ] = led_code ;
72
+ data -> led_report [2 ] = value ? TP10UBKBD_LED_ON : TP10UBKBD_LED_OFF ;
73
+ ret = hid_hw_raw_request (hdev , data -> led_report [0 ], data -> led_report , 3 ,
74
+ HID_OUTPUT_REPORT , HID_REQ_SET_REPORT );
75
+ if (ret )
76
+ hid_err (hdev , "Set LED output report error: %d\n" , ret );
77
+
78
+ mutex_unlock (& data -> led_report_mutex );
79
+ }
80
+
51
81
static const __u8 lenovo_pro_dock_need_fixup_collection [] = {
52
82
0x05 , 0x88 , /* Usage Page (Vendor Usage Page 0x88) */
53
83
0x09 , 0x01 , /* Usage (Vendor Usage 0x01) */
@@ -175,6 +205,37 @@ static int lenovo_input_mapping_scrollpoint(struct hid_device *hdev,
175
205
return 0 ;
176
206
}
177
207
208
+ static int lenovo_input_mapping_tp10_ultrabook_kbd (struct hid_device * hdev ,
209
+ struct hid_input * hi , struct hid_field * field ,
210
+ struct hid_usage * usage , unsigned long * * bit , int * max )
211
+ {
212
+ /*
213
+ * The ThinkPad 10 Ultrabook Keyboard uses 0x000c0001 usage for
214
+ * a bunch of keys which have no standard consumer page code.
215
+ */
216
+ if (usage -> hid == 0x000c0001 ) {
217
+ switch (usage -> usage_index ) {
218
+ case 8 : /* Fn-Esc: Fn-lock toggle */
219
+ map_key_clear (KEY_FN_ESC );
220
+ return 1 ;
221
+ case 9 : /* Fn-F4: Mic mute */
222
+ map_key_clear (KEY_MICMUTE );
223
+ return 1 ;
224
+ case 10 : /* Fn-F7: Control panel */
225
+ map_key_clear (KEY_CONFIG );
226
+ return 1 ;
227
+ case 11 : /* Fn-F8: Search (magnifier glass) */
228
+ map_key_clear (KEY_SEARCH );
229
+ return 1 ;
230
+ case 12 : /* Fn-F10: Open My computer (6 boxes) */
231
+ map_key_clear (KEY_FILE );
232
+ return 1 ;
233
+ }
234
+ }
235
+
236
+ return 0 ;
237
+ }
238
+
178
239
static int lenovo_input_mapping (struct hid_device * hdev ,
179
240
struct hid_input * hi , struct hid_field * field ,
180
241
struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -195,6 +256,9 @@ static int lenovo_input_mapping(struct hid_device *hdev,
195
256
case USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL :
196
257
return lenovo_input_mapping_scrollpoint (hdev , hi , field ,
197
258
usage , bit , max );
259
+ case USB_DEVICE_ID_LENOVO_TP10UBKBD :
260
+ return lenovo_input_mapping_tp10_ultrabook_kbd (hdev , hi , field ,
261
+ usage , bit , max );
198
262
default :
199
263
return 0 ;
200
264
}
@@ -677,6 +741,7 @@ static void lenovo_led_brightness_set(struct led_classdev *led_cdev,
677
741
struct device * dev = led_cdev -> dev -> parent ;
678
742
struct hid_device * hdev = to_hid_device (dev );
679
743
struct lenovo_drvdata * data_pointer = hid_get_drvdata (hdev );
744
+ u8 tp10ubkbd_led [] = { TP10UBKBD_MUTE_LED , TP10UBKBD_MICMUTE_LED };
680
745
int led_nr = 0 ;
681
746
682
747
if (led_cdev == & data_pointer -> led_micmute )
@@ -691,6 +756,9 @@ static void lenovo_led_brightness_set(struct led_classdev *led_cdev,
691
756
case USB_DEVICE_ID_LENOVO_TPKBD :
692
757
lenovo_led_set_tpkbd (hdev );
693
758
break ;
759
+ case USB_DEVICE_ID_LENOVO_TP10UBKBD :
760
+ lenovo_led_set_tp10ubkbd (hdev , tp10ubkbd_led [led_nr ], value );
761
+ break ;
694
762
}
695
763
}
696
764
@@ -831,6 +899,25 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
831
899
return 0 ;
832
900
}
833
901
902
+ static int lenovo_probe_tp10ubkbd (struct hid_device * hdev )
903
+ {
904
+ struct lenovo_drvdata * data ;
905
+
906
+ /* All the custom action happens on the USBMOUSE device for USB */
907
+ if (hdev -> type != HID_TYPE_USBMOUSE )
908
+ return 0 ;
909
+
910
+ data = devm_kzalloc (& hdev -> dev , sizeof (* data ), GFP_KERNEL );
911
+ if (!data )
912
+ return - ENOMEM ;
913
+
914
+ mutex_init (& data -> led_report_mutex );
915
+
916
+ hid_set_drvdata (hdev , data );
917
+
918
+ return lenovo_register_leds (hdev );
919
+ }
920
+
834
921
static int lenovo_probe (struct hid_device * hdev ,
835
922
const struct hid_device_id * id )
836
923
{
@@ -856,6 +943,9 @@ static int lenovo_probe(struct hid_device *hdev,
856
943
case USB_DEVICE_ID_LENOVO_CBTKBD :
857
944
ret = lenovo_probe_cptkbd (hdev );
858
945
break ;
946
+ case USB_DEVICE_ID_LENOVO_TP10UBKBD :
947
+ ret = lenovo_probe_tp10ubkbd (hdev );
948
+ break ;
859
949
default :
860
950
ret = 0 ;
861
951
break ;
@@ -894,6 +984,17 @@ static void lenovo_remove_cptkbd(struct hid_device *hdev)
894
984
& lenovo_attr_group_cptkbd );
895
985
}
896
986
987
+ static void lenovo_remove_tp10ubkbd (struct hid_device * hdev )
988
+ {
989
+ struct lenovo_drvdata * data = hid_get_drvdata (hdev );
990
+
991
+ if (data == NULL )
992
+ return ;
993
+
994
+ led_classdev_unregister (& data -> led_micmute );
995
+ led_classdev_unregister (& data -> led_mute );
996
+ }
997
+
897
998
static void lenovo_remove (struct hid_device * hdev )
898
999
{
899
1000
switch (hdev -> product ) {
@@ -904,6 +1005,9 @@ static void lenovo_remove(struct hid_device *hdev)
904
1005
case USB_DEVICE_ID_LENOVO_CBTKBD :
905
1006
lenovo_remove_cptkbd (hdev );
906
1007
break ;
1008
+ case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1009
+ lenovo_remove_tp10ubkbd (hdev );
1010
+ break ;
907
1011
}
908
1012
909
1013
hid_hw_stop (hdev );
@@ -940,6 +1044,7 @@ static const struct hid_device_id lenovo_devices[] = {
940
1044
{ HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL ) },
941
1045
{ HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO ) },
942
1046
{ HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL ) },
1047
+ { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TP10UBKBD ) },
943
1048
{ }
944
1049
};
945
1050
0 commit comments