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 :
@@ -363,10 +493,12 @@ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
363493
364494 switch (hdev -> product ) {
365495 case USB_DEVICE_ID_LENOVO_CUSBKBD :
496+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
366497 ret = hid_hw_raw_request (hdev , 0x13 , buf , 3 ,
367498 HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
368499 break ;
369500 case USB_DEVICE_ID_LENOVO_CBTKBD :
501+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
370502 ret = hid_hw_output_report (hdev , buf , 3 );
371503 break ;
372504 default :
@@ -422,6 +554,8 @@ static ssize_t attr_fn_lock_store(struct device *dev,
422554 switch (hdev -> product ) {
423555 case USB_DEVICE_ID_LENOVO_CUSBKBD :
424556 case USB_DEVICE_ID_LENOVO_CBTKBD :
557+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
558+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
425559 lenovo_features_set_cptkbd (hdev );
426560 break ;
427561 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -568,6 +702,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
568702 switch (hdev -> product ) {
569703 case USB_DEVICE_ID_LENOVO_CUSBKBD :
570704 case USB_DEVICE_ID_LENOVO_CBTKBD :
705+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
706+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
571707 return lenovo_event_cptkbd (hdev , field , usage , value );
572708 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
573709 case USB_DEVICE_ID_LENOVO_X1_TAB :
@@ -960,8 +1096,9 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
9601096 struct lenovo_drvdata * cptkbd_data ;
9611097
9621098 /* 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 ) {
1099+ if (((hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD ) ||
1100+ (hdev -> product == USB_DEVICE_ID_LENOVO_TPIIUSBKBD )) &&
1101+ hdev -> type != HID_TYPE_USBMOUSE ) {
9651102 hid_dbg (hdev , "Ignoring keyboard half of device\n" );
9661103 return 0 ;
9671104 }
@@ -977,11 +1114,14 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
9771114
9781115 /*
9791116 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
980- * regular keys
1117+ * regular keys (Compact only)
9811118 */
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 );
1119+ if (hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD ||
1120+ hdev -> product == USB_DEVICE_ID_LENOVO_CBTKBD ) {
1121+ ret = lenovo_send_cmd_cptkbd (hdev , 0x01 , 0x03 );
1122+ if (ret )
1123+ hid_warn (hdev , "Failed to switch F7/9/11 mode: %d\n" , ret );
1124+ }
9851125
9861126 /* Switch middle button to native mode */
9871127 ret = lenovo_send_cmd_cptkbd (hdev , 0x09 , 0x01 );
@@ -1088,6 +1228,8 @@ static int lenovo_probe(struct hid_device *hdev,
10881228 break ;
10891229 case USB_DEVICE_ID_LENOVO_CUSBKBD :
10901230 case USB_DEVICE_ID_LENOVO_CBTKBD :
1231+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1232+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
10911233 ret = lenovo_probe_cptkbd (hdev );
10921234 break ;
10931235 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -1154,6 +1296,8 @@ static void lenovo_remove(struct hid_device *hdev)
11541296 break ;
11551297 case USB_DEVICE_ID_LENOVO_CUSBKBD :
11561298 case USB_DEVICE_ID_LENOVO_CBTKBD :
1299+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1300+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
11571301 lenovo_remove_cptkbd (hdev );
11581302 break ;
11591303 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
@@ -1172,6 +1316,8 @@ static int lenovo_input_configured(struct hid_device *hdev,
11721316 case USB_DEVICE_ID_LENOVO_TPKBD :
11731317 case USB_DEVICE_ID_LENOVO_CUSBKBD :
11741318 case USB_DEVICE_ID_LENOVO_CBTKBD :
1319+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1320+ case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
11751321 if (test_bit (EV_REL , hi -> input -> evbit )) {
11761322 /* set only for trackpoint device */
11771323 __set_bit (INPUT_PROP_POINTER , hi -> input -> propbit );
@@ -1188,7 +1334,9 @@ static int lenovo_input_configured(struct hid_device *hdev,
11881334static const struct hid_device_id lenovo_devices [] = {
11891335 { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPKBD ) },
11901336 { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_CUSBKBD ) },
1337+ { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPIIUSBKBD ) },
11911338 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_CBTKBD ) },
1339+ { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPIIBTKBD ) },
11921340 { HID_USB_DEVICE (USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_TPPRODOCK ) },
11931341 { HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_III ) },
11941342 { HID_USB_DEVICE (USB_VENDOR_ID_IBM , USB_DEVICE_ID_IBM_SCROLLPOINT_PRO ) },
0 commit comments