mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
HID: lenovo: Add middleclick_workaround sysfs knob for cptkbd
[ Upstream commit2814646f76
] Previous attempt to autodetect well-behaving patched firmware introduced in commit46a0a2c96f
("HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround") has shown that there are false-positives on original firmware (on both 1st gen and 2nd gen keyboards) which causes the middle button click workaround to be mistakenly disabled. This commit adds explicit parameter to sysfs to control this workaround. Fixes:46a0a2c96f
("HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround") Fixes:43527a0094
("HID: lenovo: Restrict detection of patched firmware only to USB cptkbd") Signed-off-by: Mikhail Khvainitski <me@khvoinitsky.org> Signed-off-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
877c08e04e
commit
3108f86489
@ -54,10 +54,10 @@ struct lenovo_drvdata {
|
||||
/* 0: Up
|
||||
* 1: Down (undecided)
|
||||
* 2: Scrolling
|
||||
* 3: Patched firmware, disable workaround
|
||||
*/
|
||||
u8 middlebutton_state;
|
||||
bool fn_lock;
|
||||
bool middleclick_workaround_cptkbd;
|
||||
};
|
||||
|
||||
#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
|
||||
@ -621,6 +621,36 @@ static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t attr_middleclick_workaround_show_cptkbd(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n",
|
||||
cptkbd_data->middleclick_workaround_cptkbd);
|
||||
}
|
||||
|
||||
static ssize_t attr_middleclick_workaround_store_cptkbd(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
|
||||
int value;
|
||||
|
||||
if (kstrtoint(buf, 10, &value))
|
||||
return -EINVAL;
|
||||
if (value < 0 || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
cptkbd_data->middleclick_workaround_cptkbd = !!value;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct device_attribute dev_attr_fn_lock =
|
||||
__ATTR(fn_lock, S_IWUSR | S_IRUGO,
|
||||
@ -632,10 +662,16 @@ static struct device_attribute dev_attr_sensitivity_cptkbd =
|
||||
attr_sensitivity_show_cptkbd,
|
||||
attr_sensitivity_store_cptkbd);
|
||||
|
||||
static struct device_attribute dev_attr_middleclick_workaround_cptkbd =
|
||||
__ATTR(middleclick_workaround, S_IWUSR | S_IRUGO,
|
||||
attr_middleclick_workaround_show_cptkbd,
|
||||
attr_middleclick_workaround_store_cptkbd);
|
||||
|
||||
|
||||
static struct attribute *lenovo_attributes_cptkbd[] = {
|
||||
&dev_attr_fn_lock.attr,
|
||||
&dev_attr_sensitivity_cptkbd.attr,
|
||||
&dev_attr_middleclick_workaround_cptkbd.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -686,23 +722,7 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
|
||||
{
|
||||
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
|
||||
|
||||
if (cptkbd_data->middlebutton_state != 3) {
|
||||
/* REL_X and REL_Y events during middle button pressed
|
||||
* are only possible on patched, bug-free firmware
|
||||
* so set middlebutton_state to 3
|
||||
* to never apply workaround anymore
|
||||
*/
|
||||
if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD &&
|
||||
cptkbd_data->middlebutton_state == 1 &&
|
||||
usage->type == EV_REL &&
|
||||
(usage->code == REL_X || usage->code == REL_Y)) {
|
||||
cptkbd_data->middlebutton_state = 3;
|
||||
/* send middle button press which was hold before */
|
||||
input_event(field->hidinput->input,
|
||||
EV_KEY, BTN_MIDDLE, 1);
|
||||
input_sync(field->hidinput->input);
|
||||
}
|
||||
|
||||
if (cptkbd_data->middleclick_workaround_cptkbd) {
|
||||
/* "wheel" scroll events */
|
||||
if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
|
||||
usage->code == REL_HWHEEL)) {
|
||||
@ -1166,6 +1186,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
|
||||
cptkbd_data->middlebutton_state = 0;
|
||||
cptkbd_data->fn_lock = true;
|
||||
cptkbd_data->sensitivity = 0x05;
|
||||
cptkbd_data->middleclick_workaround_cptkbd = true;
|
||||
lenovo_features_set_cptkbd(hdev);
|
||||
|
||||
ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
|
||||
|
Loading…
Reference in New Issue
Block a user