]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
HID: rapoo: Add support for side buttons on RAPOO 0x2015 mouse
authorNguyen Dinh Dang Duong <dangduong31205@gmail.com>
Fri, 27 Jun 2025 17:04:23 +0000 (00:04 +0700)
committerJiri Kosina <jkosina@suse.com>
Sat, 10 Jan 2026 08:52:37 +0000 (09:52 +0100)
This patch adds support for handling the side buttons
on the RAPOO 0x2015 wireless mouse. These buttons were
previously not generating input events due to missing
driver logic.

The new code handles raw HID input report with Report
ID 1 and maps the side buttons to KEY_BACK and KEY_FORWARD
using the input subsystem.

Tested on a RAPOO mouse with USB ID 24AE:2015.

Signed-off-by: Nguyen Dinh Dang Duong <dangduong31205@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-ids.h
drivers/hid/hid-rapoo.c [new file with mode: 0644]

index 920a64b66b25b39e8259105c7c9b975fb77b2725..68247a539e080e11b874f896600bf942cf9caece 100644 (file)
@@ -1015,6 +1015,12 @@ config HID_PXRC
        To compile this driver as a module, choose M here: the
        module will be called hid-pxrc.
 
+config HID_RAPOO
+       tristate "Rapoo non-fully HID-compliant devices"
+       help
+       Support for Rapoo devices that are not fully compliant with the
+       HID standard.
+
 config HID_RAZER
        tristate "Razer non-fully HID-compliant devices"
        help
index 361a7daedeb85454114def8afb5f58caeab58a00..e01838239ae64ca2d9b25534c890589476499830 100644 (file)
@@ -113,6 +113,7 @@ obj-$(CONFIG_HID_PLANTRONICS)       += hid-plantronics.o
 obj-$(CONFIG_HID_PLAYSTATION)  += hid-playstation.o
 obj-$(CONFIG_HID_PRIMAX)       += hid-primax.o
 obj-$(CONFIG_HID_PXRC)         += hid-pxrc.o
+obj-$(CONFIG_HID_RAPOO) += hid-rapoo.o
 obj-$(CONFIG_HID_RAZER)        += hid-razer.o
 obj-$(CONFIG_HID_REDRAGON)     += hid-redragon.o
 obj-$(CONFIG_HID_RETRODE)      += hid-retrode.o
index 9c2bf584d9f6f25eb72e0ffbb4db0e247d2a0115..943399e2b44420e0743845686679c4c723f58431 100644 (file)
 #define I2C_PRODUCT_ID_RAYDIUM_4B33    0x4b33
 #define I2C_PRODUCT_ID_RAYDIUM_3118    0x3118
 
+#define USB_VENDOR_ID_RAPOO                    0x24ae
+#define USB_DEVICE_ID_RAPOO_2_4G_RECEIVER      0x2015
+
 #define USB_VENDOR_ID_RAZER            0x1532
 #define USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE   0x010D
 #define USB_DEVICE_ID_RAZER_BLACKWIDOW            0x010e
diff --git a/drivers/hid/hid-rapoo.c b/drivers/hid/hid-rapoo.c
new file mode 100644 (file)
index 0000000..4c81f30
--- /dev/null
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <asm-generic/errno-base.h>
+#include <asm-generic/int-ll64.h>
+#include <linux/bitops.h>
+#include <linux/input.h>
+#include <linux/input-event-codes.h>
+#include <linux/module.h>
+#include <linux/hid.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define RAPOO_BTN_BACK                 0x08
+#define RAPOO_BTN_FORWARD              0x10
+
+static const struct hid_device_id rapoo_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_RAPOO, USB_DEVICE_ID_RAPOO_2_4G_RECEIVER) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, rapoo_devices);
+
+static int rapoo_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+       struct input_dev *input;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               hid_err(hdev, "parse failed\n");
+               return ret;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               hid_err(hdev, "start failed\n");
+               return ret;
+       }
+
+       if (hdev->bus == BUS_USB) {
+               struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+               if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
+                       return 0;
+       }
+
+       input = devm_input_allocate_device(&hdev->dev);
+       if (!input)
+               return -ENOMEM;
+
+       input->name = "Rapoo 2.4G Wireless Mouse";
+       input->phys = "rapoo/input1";
+       input->id.bustype = hdev->bus;
+       input->id.vendor = hdev->vendor;
+       input->id.product = hdev->product;
+       input->id.version = hdev->version;
+
+       __set_bit(EV_KEY, input->evbit);
+       __set_bit(KEY_BACK, input->keybit);
+       __set_bit(KEY_FORWARD, input->keybit);
+
+       ret = input_register_device(input);
+       if (ret)
+               return ret;
+
+       hid_set_drvdata(hdev, input);
+
+       return ret;
+}
+
+static int rapoo_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)
+{
+       struct input_dev *input = hid_get_drvdata(hdev);
+
+       if (!input)
+               return 0;
+
+       if (report->id == 1 && size >= 2) {
+               u8 btn = data[1];
+
+               input_report_key(input, KEY_BACK, btn & RAPOO_BTN_BACK);
+               input_report_key(input, KEY_FORWARD, btn & RAPOO_BTN_FORWARD);
+               input_sync(input);
+               return 1;
+       }
+
+       return 0;
+}
+
+static struct hid_driver rapoo_driver = {
+       .name = "hid-rapoo",
+       .id_table = rapoo_devices,
+       .probe = rapoo_probe,
+       .raw_event = rapoo_raw_event,
+};
+
+module_hid_driver(rapoo_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nguyen Dinh Dang Duong <dangduong31205@gmail.com>");
+MODULE_DESCRIPTION("RAPOO 2.4G Wireless Device Driver");
+