aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Lentin <jm@lentin.co.uk>2015-08-11 17:40:52 -0400
committerJiri Kosina <jkosina@suse.cz>2015-08-12 08:32:31 -0400
commit3cb5ff0220e31bd1043bb18fd5765c9f86928491 (patch)
tree70369e3713cd7b5f2235e16c605566e6a083a91e
parentdbfebb44b7c650dd134a8be07f9afd5862150987 (diff)
HID: lenovo: Hide middle-button press until release
Don't relay a middle button press to userspace until release, and then only if there was no scroll events inbetween. This is closer to what Xorg's wheel emulation does, and avoids spurious middle-click pastes. Signed-off-by: Jamie Lentin <jm@lentin.co.uk> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-lenovo.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index d40221d78188..e4bc6cb6d7fa 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd {
37}; 37};
38 38
39struct lenovo_drvdata_cptkbd { 39struct lenovo_drvdata_cptkbd {
40 u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
40 bool fn_lock; 41 bool fn_lock;
41 int sensitivity; 42 int sensitivity;
42}; 43};
@@ -316,6 +317,53 @@ static int lenovo_raw_event(struct hid_device *hdev,
316 return 0; 317 return 0;
317} 318}
318 319
320static int lenovo_event_cptkbd(struct hid_device *hdev,
321 struct hid_field *field, struct hid_usage *usage, __s32 value)
322{
323 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
324
325 /* "wheel" scroll events */
326 if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
327 usage->code == REL_HWHEEL)) {
328 /* Scroll events disable middle-click event */
329 cptkbd_data->middlebutton_state = 2;
330 return 0;
331 }
332
333 /* Middle click events */
334 if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
335 if (value == 1) {
336 cptkbd_data->middlebutton_state = 1;
337 } else if (value == 0) {
338 if (cptkbd_data->middlebutton_state == 1) {
339 /* No scrolling inbetween, send middle-click */
340 input_event(field->hidinput->input,
341 EV_KEY, BTN_MIDDLE, 1);
342 input_sync(field->hidinput->input);
343 input_event(field->hidinput->input,
344 EV_KEY, BTN_MIDDLE, 0);
345 input_sync(field->hidinput->input);
346 }
347 cptkbd_data->middlebutton_state = 0;
348 }
349 return 1;
350 }
351
352 return 0;
353}
354
355static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
356 struct hid_usage *usage, __s32 value)
357{
358 switch (hdev->product) {
359 case USB_DEVICE_ID_LENOVO_CUSBKBD:
360 case USB_DEVICE_ID_LENOVO_CBTKBD:
361 return lenovo_event_cptkbd(hdev, field, usage, value);
362 default:
363 return 0;
364 }
365}
366
319static int lenovo_features_set_tpkbd(struct hid_device *hdev) 367static int lenovo_features_set_tpkbd(struct hid_device *hdev)
320{ 368{
321 struct hid_report *report; 369 struct hid_report *report;
@@ -708,6 +756,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
708 hid_warn(hdev, "Failed to switch middle button: %d\n", ret); 756 hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
709 757
710 /* Set keyboard settings to known state */ 758 /* Set keyboard settings to known state */
759 cptkbd_data->middlebutton_state = 0;
711 cptkbd_data->fn_lock = true; 760 cptkbd_data->fn_lock = true;
712 cptkbd_data->sensitivity = 0x05; 761 cptkbd_data->sensitivity = 0x05;
713 lenovo_features_set_cptkbd(hdev); 762 lenovo_features_set_cptkbd(hdev);
@@ -835,6 +884,7 @@ static struct hid_driver lenovo_driver = {
835 .probe = lenovo_probe, 884 .probe = lenovo_probe,
836 .remove = lenovo_remove, 885 .remove = lenovo_remove,
837 .raw_event = lenovo_raw_event, 886 .raw_event = lenovo_raw_event,
887 .event = lenovo_event,
838 .report_fixup = lenovo_report_fixup, 888 .report_fixup = lenovo_report_fixup,
839}; 889};
840module_hid_driver(lenovo_driver); 890module_hid_driver(lenovo_driver);