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 +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_DESCRIPTION("RAPOO 2.4G Wireless Device Driver"); +