Skip to content

Commit 047b618

Browse files
jellyJiri Kosina
authored andcommitted
HID: Add driver for Razer Blackwidow keyboards
Add a driver to enable the macro keys (M1 - M5) by default, these are mapped to XF86Tools and XF86Launch5 - XF86Launch8. The driver remaps them by default to macro keys with an option to retain the old mapping which users most likely already use as there are many scripts to enable the macro keys available on Github and other websites. Signed-off-by: Jelle van der Waa <jvanderwaa@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent a254a9d commit 047b618

4 files changed

Lines changed: 136 additions & 0 deletions

File tree

drivers/hid/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,13 @@ config PLAYSTATION_FF
929929
Say Y here if you would like to enable force feedback support for
930930
PlayStation game controllers.
931931

932+
config HID_RAZER
933+
tristate "Razer non-fully HID-compliant devices"
934+
depends on HID
935+
help
936+
Support for Razer devices that are not fully compliant with the
937+
HID standard.
938+
932939
config HID_PRIMAX
933940
tristate "Primax non-fully HID-compliant devices"
934941
depends on HID

drivers/hid/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o
9999
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
100100
obj-$(CONFIG_HID_PLAYSTATION) += hid-playstation.o
101101
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
102+
obj-$(CONFIG_HID_RAZER) += hid-razer.o
102103
obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
103104
obj-$(CONFIG_HID_RETRODE) += hid-retrode.o
104105
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \

drivers/hid/hid-ids.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,9 @@
10301030
#define I2C_PRODUCT_ID_RAYDIUM_3118 0x3118
10311031

10321032
#define USB_VENDOR_ID_RAZER 0x1532
1033+
#define USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE 0x010D
1034+
#define USB_DEVICE_ID_RAZER_BLACKWIDOW 0x010e
1035+
#define USB_DEVICE_ID_RAZER_BLACKWIDOW_CLASSIC 0x011b
10331036
#define USB_DEVICE_ID_RAZER_BLADE_14 0x011D
10341037

10351038
#define USB_VENDOR_ID_REALTEK 0x0bda

drivers/hid/hid-razer.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* HID driver for gaming keys on Razer Blackwidow gaming keyboards
4+
* Macro Key Keycodes: M1 = 191, M2 = 192, M3 = 193, M4 = 194, M5 = 195
5+
*
6+
* Copyright (c) 2021 Jelle van der Waa <jvanderwaa@redhat.com>
7+
*/
8+
9+
#include <linux/device.h>
10+
#include <linux/hid.h>
11+
#include <linux/module.h>
12+
#include <linux/random.h>
13+
#include <linux/sched.h>
14+
#include <linux/usb.h>
15+
#include <linux/wait.h>
16+
17+
#include "hid-ids.h"
18+
19+
#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
20+
21+
#define RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE 91
22+
23+
static bool macro_key_remapping = 1;
24+
module_param(macro_key_remapping, bool, 0644);
25+
MODULE_PARM_DESC(macro_key_remapping, " on (Y) off (N)");
26+
27+
28+
static unsigned char blackwidow_init[RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE] = {
29+
0x00,
30+
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04,
31+
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41+
0x04, 0x00
42+
};
43+
44+
static int razer_input_mapping(struct hid_device *hdev,
45+
struct hid_input *hi, struct hid_field *field,
46+
struct hid_usage *usage, unsigned long **bit, int *max)
47+
{
48+
49+
if (!macro_key_remapping)
50+
return 0;
51+
52+
if ((usage->hid & HID_UP_KEYBOARD) != HID_UP_KEYBOARD)
53+
return 0;
54+
55+
switch (usage->hid & ~HID_UP_KEYBOARD) {
56+
case 0x68:
57+
map_key_clear(KEY_MACRO1);
58+
return 1;
59+
case 0x69:
60+
map_key_clear(KEY_MACRO2);
61+
return 1;
62+
case 0x6a:
63+
map_key_clear(KEY_MACRO3);
64+
return 1;
65+
case 0x6b:
66+
map_key_clear(KEY_MACRO4);
67+
return 1;
68+
case 0x6c:
69+
map_key_clear(KEY_MACRO5);
70+
return 1;
71+
}
72+
73+
return 0;
74+
}
75+
76+
static int razer_probe(struct hid_device *hdev, const struct hid_device_id *id)
77+
{
78+
char *buf;
79+
int ret = 0;
80+
81+
ret = hid_parse(hdev);
82+
if (ret)
83+
return ret;
84+
85+
/*
86+
* Only send the enable macro keys command for the third device
87+
* identified as mouse input.
88+
*/
89+
if (hdev->type == HID_TYPE_USBMOUSE) {
90+
buf = kmemdup(blackwidow_init, RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE, GFP_KERNEL);
91+
if (buf == NULL)
92+
return -ENOMEM;
93+
94+
ret = hid_hw_raw_request(hdev, 0, buf, RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE,
95+
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
96+
if (ret != RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE)
97+
hid_err(hdev, "failed to enable macro keys: %d\n", ret);
98+
99+
kfree(buf);
100+
}
101+
102+
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
103+
}
104+
105+
static const struct hid_device_id razer_devices[] = {
106+
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,
107+
USB_DEVICE_ID_RAZER_BLACKWIDOW) },
108+
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,
109+
USB_DEVICE_ID_RAZER_BLACKWIDOW_CLASSIC) },
110+
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,
111+
USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE) },
112+
{ }
113+
};
114+
MODULE_DEVICE_TABLE(hid, razer_devices);
115+
116+
static struct hid_driver razer_driver = {
117+
.name = "razer",
118+
.id_table = razer_devices,
119+
.input_mapping = razer_input_mapping,
120+
.probe = razer_probe,
121+
};
122+
module_hid_driver(razer_driver);
123+
124+
MODULE_AUTHOR("Jelle van der Waa <jvanderwaa@redhat.com>");
125+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)