lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250703004943.515919-6-derekjohn.clark@gmail.com>
Date: Wed,  2 Jul 2025 17:49:42 -0700
From: "Derek J. Clark" <derekjohn.clark@...il.com>
To: Jiri Kosina <jikos@...nel.org>,
	Benjamin Tissoires <bentiss@...nel.org>
Cc: Mario Limonciello <superm1@...nel.org>,
	Xino Ni <nijs1@...ovo.com>,
	Zhixin Zhang <zhangzx36@...ovo.com>,
	Mia Shao <shaohz1@...ovo.com>,
	Mark Pearson <mpearson-lenovo@...ebb.ca>,
	"Pierre-Loup A . Griffais" <pgriffais@...vesoftware.com>,
	"Derek J . Clark" <derekjohn.clark@...il.com>,
	linux-input@...r.kernel.org,
	linux-doc@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: [PATCH 5/6] HID: Add lenovo-legos-hid core

Adds core interface for the lenovo-legos-hid driver. The purpose of core
is to identify each available endpoint for the MCU in the Lenovo Legion
Go S and route each one to the appropriate initialization and event
handling functions. Endpoint specific logic will be implemented in
subsequent patches.

Signed-off-by: Derek J. Clark <derekjohn.clark@...il.com>
---
 MAINTAINERS                           |   1 +
 drivers/hid/Kconfig                   |   2 +
 drivers/hid/Makefile                  |   2 +
 drivers/hid/lenovo-legos-hid/Kconfig  |  11 +++
 drivers/hid/lenovo-legos-hid/Makefile |   6 ++
 drivers/hid/lenovo-legos-hid/core.c   | 113 ++++++++++++++++++++++++++
 drivers/hid/lenovo-legos-hid/core.h   |  25 ++++++
 7 files changed, 160 insertions(+)
 create mode 100644 drivers/hid/lenovo-legos-hid/Kconfig
 create mode 100644 drivers/hid/lenovo-legos-hid/Makefile
 create mode 100644 drivers/hid/lenovo-legos-hid/core.c
 create mode 100644 drivers/hid/lenovo-legos-hid/core.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 68211d6eb236..aa61be9e5bc1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13751,6 +13751,7 @@ M:	Derek J. Clark <derekjohn.clark@...il.com>
 L:	linux-input@...r.kernel.org
 S:	Maintained
 F:	Documentation/ABI/testing/sysfs-driver-lenovo-legos-hid
+F:	drivers/hid/lenovo-legos-hid/*
 
 LETSKETCH HID TABLET DRIVER
 M:	Hans de Goede <hansg@...nel.org>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index a57901203aeb..494e8386b598 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1436,4 +1436,6 @@ endif # HID
 
 source "drivers/hid/usbhid/Kconfig"
 
+source "drivers/hid/lenovo-legos-hid/Kconfig"
+
 endif # HID_SUPPORT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 10ae5dedbd84..bdf3ebaf11e5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -175,3 +175,5 @@ obj-$(CONFIG_AMD_SFH_HID)       += amd-sfh-hid/
 obj-$(CONFIG_SURFACE_HID_CORE)  += surface-hid/
 
 obj-$(CONFIG_INTEL_THC_HID)     += intel-thc-hid/
+
+obj-$(CONFIG_LENOVO_LEGOS_HID)  += lenovo-legos-hid/
diff --git a/drivers/hid/lenovo-legos-hid/Kconfig b/drivers/hid/lenovo-legos-hid/Kconfig
new file mode 100644
index 000000000000..6918b25e191c
--- /dev/null
+++ b/drivers/hid/lenovo-legos-hid/Kconfig
@@ -0,0 +1,11 @@
+config LENOVO_LEGOS_HID
+	tristate "Lenovo Legion Go S HID"
+	depends on USB_HID
+	depends on LEDS_CLASS
+	depends on LEDS_CLASS_MULTICOLOR
+	help
+	  Say Y here to include support for the Lenovo Legion Go S Handheld
+	  Console Controller.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called lenovo-legos-hid.
diff --git a/drivers/hid/lenovo-legos-hid/Makefile b/drivers/hid/lenovo-legos-hid/Makefile
new file mode 100644
index 000000000000..707f1be80c78
--- /dev/null
+++ b/drivers/hid/lenovo-legos-hid/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Makefile - Lenovo Legion Go S Handheld Console Controller driver
+#
+lenovo-legos-hid-y := core.o
+obj-$(CONFIG_LENOVO_LEGOS_HID)	:= lenovo-legos-hid.o
diff --git a/drivers/hid/lenovo-legos-hid/core.c b/drivers/hid/lenovo-legos-hid/core.c
new file mode 100644
index 000000000000..9049cbb8bd6c
--- /dev/null
+++ b/drivers/hid/lenovo-legos-hid/core.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  HID driver for Lenovo Legion Go S series gamepad.
+ *
+ *  Copyright (c) 2025 Derek J. Clark <derekjohn.clark@...il.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/hid.h>
+#include <linux/types.h>
+#include <linux/usb.h>
+
+#include "core.h"
+#include "../hid-ids.h"
+
+u8 get_endpoint_address(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_host_endpoint *ep;
+
+	if (intf) {
+		ep = intf->cur_altsetting->endpoint;
+		if (ep)
+			return ep->desc.bEndpointAddress;
+	}
+
+	return -ENODEV;
+}
+
+static int lenovo_legos_raw_event(struct hid_device *hdev,
+				  struct hid_report *report, u8 *data, int size)
+{
+	int ep;
+
+	ep = get_endpoint_address(hdev);
+
+	switch (ep) {
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int lenovo_legos_hid_probe(struct hid_device *hdev,
+				  const struct hid_device_id *id)
+{
+	int ret, ep;
+
+	ep = get_endpoint_address(hdev);
+	if (ep <= 0)
+		return ep;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "Parse failed\n");
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	if (ret) {
+		hid_err(hdev, "Failed to start HID device\n");
+		return ret;
+	}
+
+	ret = hid_hw_open(hdev);
+	if (ret) {
+		hid_err(hdev, "Failed to open HID device\n");
+		hid_hw_stop(hdev);
+		return ret;
+	}
+
+	switch (ep) {
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static void lenovo_legos_hid_remove(struct hid_device *hdev)
+{
+	int ep = get_endpoint_address(hdev);
+
+	switch (ep) {
+	default:
+		hid_hw_close(hdev);
+		hid_hw_stop(hdev);
+
+		break;
+	}
+}
+
+static const struct hid_device_id lenovo_legos_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QHE,
+			 USB_DEVICE_ID_LENOVO_LEGION_GO_S_XINPUT) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QHE,
+			 USB_DEVICE_ID_LENOVO_LEGION_GO_S_DINPUT) },
+	{}
+};
+
+MODULE_DEVICE_TABLE(hid, lenovo_legos_devices);
+static struct hid_driver lenovo_legos_hid = {
+	.name = "lenovo-legos-hid",
+	.id_table = lenovo_legos_devices,
+	.probe = lenovo_legos_hid_probe,
+	.remove = lenovo_legos_hid_remove,
+	.raw_event = lenovo_legos_raw_event,
+};
+module_hid_driver(lenovo_legos_hid);
+
+MODULE_AUTHOR("Derek J. Clark");
+MODULE_DESCRIPTION("HID Driver for Lenovo Legion Go S Series gamepad.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/lenovo-legos-hid/core.h b/drivers/hid/lenovo-legos-hid/core.h
new file mode 100644
index 000000000000..efbc50896536
--- /dev/null
+++ b/drivers/hid/lenovo-legos-hid/core.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* Copyright(C) 2025 Derek J. Clark <derekjohn.clark@...il.com> */
+
+#ifndef _LENOVO_LEGOS_HID_CORE_
+#define _LENOVO_LEGOS_HID_CORE_
+
+#include <linux/types.h>
+
+#define GO_S_PACKET_SIZE 64
+
+struct hid_device;
+
+enum legos_interface {
+	LEGION_GO_S_IAP_INTF_IN = 0x81,
+	LEGION_GO_S_TP_INTF_IN = 0x83,
+	LEGION_GO_S_CFG_INTF_IN,
+	LEGION_GO_S_IMU_INTF_IN,
+	LEGION_GO_S_GP_INFT_IN,
+	LEGION_GO_S_UNK_INTF_IN,
+};
+
+u8 get_endpoint_address(struct hid_device *hdev);
+
+#endif /* !_LENOVO_LEGOS_HID_CORE_*/
-- 
2.50.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ