Skip to content

Commit 94eefa2

Browse files
lentinjJiri Kosina
authored andcommitted
HID: lenovo: Use native middle-button mode for compact keyboards
By default the middle button is in a compatibility mode, and generates standard wheel events when dragging with the middle trackpoint button. Unfortunately this is buggy: * The middle button comes up before starting wheel events, causing a middle click on whatever the mouse cursor was sitting on * The USB keyboard always generates the "native" horizontal wheel event, regardless of mode. Instead, enable the "native" mode the Windows driver uses, and add support for the custom events this generates. This fixes the USB keyboard wheel events, and the middle-click up event comes after the wheel events. Signed-off-by: Jamie Lentin <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent e3cb0ac commit 94eefa2

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

drivers/hid/hid-lenovo.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,38 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
9292
case 0x00fa: /* Fn-Esc: Fn-lock toggle */
9393
map_key_clear(KEY_FN_ESC);
9494
return 1;
95+
case 0x00fb: /* Middle mouse button (in native mode) */
96+
map_key_clear(BTN_MIDDLE);
97+
return 1;
98+
}
99+
}
100+
101+
/* Compatibility middle/wheel mappings should be ignored */
102+
if (usage->hid == HID_GD_WHEEL)
103+
return -1;
104+
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON &&
105+
(usage->hid & HID_USAGE) == 0x003)
106+
return -1;
107+
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER &&
108+
(usage->hid & HID_USAGE) == 0x238)
109+
return -1;
110+
111+
/* Map wheel emulation reports: 0xffa1 = USB, 0xff10 = BT */
112+
if ((usage->hid & HID_USAGE_PAGE) == 0xff100000 ||
113+
(usage->hid & HID_USAGE_PAGE) == 0xffa10000) {
114+
field->flags |= HID_MAIN_ITEM_RELATIVE | HID_MAIN_ITEM_VARIABLE;
115+
field->logical_minimum = -127;
116+
field->logical_maximum = 127;
117+
118+
switch (usage->hid & HID_USAGE) {
119+
case 0x0000:
120+
hid_map_usage(hi, usage, bit, max, EV_REL, 0x06);
121+
return 1;
122+
case 0x0001:
123+
hid_map_usage(hi, usage, bit, max, EV_REL, 0x08);
124+
return 1;
125+
default:
126+
return -1;
95127
}
96128
}
97129

@@ -633,6 +665,11 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
633665
if (ret)
634666
hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
635667

668+
/* Switch middle button to native mode */
669+
ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
670+
if (ret)
671+
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
672+
636673
/* Set keyboard settings to known state */
637674
cptkbd_data->fn_lock = true;
638675
cptkbd_data->sensitivity = 0x05;

0 commit comments

Comments
 (0)