Commit 94596303 authored by Jiri Kosina's avatar Jiri Kosina
Browse files

Merge branch 'for-6.9/lenovo' into for-linus

- 2nd version of code for applying proper quirk depending on firmware version
  for lenovo/cptkbd (Mikhail Khvainitski)
parents 2e21dee6 2814646f
Loading
Loading
Loading
Loading
+39 −18
Original line number Diff line number Diff line
@@ -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);