mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/4] HID: add Kysona driver
@ 2024-10-05 11:57 Lode Willems
  2024-10-05 11:57 ` [PATCH 1/4] HID: Add IDs for Kysona Lode Willems
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Lode Willems @ 2024-10-05 11:57 UTC (permalink / raw)
  To: linux-input; +Cc: jikos, bentiss, linux-kernel, Lode Willems

This patchset adds a driver for the Kysona M600 mouse
with support for battery reporting.

Tested with a Kysona M600 V-HUB Special Edition

Lode Willems (4):
  HID: Add IDs for Kysona
  HID: Kysona: Add basic battery reporting for Kysona M600
  HID: Kysona: check battery status every 5s using a workqueue
  HID: Kysona: add basic online status

 drivers/hid/Kconfig      |   9 ++
 drivers/hid/Makefile     |   1 +
 drivers/hid/hid-ids.h    |   4 +
 drivers/hid/hid-kysona.c | 248 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 262 insertions(+)
 create mode 100644 drivers/hid/hid-kysona.c

-- 
2.46.1


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

* [PATCH 1/4] HID: Add IDs for Kysona
  2024-10-05 11:57 [PATCH 0/4] HID: add Kysona driver Lode Willems
@ 2024-10-05 11:57 ` Lode Willems
  2024-10-05 11:57 ` [PATCH 2/4] HID: Kysona: Add basic battery reporting for Kysona M600 Lode Willems
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lode Willems @ 2024-10-05 11:57 UTC (permalink / raw)
  To: linux-input; +Cc: jikos, bentiss, linux-kernel, Lode Willems

Add the vendor ID for Kysona and the product IDs for the M600 mouse
(both the dongle and the mouse itself)

Signed-off-by: Lode Willems <me@lodewillems.com>
---
 drivers/hid/hid-ids.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 781c5aa29859..76052c653112 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -749,6 +749,10 @@
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2	0x501A
 #define USB_DEVICE_ID_KYE_PENSKETCH_T609A	0x501B
 
+#define USB_VENDOR_ID_KYSONA		0x3554
+#define USB_DEVICE_ID_KYSONA_M600_DONGLE	0xF57C
+#define USB_DEVICE_ID_KYSONA_M600_WIRED	0xF57D
+
 #define USB_VENDOR_ID_LABTEC		0x1020
 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD	0x0006
 #define USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE	0x8888
-- 
2.46.1


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

* [PATCH 2/4] HID: Kysona: Add basic battery reporting for Kysona M600
  2024-10-05 11:57 [PATCH 0/4] HID: add Kysona driver Lode Willems
  2024-10-05 11:57 ` [PATCH 1/4] HID: Add IDs for Kysona Lode Willems
@ 2024-10-05 11:57 ` Lode Willems
  2024-10-05 11:57 ` [PATCH 3/4] HID: Kysona: check battery status every 5s using a workqueue Lode Willems
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lode Willems @ 2024-10-05 11:57 UTC (permalink / raw)
  To: linux-input; +Cc: jikos, bentiss, linux-kernel, Lode Willems

In this initial the battery is only probed once, a following patch will add
periodic checking.

Signed-off-by: Lode Willems <me@lodewillems.com>
---
 drivers/hid/Kconfig      |   9 ++
 drivers/hid/Makefile     |   1 +
 drivers/hid/hid-kysona.c | 208 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 218 insertions(+)
 create mode 100644 drivers/hid/hid-kysona.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 08446c89eff6..541dbee4fa00 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -459,6 +459,15 @@ config HID_KYE
 	- MousePen i608X tablet
 	- EasyPen M610X tablet
 
+config HID_KYSONA
+	tristate "Kysona devices"
+	depends on USB_HID
+	help
+	Support for Kysona mice.
+
+	Say Y here if you have a Kysona M600 mouse
+	and want to be able to read its battery capacity.
+
 config HID_UCLOGIC
 	tristate "UC-Logic"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e40f1ddebbb7..c39ef074ac66 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_HID_JABRA)		+= hid-jabra.o
 obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
+obj-$(CONFIG_HID_KYSONA)	+= hid-kysona.o
 obj-$(CONFIG_HID_LCPOWER)	+= hid-lcpower.o
 obj-$(CONFIG_HID_LENOVO)	+= hid-lenovo.o
 obj-$(CONFIG_HID_LETSKETCH)	+= hid-letsketch.o
diff --git a/drivers/hid/hid-kysona.c b/drivers/hid/hid-kysona.c
new file mode 100644
index 000000000000..91e359c31fa1
--- /dev/null
+++ b/drivers/hid/hid-kysona.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  USB HID driver for Kysona
+ *  Kysona M600 mice.
+ *
+ *  Copyright (c) 2024 Lode Willems <me@lodewillems.com>
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define BATTERY_REPORT_ID 4
+
+struct kysona_drvdata {
+	struct hid_device *hdev;
+	struct power_supply_desc battery_desc;
+	struct power_supply *battery;
+	u8 battery_capacity;
+	bool battery_charging;
+	u16 battery_voltage;
+};
+
+static enum power_supply_property kysona_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW
+};
+
+static int kysona_battery_get_property(struct power_supply *psy,
+				       enum power_supply_property psp,
+				       union power_supply_propval *val)
+{
+	struct kysona_drvdata *drv_data = power_supply_get_drvdata(psy);
+	int ret = 0;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = 1;
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		// TODO: check if device is online
+		val->intval = drv_data->battery_charging ?
+			POWER_SUPPLY_STATUS_CHARGING :
+			POWER_SUPPLY_STATUS_DISCHARGING;
+		break;
+	case POWER_SUPPLY_PROP_SCOPE:
+		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		val->intval = drv_data->battery_capacity;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		/* hardware reports voltage in mV. sysfs expects uV */
+		val->intval = drv_data->battery_voltage * 1000;
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = drv_data->hdev->name;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static const char kysona_battery_request[] = {
+	0x08, BATTERY_REPORT_ID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49
+};
+
+static int kysona_m600_fetch_battery(struct hid_device *hdev)
+{
+	u8 *write_buf;
+	int ret;
+
+	/* Request battery information */
+	write_buf = kmemdup(kysona_battery_request, sizeof(kysona_battery_request), GFP_KERNEL);
+	if (!write_buf)
+		return -ENOMEM;
+
+	ret = hid_hw_raw_request(hdev, kysona_battery_request[0],
+				 write_buf, sizeof(kysona_battery_request),
+				 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+	if (ret < (int)sizeof(kysona_battery_request)) {
+		hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
+		ret = -ENODATA;
+	}
+	kfree(write_buf);
+	return ret;
+}
+
+static void kysona_fetch_battery(struct hid_device *hdev)
+{
+	int ret = kysona_m600_fetch_battery(hdev);
+
+	if (ret < 0)
+		hid_dbg(hdev,
+			"Battery query failed (err: %d)\n", ret);
+}
+
+static int kysona_battery_probe(struct hid_device *hdev)
+{
+	struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
+	struct power_supply_config pscfg = { .drv_data = drv_data };
+	int ret = 0;
+
+	drv_data->battery_capacity = 100;
+
+	drv_data->battery_desc.properties = kysona_battery_props;
+	drv_data->battery_desc.num_properties = ARRAY_SIZE(kysona_battery_props);
+	drv_data->battery_desc.get_property = kysona_battery_get_property;
+	drv_data->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+	drv_data->battery_desc.use_for_apm = 0;
+	drv_data->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
+						     "kysona-%s-battery",
+						     strlen(hdev->uniq) ?
+						     hdev->uniq : dev_name(&hdev->dev));
+	if (!drv_data->battery_desc.name)
+		return -ENOMEM;
+
+	drv_data->battery = devm_power_supply_register(&hdev->dev,
+						       &drv_data->battery_desc, &pscfg);
+	if (IS_ERR(drv_data->battery)) {
+		ret = PTR_ERR(drv_data->battery);
+		drv_data->battery = NULL;
+		hid_err(hdev, "Unable to register battery device\n");
+		return ret;
+	}
+
+	power_supply_powers(drv_data->battery, &hdev->dev);
+	kysona_fetch_battery(hdev);
+
+	return ret;
+}
+
+static int kysona_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct kysona_drvdata *drv_data;
+	struct usb_interface *usbif;
+
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
+	usbif = to_usb_interface(hdev->dev.parent);
+
+	drv_data = devm_kzalloc(&hdev->dev, sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
+	hid_set_drvdata(hdev, drv_data);
+	drv_data->hdev = hdev;
+
+	ret = hid_parse(hdev);
+	if (ret)
+		return ret;
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret)
+		return ret;
+
+	if (usbif->cur_altsetting->desc.bInterfaceNumber == 1) {
+		if (kysona_battery_probe(hdev) < 0)
+			hid_err(hdev, "Kysona hid battery_probe failed: %d\n", ret);
+	}
+
+	return 0;
+}
+
+static int kysona_raw_event(struct hid_device *hdev,
+			    struct hid_report *report, u8 *data, int size)
+{
+	struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
+
+	if (drv_data->battery && size == sizeof(kysona_battery_request) &&
+	    data[0] == 8 && data[1] == BATTERY_REPORT_ID) {
+		drv_data->battery_capacity = data[6];
+		drv_data->battery_charging = data[7];
+		drv_data->battery_voltage = (data[8] << 8) | data[9];
+	}
+
+	return 0;
+}
+
+static const struct hid_device_id kysona_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYSONA, USB_DEVICE_ID_KYSONA_M600_DONGLE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYSONA, USB_DEVICE_ID_KYSONA_M600_WIRED) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, kysona_devices);
+
+static struct hid_driver kysona_driver = {
+	.name			= "kysona",
+	.id_table		= kysona_devices,
+	.probe			= kysona_probe,
+	.raw_event		= kysona_raw_event
+};
+module_hid_driver(kysona_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HID driver for Kysona devices");
+MODULE_AUTHOR("Lode Willems <me@lodewillems.com>");
-- 
2.46.1


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

* [PATCH 3/4] HID: Kysona: check battery status every 5s using a workqueue
  2024-10-05 11:57 [PATCH 0/4] HID: add Kysona driver Lode Willems
  2024-10-05 11:57 ` [PATCH 1/4] HID: Add IDs for Kysona Lode Willems
  2024-10-05 11:57 ` [PATCH 2/4] HID: Kysona: Add basic battery reporting for Kysona M600 Lode Willems
@ 2024-10-05 11:57 ` Lode Willems
  2024-10-05 11:57 ` [PATCH 4/4] HID: Kysona: add basic online status Lode Willems
  2024-10-18 10:29 ` [PATCH 0/4] HID: add Kysona driver Jiri Kosina
  4 siblings, 0 replies; 6+ messages in thread
From: Lode Willems @ 2024-10-05 11:57 UTC (permalink / raw)
  To: linux-input; +Cc: jikos, bentiss, linux-kernel, Lode Willems

Use a workqueue to periodically check the battery status

Signed-off-by: Lode Willems <me@lodewillems.com>
---
 drivers/hid/hid-kysona.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-kysona.c b/drivers/hid/hid-kysona.c
index 91e359c31fa1..403bdc4a5e12 100644
--- a/drivers/hid/hid-kysona.c
+++ b/drivers/hid/hid-kysona.c
@@ -12,6 +12,8 @@
 
 #include "hid-ids.h"
 
+#define BATTERY_TIMEOUT_MS 5000
+
 #define BATTERY_REPORT_ID 4
 
 struct kysona_drvdata {
@@ -21,6 +23,7 @@ struct kysona_drvdata {
 	u8 battery_capacity;
 	bool battery_charging;
 	u16 battery_voltage;
+	struct delayed_work battery_work;
 };
 
 static enum power_supply_property kysona_battery_props[] = {
@@ -104,6 +107,17 @@ static void kysona_fetch_battery(struct hid_device *hdev)
 			"Battery query failed (err: %d)\n", ret);
 }
 
+static void kysona_battery_timer_tick(struct work_struct *work)
+{
+	struct kysona_drvdata *drv_data = container_of(work,
+		struct kysona_drvdata, battery_work.work);
+	struct hid_device *hdev = drv_data->hdev;
+
+	kysona_fetch_battery(hdev);
+	schedule_delayed_work(&drv_data->battery_work,
+			      msecs_to_jiffies(BATTERY_TIMEOUT_MS));
+}
+
 static int kysona_battery_probe(struct hid_device *hdev)
 {
 	struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
@@ -134,7 +148,11 @@ static int kysona_battery_probe(struct hid_device *hdev)
 	}
 
 	power_supply_powers(drv_data->battery, &hdev->dev);
+
+	INIT_DELAYED_WORK(&drv_data->battery_work, kysona_battery_timer_tick);
 	kysona_fetch_battery(hdev);
+	schedule_delayed_work(&drv_data->battery_work,
+			      msecs_to_jiffies(BATTERY_TIMEOUT_MS));
 
 	return ret;
 }
@@ -188,6 +206,16 @@ static int kysona_raw_event(struct hid_device *hdev,
 	return 0;
 }
 
+static void kysona_remove(struct hid_device *hdev)
+{
+	struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
+
+	if (drv_data->battery)
+		cancel_delayed_work_sync(&drv_data->battery_work);
+
+	hid_hw_stop(hdev);
+}
+
 static const struct hid_device_id kysona_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYSONA, USB_DEVICE_ID_KYSONA_M600_DONGLE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYSONA, USB_DEVICE_ID_KYSONA_M600_WIRED) },
@@ -199,7 +227,8 @@ static struct hid_driver kysona_driver = {
 	.name			= "kysona",
 	.id_table		= kysona_devices,
 	.probe			= kysona_probe,
-	.raw_event		= kysona_raw_event
+	.raw_event		= kysona_raw_event,
+	.remove			= kysona_remove
 };
 module_hid_driver(kysona_driver);
 
-- 
2.46.1


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

* [PATCH 4/4] HID: Kysona: add basic online status
  2024-10-05 11:57 [PATCH 0/4] HID: add Kysona driver Lode Willems
                   ` (2 preceding siblings ...)
  2024-10-05 11:57 ` [PATCH 3/4] HID: Kysona: check battery status every 5s using a workqueue Lode Willems
@ 2024-10-05 11:57 ` Lode Willems
  2024-10-18 10:29 ` [PATCH 0/4] HID: add Kysona driver Jiri Kosina
  4 siblings, 0 replies; 6+ messages in thread
From: Lode Willems @ 2024-10-05 11:57 UTC (permalink / raw)
  To: linux-input; +Cc: jikos, bentiss, linux-kernel, Lode Willems

Wait for a response to the battery status request to set the device as
online. This prevent wrong power info when the dongle is connected but
the mouse is turned off.

Signed-off-by: Lode Willems <me@lodewillems.com>
---
 drivers/hid/hid-kysona.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/hid-kysona.c b/drivers/hid/hid-kysona.c
index 403bdc4a5e12..d4c0406b3323 100644
--- a/drivers/hid/hid-kysona.c
+++ b/drivers/hid/hid-kysona.c
@@ -18,6 +18,8 @@
 
 struct kysona_drvdata {
 	struct hid_device *hdev;
+	bool online;
+
 	struct power_supply_desc battery_desc;
 	struct power_supply *battery;
 	u8 battery_capacity;
@@ -32,7 +34,8 @@ static enum power_supply_property kysona_battery_props[] = {
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_SCOPE,
 	POWER_SUPPLY_PROP_MODEL_NAME,
-	POWER_SUPPLY_PROP_VOLTAGE_NOW
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_ONLINE
 };
 
 static int kysona_battery_get_property(struct power_supply *psy,
@@ -46,11 +49,16 @@ static int kysona_battery_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = 1;
 		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = drv_data->online;
+		break;
 	case POWER_SUPPLY_PROP_STATUS:
-		// TODO: check if device is online
-		val->intval = drv_data->battery_charging ?
-			POWER_SUPPLY_STATUS_CHARGING :
-			POWER_SUPPLY_STATUS_DISCHARGING;
+		if (drv_data->online)
+			val->intval = drv_data->battery_charging ?
+					POWER_SUPPLY_STATUS_CHARGING :
+					POWER_SUPPLY_STATUS_DISCHARGING;
+		else
+			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 		break;
 	case POWER_SUPPLY_PROP_SCOPE:
 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
@@ -124,7 +132,9 @@ static int kysona_battery_probe(struct hid_device *hdev)
 	struct power_supply_config pscfg = { .drv_data = drv_data };
 	int ret = 0;
 
+	drv_data->online = false;
 	drv_data->battery_capacity = 100;
+	drv_data->battery_voltage = 4200;
 
 	drv_data->battery_desc.properties = kysona_battery_props;
 	drv_data->battery_desc.num_properties = ARRAY_SIZE(kysona_battery_props);
@@ -201,6 +211,7 @@ static int kysona_raw_event(struct hid_device *hdev,
 		drv_data->battery_capacity = data[6];
 		drv_data->battery_charging = data[7];
 		drv_data->battery_voltage = (data[8] << 8) | data[9];
+		drv_data->online = true;
 	}
 
 	return 0;
-- 
2.46.1


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

* Re: [PATCH 0/4] HID: add Kysona driver
  2024-10-05 11:57 [PATCH 0/4] HID: add Kysona driver Lode Willems
                   ` (3 preceding siblings ...)
  2024-10-05 11:57 ` [PATCH 4/4] HID: Kysona: add basic online status Lode Willems
@ 2024-10-18 10:29 ` Jiri Kosina
  4 siblings, 0 replies; 6+ messages in thread
From: Jiri Kosina @ 2024-10-18 10:29 UTC (permalink / raw)
  To: Lode Willems; +Cc: linux-input, bentiss, linux-kernel

On Sat, 5 Oct 2024, Lode Willems wrote:

> This patchset adds a driver for the Kysona M600 mouse
> with support for battery reporting.
> 
> Tested with a Kysona M600 V-HUB Special Edition
> 
> Lode Willems (4):
>   HID: Add IDs for Kysona
>   HID: Kysona: Add basic battery reporting for Kysona M600
>   HID: Kysona: check battery status every 5s using a workqueue
>   HID: Kysona: add basic online status
> 
>  drivers/hid/Kconfig      |   9 ++
>  drivers/hid/Makefile     |   1 +
>  drivers/hid/hid-ids.h    |   4 +
>  drivers/hid/hid-kysona.c | 248 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 262 insertions(+)
>  create mode 100644 drivers/hid/hid-kysona.c

Now queued in hid.git#for-6.13/kysona.

Thanks,

-- 
Jiri Kosina
SUSE Labs


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

end of thread, other threads:[~2024-10-18 10:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-05 11:57 [PATCH 0/4] HID: add Kysona driver Lode Willems
2024-10-05 11:57 ` [PATCH 1/4] HID: Add IDs for Kysona Lode Willems
2024-10-05 11:57 ` [PATCH 2/4] HID: Kysona: Add basic battery reporting for Kysona M600 Lode Willems
2024-10-05 11:57 ` [PATCH 3/4] HID: Kysona: check battery status every 5s using a workqueue Lode Willems
2024-10-05 11:57 ` [PATCH 4/4] HID: Kysona: add basic online status Lode Willems
2024-10-18 10:29 ` [PATCH 0/4] HID: add Kysona driver Jiri Kosina

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®