Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v2] HID: add driver for EWEADN G5 mice
  2026-11-01 15:40 [PATCH v2] HID: add driver for EWEADN G5 mice Liang Haowen
@ 2026-11-01 15:33 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-11-01 15:33 UTC (permalink / raw)
  To: Liang Haowen, linux-input; +Cc: dmitry.torokhov

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] HID: hid-eweadn: missing hid-ids.h include breaks build
- [Low] HID: hid-eweadn: redundant eweadn_probe() duplicates default probe
--

commit 4edaba02eb50bfbcf89b68ad006b2e16efd6acc9
Author: Liang Haowen <nbg2974@gmail.com>

HID: add driver for EWEADN G5 mice

This commit adds a HID driver for EWEADN G5 wireless and wired mice that
replaces the broken firmware report descriptor on USB interface 0 with a
standard mouse report descriptor.

> diff --git a/drivers/hid/hid-eweadn.c b/drivers/hid/hid-eweadn.c
> new file mode 100644
> index 0000000000000..79a9a1545b395
> --- /dev/null
> +++ b/drivers/hid/hid-eweadn.c
> @@ -0,0 +1,129 @@

[ ... ]

> +#include <linux/hid.h>
> +#include <linux/module.h>
> +#include <linux/usb.h>
> +
> +static __u8 eweadn_rdesc[] = {

[ ... ]

> +static int eweadn_probe(struct hid_device *hdev,
> +			const struct hid_device_id *id)
> +{
> +	int ret;
> +
> +	ret = hid_parse(hdev);
> +	if (ret) {
> +		hid_err(hdev, "parse failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> +	if (ret) {
> +		hid_err(hdev, "hw start failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}

[Severity: Low]
This isn't a bug, but is eweadn_probe() needed here?

In drivers/hid/hid-core.c, __hid_device_probe() already runs the default
probe sequence when hdrv->probe is not set:

drivers/hid/hid-core.c:__hid_device_probe() {
	if (hdrv->probe) {
		ret = hdrv->probe(hdev, id);
	} else { /* default probe */
		ret = hid_open_report(hdev);
		if (!ret)
			ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
	}
}

Since hid_parse() is just a wrapper around hid_open_report(), could
eweadn_probe() and the .probe assignment in eweadn_driver be dropped to
rely on the default HID core probe like other report-fixup-only drivers?

> +
> +static const struct hid_device_id eweadn_devices[] = {
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_YJXCHIP, USB_DEVICE_ID_YJXCHIP_MOUSE) },
> +	{ HID_USB_DEVICE(0xa8a4, 0x2255) },	/* replacement unit, wired mouse */
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(hid, eweadn_devices);
> +
> +static struct hid_driver eweadn_driver = {
> +	.name = "eweadn",
> +	.id_table = eweadn_devices,
> +	.report_fixup = eweadn_report_fixup,
> +	.probe = eweadn_probe,
> +};

[Severity: Low]
As reported by Sashiko on v1 [1], does this fail to build when
CONFIG_HID_EWEADN is enabled because drivers/hid/hid-eweadn.c uses
USB_VENDOR_ID_YJXCHIP and USB_DEVICE_ID_YJXCHIP_MOUSE in eweadn_devices[]
without including "hid-ids.h"?

Those macros are defined in drivers/hid/hid-ids.h:

#define USB_VENDOR_ID_YJXCHIP		0xa8a5
#define USB_DEVICE_ID_YJXCHIP_MOUSE	0x2255

Should drivers/hid/hid-eweadn.c include "hid-ids.h", define symbolic
constants in drivers/hid/hid-ids.h for the 0xa8a4:0x2255 device ID entry in
eweadn_devices[] as well, and mark eweadn_rdesc[] as const?

[1] https://lore.kernel.org/r/6ae7529d.10abdf86.7545b.3e9a@mx.google.com

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/6ae759e9.4b0417f2.1062f7.b196@mx.google.com?part=1

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

* [PATCH v2] HID: add driver for EWEADN G5 mice
@ 2026-11-01 15:40 Liang Haowen
  2026-11-01 15:33 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Liang Haowen @ 2026-11-01 15:40 UTC (permalink / raw)
  To: linux-input; +Cc: Jiri Kosina, Benjamin Tissoires, linux-kernel

EWEADN G5 mice (YJX-CHIP receivers 0xa8a5:2255, replacement units
and the wired mouse 0xa8a4:2255) send motion and buttons in a
9-byte vendor report on interface 0. The report descriptor the
firmware ships does not describe that data: the 0xa8a5 receivers
declare vendor usages with no mouse mapping, and the 0xa8a4 units
declare a standard mouse report the firmware then does not send.
Either way the stock input path produces no pointer events, and
there is no Linux driver from the vendor.

The report itself is a plain mouse report: buttons, int16 dx and
dy, an int8 wheel. Replace the descriptor at parse time with one
that describes exactly that report, so hid-core can parse the
frames with no custom event handling. The keyboard and
vendor-configuration interfaces bind to this driver too and keep
their own descriptors untouched.

Both device IDs bind with the fixed-up descriptor, and motion
events flow through the stock input path. This also makes the
userspace relay used until now (github.com/NB-Group/g5moused)
unnecessary.

Cc: Jiri Kosina <jikos@kernel.org>
Cc: Benjamin Tissoires <bentiss@kernel.org>
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Liang Haowen <nbg2974@gmail.com>
---
Changes in v2, from the review of v1:

- Bind all interfaces of the composite device instead of returning
  -ENODEV for the non-mouse ones: hid-generic steps aside for any
  registered driver whose id_table matches, so rejecting them left
  the keyboard and vendor-configuration interfaces with no driver
  at all. Only the mouse interface gets the fixed-up descriptor
  now; the others keep their own.

- Guard the USB interface lookup with hid_is_usb(): a virtual HID
  device created through /dev/uhid can claim BUS_USB with matching
  vendor and product IDs, and casting its parent would dereference
  memory that is not a usb_interface.

- Use the USB_VENDOR_ID_YJXCHIP macro for the original receiver.
---
 drivers/hid/Kconfig      |   9 +++
 drivers/hid/Makefile     |   1 +
 drivers/hid/hid-eweadn.c | 129 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 drivers/hid/hid-eweadn.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 2481bc0..3946f75 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -380,6 +380,15 @@ config HID_EVISION
 	applying customization using userspace programs.
 	Support for some EVision devices requiring report descriptor fixups.
 
+config HID_EWEADN
+	tristate "EWEADN G5 mice support"
+	depends on USB_HID
+	help
+	Support for EWEADN G5 wireless mice (YJX-CHIP 0xa8a5:2255 receivers,
+	0xa8a4 replacement units and the wired mouse). The stock report
+	descriptor does not describe the reports the firmware sends, so
+	the pointer is dead without this fixup.
+
 config HID_EZKEY
 	tristate "Ezkey BTC 8193 keyboard"
 	help
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 43a8eb0..2db5b5d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_HID_ELAN)		+= hid-elan.o
 obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
 obj-$(CONFIG_HID_ELO)		+= hid-elo.o
 obj-$(CONFIG_HID_EVISION)	+= hid-evision.o
+obj-$(CONFIG_HID_EWEADN)	+= hid-eweadn.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_FT260)		+= hid-ft260.o
 obj-$(CONFIG_HID_GEMBIRD)	+= hid-gembird.o
diff --git a/drivers/hid/hid-eweadn.c b/drivers/hid/hid-eweadn.c
new file mode 100644
index 0000000..79a9a15
--- /dev/null
+++ b/drivers/hid/hid-eweadn.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * HID driver for EWEADN G5 mice (YJX-CHIP a8a5:2255 / a8a4:2255).
+ *
+ * The mouse reports motion and buttons in a vendor-defined report
+ * (id 0x02) on interface 0. The report descriptor the firmware
+ * ships does not describe that data: the original 0xa8a5 receivers
+ * declare vendor usages with no mouse mapping, and the 0xa8a4 units
+ * declare a standard mouse report that the firmware then does not
+ * send. Either way the stock input path produces no pointer events.
+ * The report itself is a plain mouse report:
+ *
+ *   [1] buttons, 5 bits
+ *   [2] unused
+ *   [3] dx, int16 LE
+ *   [5] dy, int16 LE
+ *   [7] wheel, int8
+ *   [8] unused
+ *
+ * The descriptor below describes exactly that report, so hid-core
+ * can parse the frames without any custom event handling. The
+ * keyboard and vendor-configuration interfaces bind to this driver
+ * too and keep their own descriptors untouched.
+ *
+ * 0xa8a5 is the original receiver, 0xa8a4 the replacement units
+ * first seen in October 2026 and the mouse itself on its USB cable.
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+static __u8 eweadn_rdesc[] = {
+	0x05, 0x01,		/* Usage Page (Generic Desktop) */
+	0x09, 0x02,		/* Usage (Mouse) */
+	0xA1, 0x01,		/* Collection (Application) */
+	0x85, 0x02,		/*   Report ID (2) */
+	0x09, 0x01,		/*   Usage (Pointer) */
+	0xA1, 0x00,		/*   Collection (Physical) */
+	0x05, 0x09,		/*     Usage Page (Button) */
+	0x19, 0x01,		/*     Usage Minimum (1) */
+	0x29, 0x05,		/*     Usage Maximum (5) */
+	0x15, 0x00,		/*     Logical Minimum (0) */
+	0x25, 0x01,		/*     Logical Maximum (1) */
+	0x75, 0x01,		/*     Report Size (1) */
+	0x95, 0x05,		/*     Report Count (5) */
+	0x81, 0x02,		/*     Input (Data,Var,Abs) */
+	0x95, 0x0B,		/*     Report Count (11), padding to byte */
+	0x81, 0x03,		/*     Input (Cnst,Var,Abs) */
+	0x05, 0x01,		/*     Usage Page (Generic Desktop) */
+	0x09, 0x30,		/*     Usage (X) */
+	0x09, 0x31,		/*     Usage (Y) */
+	0x16, 0x00, 0x80,	/*     Logical Minimum (-32768) */
+	0x26, 0xFF, 0x7F,	/*     Logical Maximum (32767) */
+	0x75, 0x10,		/*     Report Size (16) */
+	0x95, 0x02,		/*     Report Count (2) */
+	0x81, 0x06,		/*     Input (Data,Var,Rel) */
+	0x09, 0x38,		/*     Usage (Wheel) */
+	0x15, 0x81,		/*     Logical Minimum (-127) */
+	0x25, 0x7F,		/*     Logical Maximum (127) */
+	0x75, 0x08,		/*     Report Size (8) */
+	0x95, 0x01,		/*     Report Count (1) */
+	0x81, 0x06,		/*     Input (Data,Var,Rel) */
+	0x95, 0x01,		/*     Report Count (1), trailing pad */
+	0x81, 0x03,		/*     Input (Cnst,Var,Abs) */
+	0xC0,			/*   End Collection */
+	0xC0,			/* End Collection */
+};
+
+static const __u8 *eweadn_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+				       unsigned int *rsize)
+{
+	struct usb_interface *intf;
+
+	if (!hid_is_usb(hdev))
+		return rdesc;
+
+	/*
+	 * Only the mouse interface carries the vendor report; the
+	 * keyboard and vendor-configuration interfaces keep their
+	 * own descriptors.
+	 */
+	intf = to_usb_interface(hdev->dev.parent);
+	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+		return rdesc;
+
+	hid_info(hdev, "fixing up EWEADN G5 mouse report descriptor\n");
+	*rsize = sizeof(eweadn_rdesc);
+	return eweadn_rdesc;
+}
+
+static int eweadn_probe(struct hid_device *hdev,
+			const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		hid_err(hdev, "hw start failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct hid_device_id eweadn_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_YJXCHIP, USB_DEVICE_ID_YJXCHIP_MOUSE) },
+	{ HID_USB_DEVICE(0xa8a4, 0x2255) },	/* replacement unit, wired mouse */
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, eweadn_devices);
+
+static struct hid_driver eweadn_driver = {
+	.name = "eweadn",
+	.id_table = eweadn_devices,
+	.report_fixup = eweadn_report_fixup,
+	.probe = eweadn_probe,
+};
+module_hid_driver(eweadn_driver);
+
+MODULE_AUTHOR("Liang Haowen <nbg2974@gmail.com>");
+MODULE_DESCRIPTION("HID driver for EWEADN G5 mice");
+MODULE_LICENSE("GPL");
-- 
2.55.0



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

end of thread, other threads:[~2026-11-01 15:33 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-01 15:40 [PATCH v2] HID: add driver for EWEADN G5 mice Liang Haowen
2026-11-01 15:33 ` sashiko-bot

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