diff --git a/kernel-patch/3001-HID-lenovo-Use-constants-for-axes-names.patch b/kernel-patch/3001-HID-lenovo-Use-constants-for-axes-names.patch new file mode 100644 index 0000000..e8b1c9f --- /dev/null +++ b/kernel-patch/3001-HID-lenovo-Use-constants-for-axes-names.patch @@ -0,0 +1,30 @@ +From 2decbccdcfcfe19b35ed7424881d57213bfc5a17 Mon Sep 17 00:00:00 2001 +From: Jamie Lentin +Date: Sun, 2 Aug 2015 10:45:39 +0100 +Subject: [PATCH 1/3] HID: lenovo: Use constants for axes names + +Signed-off-by: Jamie Lentin +--- + drivers/hid/hid-lenovo.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c +index c4c3f09..65df414 100644 +--- a/drivers/hid/hid-lenovo.c ++++ b/drivers/hid/hid-lenovo.c +@@ -117,10 +117,10 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, + + switch (usage->hid & HID_USAGE) { + case 0x0000: +- hid_map_usage(hi, usage, bit, max, EV_REL, 0x06); ++ hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL); + return 1; + case 0x0001: +- hid_map_usage(hi, usage, bit, max, EV_REL, 0x08); ++ hid_map_usage(hi, usage, bit, max, EV_REL, REL_WHEEL); + return 1; + default: + return -1; +-- +2.1.4 + diff --git a/kernel-patch/3002-HID-lenovo-Add-missing-return-value-check.patch b/kernel-patch/3002-HID-lenovo-Add-missing-return-value-check.patch new file mode 100644 index 0000000..5ae50b9 --- /dev/null +++ b/kernel-patch/3002-HID-lenovo-Add-missing-return-value-check.patch @@ -0,0 +1,31 @@ +From 543e190688a51d947a024c011a09dbc6ed23a62b Mon Sep 17 00:00:00 2001 +From: Jamie Lentin +Date: Sun, 2 Aug 2015 10:46:10 +0100 +Subject: [PATCH 2/3] HID: lenovo: Add missing return-value check + +Signed-off-by: Jamie Lentin +--- + drivers/hid/hid-lenovo.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c +index 65df414..265bfe2 100644 +--- a/drivers/hid/hid-lenovo.c ++++ b/drivers/hid/hid-lenovo.c +@@ -178,9 +178,12 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev) + struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); + + ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock); +- ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity); + if (ret) + hid_err(hdev, "Fn-lock setting failed: %d\n", ret); ++ ++ ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity); ++ if (ret) ++ hid_err(hdev, "Sensitivity setting failed: %d\n", ret); + } + + static ssize_t attr_fn_lock_show_cptkbd(struct device *dev, +-- +2.1.4 + diff --git a/kernel-patch/3003-HID-lenovo-Hide-middle-button-press-until-release.patch b/kernel-patch/3003-HID-lenovo-Hide-middle-button-press-until-release.patch new file mode 100644 index 0000000..b8f7c3a --- /dev/null +++ b/kernel-patch/3003-HID-lenovo-Hide-middle-button-press-until-release.patch @@ -0,0 +1,99 @@ +From 9a8c4f2d805fbc4589ab238e7f04cd1a34f5b922 Mon Sep 17 00:00:00 2001 +From: Jamie Lentin +Date: Sun, 2 Aug 2015 10:49:30 +0100 +Subject: [PATCH 3/3] 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 +--- + drivers/hid/hid-lenovo.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c +index 265bfe2..629d988 100644 +--- a/drivers/hid/hid-lenovo.c ++++ b/drivers/hid/hid-lenovo.c +@@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd { + }; + + struct lenovo_drvdata_cptkbd { ++ u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */ + bool fn_lock; + int sensitivity; + }; +@@ -287,6 +288,53 @@ static int lenovo_raw_event(struct hid_device *hdev, + return 0; + } + ++static int lenovo_event_cptkbd(struct hid_device *hdev, ++ struct hid_field *field, struct hid_usage *usage, __s32 value) ++{ ++ struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); ++ ++ /* "wheel" scroll events */ ++ if (usage->type == EV_REL && (usage->code == REL_WHEEL || ++ usage->code == REL_HWHEEL)) { ++ /* Scroll events disable middle-click event */ ++ cptkbd_data->middlebutton_state = 2; ++ return 0; ++ } ++ ++ /* Middle click events */ ++ if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) { ++ if (value == 1) { ++ cptkbd_data->middlebutton_state = 1; ++ } else if (value == 0) { ++ if (cptkbd_data->middlebutton_state == 1) { ++ /* No scrolling inbetween, send middle-click */ ++ input_event(field->hidinput->input, ++ EV_KEY, BTN_MIDDLE, 1); ++ input_sync(field->hidinput->input); ++ input_event(field->hidinput->input, ++ EV_KEY, BTN_MIDDLE, 0); ++ input_sync(field->hidinput->input); ++ } ++ cptkbd_data->middlebutton_state = 0; ++ } ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int lenovo_event(struct hid_device *hdev, struct hid_field *field, ++ struct hid_usage *usage, __s32 value) ++{ ++ switch (hdev->product) { ++ case USB_DEVICE_ID_LENOVO_CUSBKBD: ++ case USB_DEVICE_ID_LENOVO_CBTKBD: ++ return lenovo_event_cptkbd(hdev, field, usage, value); ++ default: ++ return 0; ++ } ++} ++ + static int lenovo_features_set_tpkbd(struct hid_device *hdev) + { + struct hid_report *report; +@@ -674,6 +722,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev) + hid_warn(hdev, "Failed to switch middle button: %d\n", ret); + + /* Set keyboard settings to known state */ ++ cptkbd_data->middlebutton_state = 0; + cptkbd_data->fn_lock = true; + cptkbd_data->sensitivity = 0x05; + lenovo_features_set_cptkbd(hdev); +@@ -781,6 +830,7 @@ static struct hid_driver lenovo_driver = { + .probe = lenovo_probe, + .remove = lenovo_remove, + .raw_event = lenovo_raw_event, ++ .event = lenovo_event, + }; + module_hid_driver(lenovo_driver); + +-- +2.1.4 +