4
4
* - ThinkPad USB Keyboard with TrackPoint (tpkbd)
5
5
* - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
6
6
* - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
7
+ * - ThinkPad TrackPoint Keyboard II USB/Bluetooth (cptkbd/tpIIkbd)
7
8
*
8
9
* Copyright (c) 2012 Bernhard Seibold
9
10
* Copyright (c) 2014 Jamie Lentin <[email protected] >
@@ -110,6 +111,23 @@ static const __u8 lenovo_pro_dock_need_fixup_collection[] = {
110
111
0x2a , 0xff , 0xff , /* Usage Maximum (65535) */
111
112
};
112
113
114
+ /* Broken ThinkPad TrackPoint II collection (Bluetooth mode) */
115
+ static const __u8 lenovo_tpIIbtkbd_need_fixup_collection [] = {
116
+ 0x06 , 0x00 , 0xFF , /* Usage Page (Vendor Defined 0xFF00) */
117
+ 0x09 , 0x01 , /* Usage (0x01) */
118
+ 0xA1 , 0x01 , /* Collection (Application) */
119
+ 0x85 , 0x05 , /* Report ID (5) */
120
+ 0x1A , 0xF1 , 0x00 , /* Usage Minimum (0xF1) */
121
+ 0x2A , 0xFC , 0x00 , /* Usage Maximum (0xFC) */
122
+ 0x15 , 0x00 , /* Logical Minimum (0) */
123
+ 0x25 , 0x01 , /* Logical Maximum (1) */
124
+ 0x75 , 0x01 , /* Report Size (1) */
125
+ 0x95 , 0x0D , /* Report Count (13) */
126
+ 0x81 , 0x02 , /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */
127
+ 0x95 , 0x03 , /* Report Count (3) */
128
+ 0x81 , 0x01 , /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */
129
+ };
130
+
113
131
static __u8 * lenovo_report_fixup (struct hid_device * hdev , __u8 * rdesc ,
114
132
unsigned int * rsize )
115
133
{
@@ -126,6 +144,19 @@ static __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc,
126
144
rdesc [152 ] = 0x00 ;
127
145
}
128
146
break ;
147
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
148
+ if (* rsize >= 263 &&
149
+ memcmp (& rdesc [234 ], lenovo_tpIIbtkbd_need_fixup_collection ,
150
+ sizeof (lenovo_tpIIbtkbd_need_fixup_collection )) == 0 ) {
151
+ rdesc [244 ] = 0x00 ; /* usage minimum = 0x00 */
152
+ rdesc [247 ] = 0xff ; /* usage maximum = 0xff */
153
+ rdesc [252 ] = 0xff ; /* logical maximum = 0xff */
154
+ rdesc [254 ] = 0x08 ; /* report size = 0x08 */
155
+ rdesc [256 ] = 0x01 ; /* report count = 0x01 */
156
+ rdesc [258 ] = 0x00 ; /* input = 0x00 */
157
+ rdesc [260 ] = 0x01 ; /* report count (2) = 0x01 */
158
+ }
159
+ break ;
129
160
}
130
161
return rdesc ;
131
162
}
@@ -217,6 +248,101 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
217
248
return 0 ;
218
249
}
219
250
251
+ static int lenovo_input_mapping_tpIIkbd (struct hid_device * hdev ,
252
+ struct hid_input * hi , struct hid_field * field ,
253
+ struct hid_usage * usage , unsigned long * * bit , int * max )
254
+ {
255
+ /*
256
+ * 0xff0a0000 = USB, HID_UP_MSVENDOR = BT.
257
+ *
258
+ * In BT mode, there are two HID_UP_MSVENDOR pages.
259
+ * Use only the page that contains report ID == 5.
260
+ */
261
+ if (((usage -> hid & HID_USAGE_PAGE ) == 0xff0a0000 ||
262
+ (usage -> hid & HID_USAGE_PAGE ) == HID_UP_MSVENDOR ) &&
263
+ field -> report -> id == 5 ) {
264
+ switch (usage -> hid & HID_USAGE ) {
265
+ case 0x00bb : /* Fn-F4: Mic mute */
266
+ map_key_clear (LENOVO_KEY_MICMUTE );
267
+ return 1 ;
268
+ case 0x00c3 : /* Fn-F5: Brightness down */
269
+ map_key_clear (KEY_BRIGHTNESSDOWN );
270
+ return 1 ;
271
+ case 0x00c4 : /* Fn-F6: Brightness up */
272
+ map_key_clear (KEY_BRIGHTNESSUP );
273
+ return 1 ;
274
+ case 0x00c1 : /* Fn-F8: Notification center */
275
+ map_key_clear (KEY_NOTIFICATION_CENTER );
276
+ return 1 ;
277
+ case 0x00bc : /* Fn-F9: Control panel */
278
+ map_key_clear (KEY_CONFIG );
279
+ return 1 ;
280
+ case 0x00b6 : /* Fn-F10: Bluetooth */
281
+ map_key_clear (KEY_BLUETOOTH );
282
+ return 1 ;
283
+ case 0x00b7 : /* Fn-F11: Keyboard config */
284
+ map_key_clear (KEY_KEYBOARD );
285
+ return 1 ;
286
+ case 0x00b8 : /* Fn-F12: User function */
287
+ map_key_clear (KEY_PROG1 );
288
+ return 1 ;
289
+ case 0x00b9 : /* Fn-PrtSc: Snipping tool */
290
+ map_key_clear (KEY_SELECTIVE_SCREENSHOT );
291
+ return 1 ;
292
+ case 0x00b5 : /* Fn-Esc: Fn-lock toggle */
293
+ map_key_clear (KEY_FN_ESC );
294
+ return 1 ;
295
+ }
296
+ }
297
+
298
+ if ((usage -> hid & HID_USAGE_PAGE ) == 0xffa00000 ) {
299
+ switch (usage -> hid & HID_USAGE ) {
300
+ case 0x00fb : /* Middle mouse (in native USB mode) */
301
+ map_key_clear (BTN_MIDDLE );
302
+ return 1 ;
303
+ }
304
+ }
305
+
306
+ if ((usage -> hid & HID_USAGE_PAGE ) == HID_UP_MSVENDOR &&
307
+ field -> report -> id == 21 ) {
308
+ switch (usage -> hid & HID_USAGE ) {
309
+ case 0x0004 : /* Middle mouse (in native Bluetooth mode) */
310
+ map_key_clear (BTN_MIDDLE );
311
+ return 1 ;
312
+ }
313
+ }
314
+
315
+ /* Compatibility middle/wheel mappings should be ignored */
316
+ if (usage -> hid == HID_GD_WHEEL )
317
+ return -1 ;
318
+ if ((usage -> hid & HID_USAGE_PAGE ) == HID_UP_BUTTON &&
319
+ (usage -> hid & HID_USAGE ) == 0x003 )
320
+ return -1 ;
321
+ if ((usage -> hid & HID_USAGE_PAGE ) == HID_UP_CONSUMER &&
322
+ (usage -> hid & HID_USAGE ) == 0x238 )
323
+ return -1 ;
324
+
325
+ /* Map wheel emulation reports: 0xff10 */
326
+ if ((usage -> hid & HID_USAGE_PAGE ) == 0xff100000 ) {
327
+ field -> flags |= HID_MAIN_ITEM_RELATIVE | HID_MAIN_ITEM_VARIABLE ;
328
+ field -> logical_minimum = -127 ;
329
+ field -> logical_maximum = 127 ;
330
+
331
+ switch (usage -> hid & HID_USAGE ) {
332
+ case 0x0000 :
333
+ hid_map_usage (hi , usage , bit , max , EV_REL , REL_HWHEEL );
334
+ return 1 ;
335
+ case 0x0001 :
336
+ hid_map_usage (hi , usage , bit , max , EV_REL , REL_WHEEL );
337
+ return 1 ;
338
+ default :
339
+ return -1 ;
340
+ }
341
+ }
342
+
343
+ return 0 ;
344
+ }
345
+
220
346
static int lenovo_input_mapping_scrollpoint (struct hid_device * hdev ,
221
347
struct hid_input * hi , struct hid_field * field ,
222
348
struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -326,6 +452,10 @@ static int lenovo_input_mapping(struct hid_device *hdev,
326
452
case USB_DEVICE_ID_LENOVO_CBTKBD :
327
453
return lenovo_input_mapping_cptkbd (hdev , hi , field ,
328
454
usage , bit , max );
455
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
456
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
457
+ return lenovo_input_mapping_tpIIkbd (hdev , hi , field ,
458
+ usage , bit , max );
329
459
case USB_DEVICE_ID_IBM_SCROLLPOINT_III :
330
460
case USB_DEVICE_ID_IBM_SCROLLPOINT_PRO :
331
461
case USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL :
@@ -357,16 +487,23 @@ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
357
487
if (!buf )
358
488
return - ENOMEM ;
359
489
490
+ /*
491
+ * Feature report 0x13 is used for USB,
492
+ * output report 0x18 is used for Bluetooth.
493
+ * buf[0] is ignored by hid_hw_raw_request.
494
+ */
360
495
buf [0 ] = 0x18 ;
361
496
buf [1 ] = byte2 ;
362
497
buf [2 ] = byte3 ;
363
498
364
499
switch (hdev -> product ) {
365
500
case USB_DEVICE_ID_LENOVO_CUSBKBD :
501
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
366
502
ret = hid_hw_raw_request (hdev , 0x13 , buf , 3 ,
367
503
HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
368
504
break ;
369
505
case USB_DEVICE_ID_LENOVO_CBTKBD :
506
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
370
507
ret = hid_hw_output_report (hdev , buf , 3 );
371
508
break ;
372
509
default :
@@ -422,6 +559,8 @@ static ssize_t attr_fn_lock_store(struct device *dev,
422
559
switch (hdev -> product ) {
423
560
case USB_DEVICE_ID_LENOVO_CUSBKBD :
424
561
case USB_DEVICE_ID_LENOVO_CBTKBD :
562
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
563
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
425
564
lenovo_features_set_cptkbd (hdev );
426
565
break ;
427
566
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -556,6 +695,15 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
556
695
return 1 ;
557
696
}
558
697
698
+ if (usage -> type == EV_KEY && usage -> code == KEY_FN_ESC && value == 1 ) {
699
+ /*
700
+ * The user has toggled the Fn-lock state. Toggle our own
701
+ * cached value of it and sync our value to the keyboard to
702
+ * ensure things are in sync (the syncing should be a no-op).
703
+ */
704
+ cptkbd_data -> fn_lock = !cptkbd_data -> fn_lock ;
705
+ }
706
+
559
707
return 0 ;
560
708
}
561
709
@@ -568,6 +716,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
568
716
switch (hdev -> product ) {
569
717
case USB_DEVICE_ID_LENOVO_CUSBKBD :
570
718
case USB_DEVICE_ID_LENOVO_CBTKBD :
719
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
720
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
571
721
return lenovo_event_cptkbd (hdev , field , usage , value );
572
722
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
573
723
case USB_DEVICE_ID_LENOVO_X1_TAB :
@@ -960,8 +1110,9 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
960
1110
struct lenovo_drvdata * cptkbd_data ;
961
1111
962
1112
/* All the custom action happens on the USBMOUSE device for USB */
963
- if (hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD
964
- && hdev -> type != HID_TYPE_USBMOUSE ) {
1113
+ if (((hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD ) ||
1114
+ (hdev -> product == USB_DEVICE_ID_LENOVO_TPIIUSBKBD )) &&
1115
+ hdev -> type != HID_TYPE_USBMOUSE ) {
965
1116
hid_dbg (hdev , "Ignoring keyboard half of device\n" );
966
1117
return 0 ;
967
1118
}
@@ -977,11 +1128,14 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
977
1128
978
1129
/*
979
1130
* Tell the keyboard a driver understands it, and turn F7, F9, F11 into
980
- * regular keys
1131
+ * regular keys (Compact only)
981
1132
*/
982
- ret = lenovo_send_cmd_cptkbd (hdev , 0x01 , 0x03 );
983
- if (ret )
984
- hid_warn (hdev , "Failed to switch F7/9/11 mode: %d\n" , ret );
1133
+ if (hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD ||
1134
+ hdev -> product == USB_DEVICE_ID_LENOVO_CBTKBD ) {
1135
+ ret = lenovo_send_cmd_cptkbd (hdev , 0x01 , 0x03 );
1136
+ if (ret )
1137
+ hid_warn (hdev , "Failed to switch F7/9/11 mode: %d\n" , ret );
1138
+ }
985
1139
986
1140
/* Switch middle button to native mode */
987
1141
ret = lenovo_send_cmd_cptkbd (hdev , 0x09 , 0x01 );
@@ -1088,6 +1242,8 @@ static int lenovo_probe(struct hid_device *hdev,
1088
1242
break ;
1089
1243
case USB_DEVICE_ID_LENOVO_CUSBKBD :
1090
1244
case USB_DEVICE_ID_LENOVO_CBTKBD :
1245
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1246
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1091
1247
ret = lenovo_probe_cptkbd (hdev );
1092
1248
break ;
1093
1249
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -1154,6 +1310,8 @@ static void lenovo_remove(struct hid_device *hdev)
1154
1310
break ;
1155
1311
case USB_DEVICE_ID_LENOVO_CUSBKBD :
1156
1312
case USB_DEVICE_ID_LENOVO_CBTKBD :
1313
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1314
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1157
1315
lenovo_remove_cptkbd (hdev );
1158
1316
break ;
1159
1317
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -1172,6 +1330,8 @@ static int lenovo_input_configured(struct hid_device *hdev,
1172
1330
case USB_DEVICE_ID_LENOVO_TPKBD :
1173
1331
case USB_DEVICE_ID_LENOVO_CUSBKBD :
1174
1332
case USB_DEVICE_ID_LENOVO_CBTKBD :
1333
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1334
+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1175
1335
if (test_bit (EV_REL , hi -> input -> evbit )) {
1176
1336
/* set only for trackpoint device */
1177
1337
__set_bit (INPUT_PROP_POINTER , hi -> input -> propbit );
@@ -1188,7 +1348,9 @@ static int lenovo_input_configured(struct hid_device *hdev,
1188
1348
static const struct hid_device_id lenovo_devices [] = {
1189
1349
{ HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPKBD ) },
1190
1350
{ HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_CUSBKBD ) },
1351
+ { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPIIUSBKBD ) },
1191
1352
{ HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_CBTKBD ) },
1353
+ { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPIIBTKBD ) },
1192
1354
{ HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPPRODOCK ) },
1193
1355
{ HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_III ) },
1194
1356
{ HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_PRO ) },
0 commit comments