summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyen Dinh Dang Duong <dangduong31205@gmail.com>2025-06-28 00:04:23 +0700
committerJiri Kosina <jkosina@suse.com>2026-01-10 09:52:37 +0100
commitb3b1c68fb726907ea35ac172906705fe62c7fdaf (patch)
treeacf2b83dc1871bc3619a6ab86027d25625cb9dd8
parentd7f6629bffdcb962d383ef8c9a30afef81e997fe (diff)
HID: rapoo: Add support for side buttons on RAPOO 0x2015 mouse
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>
-rw-r--r--drivers/hid/Kconfig6
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hid-rapoo.c101
4 files changed, 111 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 920a64b66b25..68247a539e08 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -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
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 361a7daedeb8..e01838239ae6 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -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
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9c2bf584d9f6..943399e2b444 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1166,6 +1166,9 @@
#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
index 000000000000..4c81f3086de4
--- /dev/null
+++ b/drivers/hid/hid-rapoo.c
@@ -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");
+