From: Jelle van der Waa <jelle@xxxxxxxx> Add support for the macro keys on the Razer Blackwidow keyboards. By default the macro keys do not work and have to be enabled via a feature report. After being enabled they report as XF86Tools, XF86Launch5-8. Signed-off-by: Jelle van der Waa <jelle@xxxxxxxx> --- drivers/hid/Kconfig | 7 ++++ drivers/hid/Makefile | 1 + drivers/hid/hid-ids.h | 3 ++ drivers/hid/hid-razer.c | 78 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 drivers/hid/hid-razer.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 1ecb5124421c..4f347fe60a63 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1144,6 +1144,13 @@ config HID_ALPS Say Y here if you have a Alps touchpads over i2c-hid or usbhid and want support for its special functionalities. +config HID_RAZER + tristate "Razer Blackwidow keyboard support" + depends on HID + ---help--- + Say Y here if you want the Razer Blackwidow keyboards to enable macro + keys. + endmenu endif # HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 0c03308cfb08..5ae72667b07e 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -107,6 +107,7 @@ obj-$(CONFIG_HID_STEAM) += hid-steam.o obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o +obj-$(CONFIG_HID_RAZER) += hid-razer.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o obj-$(CONFIG_HID_TIVO) += hid-tivo.o obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 76969a22b0f2..d9ab9a048fee 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -960,6 +960,9 @@ #define USB_VENDOR_ID_RAZER 0x1532 #define USB_DEVICE_ID_RAZER_BLADE_14 0x011D +#define USB_DEVICE_ID_RAZER_BLACKWIDOW 0x010e +#define USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE 0x011a +#define USB_DEVICE_ID_RAZER_BLACKWIDOW_2013 0x011b #define USB_VENDOR_ID_REALTEK 0x0bda #define USB_DEVICE_ID_REALTEK_READER 0x0152 diff --git a/drivers/hid/hid-razer.c b/drivers/hid/hid-razer.c new file mode 100644 index 000000000000..d958fd9f9311 --- /dev/null +++ b/drivers/hid/hid-razer.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID driver to enable macro keys on Razer keyboards + * + * Copyright (c) 2019 Jelle van der Waa <jelle@xxxxxxxx> + */ + +#include <linux/hid.h> +#include <linux/module.h> +#include "hid-ids.h" + +#define RAZER_BLACKWIDOW_FEATURE_REPORT 0x00 +#define BUF_SIZE 91 + +static const u8 data[BUF_SIZE] = {0, 0, 0, 0, 0, 0, 2, 0, 4, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0}; + +static const struct hid_device_id razer_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLACKWIDOW) }, + { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLACKWIDOW_2013) }, + { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE) }, + {} +}; + +MODULE_DEVICE_TABLE(hid, razer_devices); + +static int razer_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + struct hid_report_enum *rep_enum; + struct hid_report *rep; + unsigned char *dmabuf; + bool has_ff000002 = false; + int ret = 0; + + dmabuf = kmemdup(data, BUF_SIZE, GFP_KERNEL); + if (!dmabuf) + return -ENOMEM; + + hdev->quirks |= HID_QUIRK_INPUT_PER_APP; + + ret = hid_parse(hdev); + if (ret) + return ret; + + rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; + list_for_each_entry(rep, &rep_enum->report_list, list) { + if (rep->maxfield && rep->field[0]->maxusage) + if (rep->field[0]->usage[0].hid == 0xff000002) + has_ff000002 = true; + } + + if (has_ff000002) { + ret = hid_hw_raw_request(hdev, RAZER_BLACKWIDOW_FEATURE_REPORT, + dmabuf, BUF_SIZE, HID_FEATURE_REPORT, + HID_REQ_SET_REPORT); + if (ret != BUF_SIZE) + hid_err(hdev, "Razer failed to enable macro keys\n"); + } + + kfree(dmabuf); + + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); +} + +static struct hid_driver razer_driver = { + .name = "hid-razer", + .id_table = razer_devices, + .probe = razer_probe, +}; + +module_hid_driver(razer_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jelle van der Waa <jelle@xxxxxxxx"); +MODULE_DESCRIPTION("Razer blackwidow 2013/2014 HID driver"); -- 2.23.0