44 * - ThinkPad USB Keyboard with TrackPoint (tpkbd)
55 * - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
66 * - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
7+ * - ThinkPad TrackPoint Keyboard II USB/Bluetooth (cptkbd/tpIIkbd)
78 *
89 * Copyright (c) 2012 Bernhard Seibold
910 * Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk>
@@ -110,6 +111,23 @@ static const __u8 lenovo_pro_dock_need_fixup_collection[] = {
110111 0x2a , 0xff , 0xff , /* Usage Maximum (65535) */
111112};
112113
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+
113131static __u8 * lenovo_report_fixup (struct hid_device * hdev , __u8 * rdesc ,
114132 unsigned int * rsize )
115133{
@@ -126,6 +144,19 @@ static __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc,
126144 rdesc [152 ] = 0x00 ;
127145 }
128146 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 ;
129160 }
130161 return rdesc ;
131162}
@@ -217,6 +248,101 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
217248 return 0 ;
218249}
219250
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+
220346static int lenovo_input_mapping_scrollpoint (struct hid_device * hdev ,
221347 struct hid_input * hi , struct hid_field * field ,
222348 struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -326,6 +452,10 @@ static int lenovo_input_mapping(struct hid_device *hdev,
326452 case USB_DEVICE_ID_LENOVO_CBTKBD :
327453 return lenovo_input_mapping_cptkbd (hdev , hi , field ,
328454 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 );
329459 case USB_DEVICE_ID_IBM_SCROLLPOINT_III :
330460 case USB_DEVICE_ID_IBM_SCROLLPOINT_PRO :
331461 case USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL :
@@ -357,16 +487,23 @@ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
357487 if (!buf )
358488 return - ENOMEM ;
359489
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+ */
360495 buf [0 ] = 0x18 ;
361496 buf [1 ] = byte2 ;
362497 buf [2 ] = byte3 ;
363498
364499 switch (hdev -> product ) {
365500 case USB_DEVICE_ID_LENOVO_CUSBKBD :
501+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
366502 ret = hid_hw_raw_request (hdev , 0x13 , buf , 3 ,
367503 HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
368504 break ;
369505 case USB_DEVICE_ID_LENOVO_CBTKBD :
506+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
370507 ret = hid_hw_output_report (hdev , buf , 3 );
371508 break ;
372509 default :
@@ -422,6 +559,8 @@ static ssize_t attr_fn_lock_store(struct device *dev,
422559 switch (hdev -> product ) {
423560 case USB_DEVICE_ID_LENOVO_CUSBKBD :
424561 case USB_DEVICE_ID_LENOVO_CBTKBD :
562+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
563+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
425564 lenovo_features_set_cptkbd (hdev );
426565 break ;
427566 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -556,6 +695,15 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
556695 return 1 ;
557696 }
558697
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+
559707 return 0 ;
560708}
561709
@@ -568,6 +716,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
568716 switch (hdev -> product ) {
569717 case USB_DEVICE_ID_LENOVO_CUSBKBD :
570718 case USB_DEVICE_ID_LENOVO_CBTKBD :
719+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
720+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
571721 return lenovo_event_cptkbd (hdev , field , usage , value );
572722 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
573723 case USB_DEVICE_ID_LENOVO_X1_TAB :
@@ -960,8 +1110,9 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
9601110 struct lenovo_drvdata * cptkbd_data ;
9611111
9621112 /* 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 ) {
9651116 hid_dbg (hdev , "Ignoring keyboard half of device\n" );
9661117 return 0 ;
9671118 }
@@ -977,11 +1128,14 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
9771128
9781129 /*
9791130 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
980- * regular keys
1131+ * regular keys (Compact only)
9811132 */
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+ }
9851139
9861140 /* Switch middle button to native mode */
9871141 ret = lenovo_send_cmd_cptkbd (hdev , 0x09 , 0x01 );
@@ -1088,6 +1242,8 @@ static int lenovo_probe(struct hid_device *hdev,
10881242 break ;
10891243 case USB_DEVICE_ID_LENOVO_CUSBKBD :
10901244 case USB_DEVICE_ID_LENOVO_CBTKBD :
1245+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1246+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
10911247 ret = lenovo_probe_cptkbd (hdev );
10921248 break ;
10931249 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -1154,6 +1310,8 @@ static void lenovo_remove(struct hid_device *hdev)
11541310 break ;
11551311 case USB_DEVICE_ID_LENOVO_CUSBKBD :
11561312 case USB_DEVICE_ID_LENOVO_CBTKBD :
1313+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1314+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
11571315 lenovo_remove_cptkbd (hdev );
11581316 break ;
11591317 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -1172,6 +1330,8 @@ static int lenovo_input_configured(struct hid_device *hdev,
11721330 case USB_DEVICE_ID_LENOVO_TPKBD :
11731331 case USB_DEVICE_ID_LENOVO_CUSBKBD :
11741332 case USB_DEVICE_ID_LENOVO_CBTKBD :
1333+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1334+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
11751335 if (test_bit (EV_REL , hi -> input -> evbit )) {
11761336 /* set only for trackpoint device */
11771337 __set_bit (INPUT_PROP_POINTER , hi -> input -> propbit );
@@ -1188,7 +1348,9 @@ static int lenovo_input_configured(struct hid_device *hdev,
11881348static const struct hid_device_id lenovo_devices [] = {
11891349 { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPKBD ) },
11901350 { 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 ) },
11911352 { 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 ) },
11921354 { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPPRODOCK ) },
11931355 { HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_III ) },
11941356 { HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_PRO ) },
0 commit comments