@@ -0,0 +1,120 @@
+// 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.
+ * Interface 1 (keyboard) and interface 2 (vendor configuration) are
+ * left to hid-generic.
+ *
+ * 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)
+{
+ 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)
+{
+ struct usb_interface *intf;
+ int ret;
+
+ intf = to_usb_interface(hdev->dev.parent);
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return -ENODEV; /* keyboard and config stay on hid-generic */
+
+ 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(0xa8a5, 0x2255) }, /* original receiver */
+ { 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");