All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400
@ 2015-09-03 13:08 Benjamin Tissoires
  2015-09-03 13:08 ` [PATCH 1/2] HID: logitech-hidpp: split HIDPP_QUIRK_DELAYED_INIT in two Benjamin Tissoires
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Benjamin Tissoires @ 2015-09-03 13:08 UTC (permalink / raw)
  To: Jiri Kosina, Nestor Lopez Casado
  Cc: simon, BALATON Zoltan, linux-input, linux-kernel, Benjamin Tissoires

Hi guys,

This series adds a new parameter for the K400 owners. This keyboard has an
embedded touchpad which defaults to report tap to click. It can be annoying
given that there are physical buttons, and we can just disable that from the
host by using the feature 0x6010.

The first patch might conflict with Simon's current work in progress, so
that's why Simon is CC-ed to it.

Cheers,
Benjamin

Benjamin Tissoires (2):
  HID: logitech-hidpp: split HIDPP_QUIRK_DELAYED_INIT in two
  HID: logitech-hidpp: add support to disable tap-to-click on the K400

 drivers/hid/hid-logitech-hidpp.c | 159 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 150 insertions(+), 9 deletions(-)

-- 
2.4.3


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] HID: logitech-hidpp: split HIDPP_QUIRK_DELAYED_INIT in two
  2015-09-03 13:08 [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400 Benjamin Tissoires
@ 2015-09-03 13:08 ` Benjamin Tissoires
  2015-09-03 13:08 ` [PATCH 2/2] HID: logitech-hidpp: add support to disable tap-to-click on the K400 Benjamin Tissoires
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Benjamin Tissoires @ 2015-09-03 13:08 UTC (permalink / raw)
  To: Jiri Kosina, Nestor Lopez Casado
  Cc: simon, BALATON Zoltan, linux-input, linux-kernel, Benjamin Tissoires

HIDPP_QUIRK_DELAYED_INIT means two things currently:
- we want to delay the initialization process
- we do not want hid to create an input device based on the report
  descriptor.

This should actually be 2 different quirks so we can have special connect
events while still having HID creating the input for us.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/hid-logitech-hidpp.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 4841964..81d1bc0 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -43,8 +43,12 @@ MODULE_PARM_DESC(disable_raw_mode,
 #define HIDPP_QUIRK_CLASS_M560			BIT(1)
 
 /* bits 2..20 are reserved for classes */
-#define HIDPP_QUIRK_DELAYED_INIT		BIT(21)
+#define HIDPP_QUIRK_CONNECT_EVENTS		BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS	BIT(22)
+#define HIDPP_QUIRK_NO_HIDINPUT			BIT(23)
+
+#define HIDPP_QUIRK_DELAYED_INIT		(HIDPP_QUIRK_NO_HIDINPUT | \
+						 HIDPP_QUIRK_CONNECT_EVENTS)
 
 /*
  * There are two hidpp protocols in use, the first version hidpp10 is known
@@ -1203,7 +1207,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
 	if (unlikely(hidpp_report_is_connect_event(report))) {
 		atomic_set(&hidpp->connected,
 				!(report->rap.params[0] & (1 << 6)));
-		if ((hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) &&
+		if ((hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) &&
 		    (schedule_work(&hidpp->work) == 0))
 			dbg_hid("%s: connect event already queued\n", __func__);
 		return 1;
@@ -1333,18 +1337,21 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
 	if (!connected || hidpp->delayed_input)
 		return;
 
+	/* the device is already connected, we can ask for its name and
+	 * protocol */
 	if (!hidpp->protocol_major) {
 		ret = !hidpp_is_connected(hidpp);
 		if (ret) {
 			hid_err(hdev, "Can not get the protocol version.\n");
 			return;
 		}
+		hid_info(hdev, "HID++ %u.%u device connected.\n",
+			 hidpp->protocol_major, hidpp->protocol_minor);
 	}
 
-	/* the device is already connected, we can ask for its name and
-	 * protocol */
-	hid_info(hdev, "HID++ %u.%u device connected.\n",
-		 hidpp->protocol_major, hidpp->protocol_minor);
+	if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT))
+		/* if HID created the input nodes for us, we can stop now */
+		return;
 
 	if (!hidpp->name || hidpp->name == hdev->name) {
 		name = hidpp_get_device_name(hidpp);
@@ -1397,7 +1404,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	if (disable_raw_mode) {
 		hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;
-		hidpp->quirks &= ~HIDPP_QUIRK_DELAYED_INIT;
+		hidpp->quirks &= ~HIDPP_QUIRK_CONNECT_EVENTS;
+		hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT;
 	}
 
 	if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
@@ -1448,7 +1456,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	/* Block incoming packets */
 	hid_device_io_stop(hdev);
 
-	if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+	if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
 		connect_mask &= ~HID_CONNECT_HIDINPUT;
 
 	ret = hid_hw_start(hdev, connect_mask);
@@ -1457,7 +1465,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto hid_hw_start_fail;
 	}
 
-	if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) {
+	if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) {
 		/* Allow incoming packets */
 		hid_device_io_start(hdev);
 
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] HID: logitech-hidpp: add support to disable tap-to-click on the K400
  2015-09-03 13:08 [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400 Benjamin Tissoires
  2015-09-03 13:08 ` [PATCH 1/2] HID: logitech-hidpp: split HIDPP_QUIRK_DELAYED_INIT in two Benjamin Tissoires
@ 2015-09-03 13:08 ` Benjamin Tissoires
  2015-09-03 15:00   ` simon
  2015-09-04 12:50 ` Jiri Kosina
  3 siblings, 0 replies; 6+ messages in thread
From: Benjamin Tissoires @ 2015-09-03 13:08 UTC (permalink / raw)
  To: Jiri Kosina, Nestor Lopez Casado
  Cc: simon, BALATON Zoltan, linux-input, linux-kernel, Benjamin Tissoires

The Logitech K400 keyboard has an embedded touchpad which is seen as a
mouse from the OS point of view. There is a hardware shortcut to disable
tap-to-click but the setting is not remembered accross reset, annoying
some users.

We can toggle this feature from the host by using the feature 0x6010:
Touchpad FW items

Reported-by: BALATON Zoltan <balaton@eik.bme.hu>
Tested-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/hid-logitech-hidpp.c | 133 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 81d1bc0..452e5d5 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -33,6 +33,11 @@ module_param(disable_raw_mode, bool, 0644);
 MODULE_PARM_DESC(disable_raw_mode,
 	"Disable Raw mode reporting for touchpads and keep firmware gestures.");
 
+static bool disable_tap_to_click;
+module_param(disable_tap_to_click, bool, 0644);
+MODULE_PARM_DESC(disable_tap_to_click,
+	"Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently).");
+
 #define REPORT_ID_HIDPP_SHORT			0x10
 #define REPORT_ID_HIDPP_LONG			0x11
 
@@ -41,6 +46,7 @@ MODULE_PARM_DESC(disable_raw_mode,
 
 #define HIDPP_QUIRK_CLASS_WTP			BIT(0)
 #define HIDPP_QUIRK_CLASS_M560			BIT(1)
+#define HIDPP_QUIRK_CLASS_K400			BIT(2)
 
 /* bits 2..20 are reserved for classes */
 #define HIDPP_QUIRK_CONNECT_EVENTS		BIT(21)
@@ -557,6 +563,52 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp)
 }
 
 /* -------------------------------------------------------------------------- */
+/* 0x6010: Touchpad FW items                                                  */
+/* -------------------------------------------------------------------------- */
+
+#define HIDPP_PAGE_TOUCHPAD_FW_ITEMS			0x6010
+
+#define CMD_TOUCHPAD_FW_ITEMS_SET			0x10
+
+struct hidpp_touchpad_fw_items {
+	uint8_t presence;
+	uint8_t desired_state;
+	uint8_t state;
+	uint8_t persistent;
+};
+
+/**
+ * send a set state command to the device by reading the current items->state
+ * field. items is then filled with the current state.
+ */
+static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp,
+				       u8 feature_index,
+				       struct hidpp_touchpad_fw_items *items)
+{
+	struct hidpp_report response;
+	int ret;
+	u8 *params = (u8 *)response.fap.params;
+
+	ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+		CMD_TOUCHPAD_FW_ITEMS_SET, &items->state, 1, &response);
+
+	if (ret > 0) {
+		hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+			__func__, ret);
+		return -EPROTO;
+	}
+	if (ret)
+		return ret;
+
+	items->presence = params[0];
+	items->desired_state = params[1];
+	items->state = params[2];
+	items->persistent = params[3];
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
 /* 0x6100: TouchPadRawXY                                                      */
 /* -------------------------------------------------------------------------- */
 
@@ -1136,6 +1188,75 @@ static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	return -1;
 }
 
+/* ------------------------------------------------------------------------- */
+/* Logitech K400 devices                                                     */
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The Logitech K400 keyboard has an embedded touchpad which is seen
+ * as a mouse from the OS point of view. There is a hardware shortcut to disable
+ * tap-to-click but the setting is not remembered accross reset, annoying some
+ * users.
+ *
+ * We can toggle this feature from the host by using the feature 0x6010:
+ * Touchpad FW items
+ */
+
+struct k400_private_data {
+	u8 feature_index;
+};
+
+static int k400_disable_tap_to_click(struct hidpp_device *hidpp)
+{
+	struct k400_private_data *k400 = hidpp->private_data;
+	struct hidpp_touchpad_fw_items items = {};
+	int ret;
+	u8 feature_type;
+
+	if (!k400->feature_index) {
+		ret = hidpp_root_get_feature(hidpp,
+			HIDPP_PAGE_TOUCHPAD_FW_ITEMS,
+			&k400->feature_index, &feature_type);
+		if (ret)
+			/* means that the device is not powered up */
+			return ret;
+	}
+
+	ret = hidpp_touchpad_fw_items_set(hidpp, k400->feature_index, &items);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int k400_allocate(struct hid_device *hdev)
+{
+	struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+	struct k400_private_data *k400;
+
+	k400 = devm_kzalloc(&hdev->dev, sizeof(struct k400_private_data),
+			    GFP_KERNEL);
+	if (!k400)
+		return -ENOMEM;
+
+	hidpp->private_data = k400;
+
+	return 0;
+};
+
+static int k400_connect(struct hid_device *hdev, bool connected)
+{
+	struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+	if (!connected)
+		return 0;
+
+	if (!disable_tap_to_click)
+		return 0;
+
+	return k400_disable_tap_to_click(hidpp);
+}
+
 /* -------------------------------------------------------------------------- */
 /* Generic HID++ devices                                                      */
 /* -------------------------------------------------------------------------- */
@@ -1332,6 +1453,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
 		ret = m560_send_config_command(hdev, connected);
 		if (ret)
 			return;
+	} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
+		ret = k400_connect(hdev, connected);
+		if (ret)
+			return;
 	}
 
 	if (!connected || hidpp->delayed_input)
@@ -1416,6 +1541,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		ret = m560_allocate(hdev);
 		if (ret)
 			goto allocate_fail;
+	} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
+		ret = k400_allocate(hdev);
+		if (ret)
+			goto allocate_fail;
 	}
 
 	INIT_WORK(&hidpp->work, delayed_work_cb);
@@ -1510,6 +1639,10 @@ static const struct hid_device_id hidpp_devices[] = {
 	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
 		USB_VENDOR_ID_LOGITECH, 0x402d),
 	  .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
+	{ /* Keyboard logitech K400 */
+	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
+		USB_VENDOR_ID_LOGITECH, 0x4024),
+	  .driver_data = HIDPP_QUIRK_CONNECT_EVENTS | HIDPP_QUIRK_CLASS_K400 },
 
 	{ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
 		USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400
  2015-09-03 13:08 [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400 Benjamin Tissoires
@ 2015-09-03 15:00   ` simon
  2015-09-03 13:08 ` [PATCH 2/2] HID: logitech-hidpp: add support to disable tap-to-click on the K400 Benjamin Tissoires
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: simon @ 2015-09-03 15:00 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Jiri Kosina, Nestor Lopez Casado, simon, BALATON Zoltan,
	linux-input, linux-kernel, Benjamin Tissoires


> The first patch might conflict with Simon's current work in progress, so
> that's why Simon is CC-ed to it.

Thanks for the 'heads-up', I think that the HID++ stuff I have in progress
won't be ready until the 4.4 cycle,
Cheers,
Simon


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400
@ 2015-09-03 15:00   ` simon
  0 siblings, 0 replies; 6+ messages in thread
From: simon @ 2015-09-03 15:00 UTC (permalink / raw)
  Cc: Jiri Kosina, Nestor Lopez Casado, simon, BALATON Zoltan,
	linux-input, linux-kernel, Benjamin Tissoires


> The first patch might conflict with Simon's current work in progress, so
> that's why Simon is CC-ed to it.

Thanks for the 'heads-up', I think that the HID++ stuff I have in progress
won't be ready until the 4.4 cycle,
Cheers,
Simon


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400
  2015-09-03 13:08 [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400 Benjamin Tissoires
                   ` (2 preceding siblings ...)
  2015-09-03 15:00   ` simon
@ 2015-09-04 12:50 ` Jiri Kosina
  3 siblings, 0 replies; 6+ messages in thread
From: Jiri Kosina @ 2015-09-04 12:50 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Nestor Lopez Casado, simon, BALATON Zoltan, linux-input, linux-kernel

On Thu, 3 Sep 2015, Benjamin Tissoires wrote:

> Hi guys,
> 
> This series adds a new parameter for the K400 owners. This keyboard has an
> embedded touchpad which defaults to report tap to click. It can be annoying
> given that there are physical buttons, and we can just disable that from the
> host by using the feature 0x6010.
> 
> The first patch might conflict with Simon's current work in progress, so
> that's why Simon is CC-ed to it.

Now in for-4.4/logitech. Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-09-04 12:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-03 13:08 [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click on the K400 Benjamin Tissoires
2015-09-03 13:08 ` [PATCH 1/2] HID: logitech-hidpp: split HIDPP_QUIRK_DELAYED_INIT in two Benjamin Tissoires
2015-09-03 13:08 ` [PATCH 2/2] HID: logitech-hidpp: add support to disable tap-to-click on the K400 Benjamin Tissoires
2015-09-03 15:00 ` [PATCH 0/2] HID: logitech-hidpp: allow to disable tap to click " simon
2015-09-03 15:00   ` simon
2015-09-04 12:50 ` Jiri Kosina

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.