diff mbox series

HID: Add support for Razer Blackwidow keyboards

Message ID 20190705221605.28293-1-jelle@vdwaa.nl (mailing list archive)
State Superseded
Delegated to: Jiri Kosina
Headers show
Series HID: Add support for Razer Blackwidow keyboards | expand

Commit Message

Jelle van der Waa July 5, 2019, 10:16 p.m. UTC
Add support for the macro keys on the Razor 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@vdwaa.nl>
---
 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

Comments

Jelle van der Waa Aug. 17, 2019, 8:59 p.m. UTC | #1
On 07/06/19 at 12:16am, Jelle van der Waa wrote:
> Add support for the macro keys on the Razor 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@vdwaa.nl>

Any update?
Jiri Kosina Oct. 1, 2019, 2:26 p.m. UTC | #2
On Sat, 6 Jul 2019, Jelle van der Waa wrote:

> Add support for the macro keys on the Razor Blackwidow keyboards. By

So I guess it should say 'Razer' here?

> 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@vdwaa.nl>
> ---
>  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 3872e03d9a59..0b4bc464fc11 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -1135,6 +1135,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 cc5d827c9164..417168a88193 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -121,6 +121,7 @@ obj-$(CONFIG_HID_XINMO)		+= hid-xinmo.o
>  obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
>  obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
>  obj-$(CONFIG_HID_VIEWSONIC)	+= hid-viewsonic.o
> +obj-$(CONFIG_HID_RAZER)		+= hid-razer.o

Please keep the list sorted, as it was before.

>  wacom-objs			:= wacom_wac.o wacom_sys.o
>  obj-$(CONFIG_HID_WACOM)		+= wacom.o
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index b032d3899fa3..8f6ce553b52c 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -955,6 +955,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@vdwaa.nl>
> + */
> +
> +#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);

Can't this all be done in userspace via udev script through hidraw?

Thanks,
Jelle van der Waa Oct. 13, 2019, 3:17 p.m. UTC | #3
On 10/01/19 at 04:26pm, Jiri Kosina wrote:
> On Sat, 6 Jul 2019, Jelle van der Waa wrote:
> 
> > Add support for the macro keys on the Razor Blackwidow keyboards. By
> 
> So I guess it should say 'Razer' here?
> 
> > 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@vdwaa.nl>
> > ---
> >  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 3872e03d9a59..0b4bc464fc11 100644
> > --- a/drivers/hid/Kconfig
> > +++ b/drivers/hid/Kconfig
> > @@ -1135,6 +1135,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 cc5d827c9164..417168a88193 100644
> > --- a/drivers/hid/Makefile
> > +++ b/drivers/hid/Makefile
> > @@ -121,6 +121,7 @@ obj-$(CONFIG_HID_XINMO)		+= hid-xinmo.o
> >  obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
> >  obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
> >  obj-$(CONFIG_HID_VIEWSONIC)	+= hid-viewsonic.o
> > +obj-$(CONFIG_HID_RAZER)		+= hid-razer.o
> 
> Please keep the list sorted, as it was before.
> 
> >  wacom-objs			:= wacom_wac.o wacom_sys.o
> >  obj-$(CONFIG_HID_WACOM)		+= wacom.o
> > diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> > index b032d3899fa3..8f6ce553b52c 100644
> > --- a/drivers/hid/hid-ids.h
> > +++ b/drivers/hid/hid-ids.h
> > @@ -955,6 +955,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@vdwaa.nl>
> > + */
> > +
> > +#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);
> 
> Can't this all be done in userspace via udev script through hidraw?

I guess it could, but that would mean everyone has to install a package
for it being able to work.
diff mbox series

Patch

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 3872e03d9a59..0b4bc464fc11 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1135,6 +1135,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 cc5d827c9164..417168a88193 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -121,6 +121,7 @@  obj-$(CONFIG_HID_XINMO)		+= hid-xinmo.o
 obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
 obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
 obj-$(CONFIG_HID_VIEWSONIC)	+= hid-viewsonic.o
+obj-$(CONFIG_HID_RAZER)		+= hid-razer.o
 
 wacom-objs			:= wacom_wac.o wacom_sys.o
 obj-$(CONFIG_HID_WACOM)		+= wacom.o
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b032d3899fa3..8f6ce553b52c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -955,6 +955,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@vdwaa.nl>
+ */
+
+#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@vdwaa.nl");
+MODULE_DESCRIPTION("Razer blackwidow 2013/2014 HID driver");