Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Razer BlackWidow V4 X #2209

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ The devices below are fully feature supported by OpenRazer, which means all avai
| Razer BlackWidow V4 Pro | 1532:028D |
| Razer DeathStalker V2 Pro (Wireless) | 1532:0290 |
| Razer DeathStalker V2 Pro (Wired) | 1532:0292 |
| Razer BlackWidow V4 X | 1532:0293 |
| Razer Ornata V3 X | 1532:0294 |
| Razer DeathStalker V2 Pro TKL (Wireless) | 1532:0296 |
| Razer DeathStalker V2 Pro TKL (Wired) | 1532:0298 |
Expand Down
23 changes: 23 additions & 0 deletions daemon/openrazer_daemon/hardware/keyboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,29 @@ class RazerBlackWidowV4(_RippleKeyboard):
DEVICE_IMAGE = "https://dl.razerzone.com/src2/13219/13219-1-en-v1.png"


class RazerBlackWidowV4X(_RippleKeyboard):
"""
Class for the Razer BlackWidow V4 X
"""
EVENT_FILE_REGEX = re.compile(r'.*Razer_Razer_BlackWidow_V4_X(-if01)?-event-kbd')

USB_VID = 0x1532
USB_PID = 0x0293
HAS_MATRIX = True
WAVE_DIRS = (1, 2)
MATRIX_DIMS = [8, 23]
POLL_RATES = [125, 250, 500, 1000, 2000, 4000, 8000]
METHODS = ['get_device_type_keyboard', 'set_wave_effect', 'set_wheel_effect', 'set_static_effect', 'set_spectrum_effect',
'set_reactive_effect', 'set_none_effect', 'set_breath_random_effect', 'set_breath_single_effect', 'set_breath_dual_effect',
'set_custom_effect', 'set_key_row', 'get_game_mode', 'set_game_mode', 'get_macro_mode', 'set_macro_mode',
'get_macro_effect', 'set_macro_effect', 'get_macros', 'delete_macro', 'add_macro',
'set_starlight_random_effect', 'set_starlight_single_effect', 'set_starlight_dual_effect',
'get_poll_rate', 'set_poll_rate', 'get_supported_poll_rates',
'set_ripple_effect', 'set_ripple_effect_random_colour']

DEVICE_IMAGE = "https://m.media-amazon.com/images/I/71qoXjgRb-L._AC_SL1500_.jpg"


class RazerBlackWidowV4Pro(_RippleKeyboard):
"""
Class for the Razer BlackWidow V4 Pro
Expand Down
26 changes: 26 additions & 0 deletions driver/razerkbd_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ static void razer_get_report_params(struct usb_device *usb_dev, uint *report_ind
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_JP:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
*report_index = 0x02;
*response_index = 0x02;
*wait_min = RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US;
Expand Down Expand Up @@ -430,6 +431,7 @@ static void razer_set_device_mode(struct razer_kbd_device *device, unsigned char
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRED:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED:
case USB_DEVICE_ID_RAZER_ORNATA_V3_X:
Expand Down Expand Up @@ -1157,6 +1159,10 @@ static ssize_t razer_attr_read_device_type(struct device *dev, struct device_att
device_type = "Razer BlackWidow V4\n";
break;

case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
device_type = "Razer BlackWidow V4 X\n";
break;

case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
device_type = "Razer BlackWidow V4 Pro\n";
break;
Expand Down Expand Up @@ -1579,6 +1585,7 @@ static ssize_t razer_attr_write_matrix_effect_none(struct device *dev, struct de
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_extended_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
request.transaction_id.id = 0x1F;
Expand Down Expand Up @@ -1664,6 +1671,7 @@ static ssize_t razer_attr_write_matrix_effect_wave(struct device *dev, struct de
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_extended_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
request.transaction_id.id = 0x1F;
Expand Down Expand Up @@ -1702,6 +1710,7 @@ static ssize_t razer_attr_write_matrix_effect_wheel(struct device *dev, struct d

switch(device->usb_pid) {
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_extended_matrix_effect_wheel(VARSTORE, BACKLIGHT_LED, direction);
request.transaction_id.id = 0x1F;
Expand Down Expand Up @@ -1761,6 +1770,7 @@ static ssize_t razer_attr_write_matrix_effect_spectrum(struct device *dev, struc
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLADE_15_BASE_2022:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
request.transaction_id.id = 0x1F;
Expand Down Expand Up @@ -1835,6 +1845,7 @@ static ssize_t razer_attr_write_matrix_effect_reactive(struct device *dev, struc
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRED:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED:
Expand Down Expand Up @@ -1995,6 +2006,7 @@ static ssize_t razer_attr_write_matrix_effect_static(struct device *dev, struct
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRED:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED:
Expand Down Expand Up @@ -2134,6 +2146,7 @@ static ssize_t razer_attr_write_matrix_effect_starlight(struct device *dev, stru
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
if (count == 7) {
request = razer_chroma_extended_matrix_effect_starlight_dual(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb*)&buf[1], (struct razer_rgb*)&buf[4]);
Expand Down Expand Up @@ -2342,6 +2355,7 @@ static ssize_t razer_attr_write_matrix_effect_breath(struct device *dev, struct
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
if (count == 3) { // Single colour mode
request = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
Expand Down Expand Up @@ -2543,6 +2557,7 @@ static ssize_t razer_attr_write_matrix_effect_custom(struct device *dev, struct
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG:
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
request = razer_chroma_extended_matrix_effect_custom_frame();
request.transaction_id.id = 0x1F;
break;
Expand Down Expand Up @@ -2685,6 +2700,7 @@ static ssize_t razer_attr_write_matrix_brightness(struct device *dev, struct dev
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_extended_matrix_brightness(VARSTORE, BACKLIGHT_LED, brightness);
request.transaction_id.id = 0x1F;
Expand Down Expand Up @@ -2773,6 +2789,7 @@ static ssize_t razer_attr_read_matrix_brightness(struct device *dev, struct devi
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_extended_matrix_get_brightness(VARSTORE, BACKLIGHT_LED);
request.transaction_id.id = 0x1F;
Expand Down Expand Up @@ -2941,6 +2958,7 @@ static ssize_t razer_attr_write_matrix_custom_frame(struct device *dev, struct d
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG:
case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
request = razer_chroma_extended_matrix_set_custom_frame(row_id, start_col, stop_col, (unsigned char*)&buf[offset]);
request.transaction_id.id = 0x1F;
break;
Expand Down Expand Up @@ -3041,6 +3059,7 @@ static ssize_t razer_attr_read_poll_rate(struct device *dev, struct device_attri
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TENKEYLESS:
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_misc_get_polling_rate2();
request.transaction_id.id = 0x1f;
Expand Down Expand Up @@ -3097,6 +3116,7 @@ static ssize_t razer_attr_write_poll_rate(struct device *dev, struct device_attr
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TENKEYLESS:
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
request = razer_chroma_misc_set_polling_rate2(polling_rate, 0x00);
request.transaction_id.id = 0x1f;
Expand Down Expand Up @@ -3306,6 +3326,7 @@ static int razer_event(struct hid_device *hdev, struct hid_field *field, struct
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2:
Expand Down Expand Up @@ -3623,6 +3644,7 @@ static int razer_raw_event(struct hid_device *hdev, struct hid_report *report, u
switch (device->usb_pid) {
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
case USB_DEVICE_ID_RAZER_ORNATA_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED:
Expand All @@ -3645,6 +3667,7 @@ static int razer_kbd_input_mapping(struct hid_device *hdev, struct hid_input *hi
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2:
Expand Down Expand Up @@ -3901,6 +3924,7 @@ static int razer_kbd_probe(struct hid_device *hdev, const struct hid_device_id *
break;

case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_matrix_effect_wheel); // Wheel effect
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_matrix_effect_wave); // Wave effect
Expand Down Expand Up @@ -4354,6 +4378,7 @@ static void razer_kbd_disconnect(struct hid_device *hdev)
break;

case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO:
device_remove_file(&hdev->dev, &dev_attr_matrix_effect_wheel); // Wheel
device_remove_file(&hdev->dev, &dev_attr_matrix_effect_wave); // Wave effect
Expand Down Expand Up @@ -4687,6 +4712,7 @@ static const struct hid_device_id razer_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRED) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_BLACKWIDOW_V4) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS) },
Expand Down
1 change: 1 addition & 0 deletions driver/razerkbd_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#define USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_PRO 0x028D
#define USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRELESS 0x0290
#define USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRED 0x0292
#define USB_DEVICE_ID_RAZER_BLACKWIDOW_V4_X 0x0293
#define USB_DEVICE_ID_RAZER_ORNATA_V3_X 0x0294
#define USB_DEVICE_ID_RAZER_DEATHSTALKER_V2 0x0295
#define USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS 0x0296
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
<modalias>usb:v1532p028Dd*</modalias>
<modalias>usb:v1532p0290d*</modalias>
<modalias>usb:v1532p0292d*</modalias>
<modalias>usb:v1532p0293d*</modalias>
<modalias>usb:v1532p0294d*</modalias>
<modalias>usb:v1532p0295d*</modalias>
<modalias>usb:v1532p0296d*</modalias>
Expand Down
2 changes: 1 addition & 1 deletion install_files/udev/99-razer.rules
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ATTRS{idProduct}=="0013|0016|0020|0024|0025|0029|002e|002f|0032|0034|0036|0037|0
ENV{ID_RAZER_CHROMA}="1", ENV{RAZER_DRIVER}="razermouse"

# Keyboards
ATTRS{idProduct}=="010d|010e|010f|0111|0113|0118|011a|011b|011c|0201|0202|0203|0204|0205|0207|0208|0209|020f|0210|0211|0214|0216|0217|021a|021e|021f|0220|0221|0224|0225|0226|0227|0228|022a|022b|022c|022d|022f|0232|0233|0234|0235|0237|0239|023a|023b|023f|0240|0241|0243|0245|0246|024a|024b|024c|024d|024e|0252|0253|0255|0256|0257|0258|0259|025a|025d|025e|0266|0269|026a|026b|026c|026d|026e|026f|0270|0271|0276|0279|027a|0282|0287|028a|028b|028c|028d|0290|0292|0294|0295|0296|0298|029e|029f|02a0|02a2|0a24", \
ATTRS{idProduct}=="010d|010e|010f|0111|0113|0118|011a|011b|011c|0201|0202|0203|0204|0205|0207|0208|0209|020f|0210|0211|0214|0216|0217|021a|021e|021f|0220|0221|0224|0225|0226|0227|0228|022a|022b|022c|022d|022f|0232|0233|0234|0235|0237|0239|023a|023b|023f|0240|0241|0243|0245|0246|024a|024b|024c|024d|024e|0252|0253|0255|0256|0257|0258|0259|025a|025d|025e|0266|0269|026a|026b|026c|026d|026e|026f|0270|0271|0276|0279|027a|0282|0287|028a|028b|028c|028d|0290|0292|0293|0294|0295|0296|0298|029e|029f|02a0|02a2|0a24", \
ATTRS{idVendor}=="1532", \
ENV{ID_RAZER_CHROMA}="1", ENV{RAZER_DRIVER}="razerkbd"

Expand Down
26 changes: 26 additions & 0 deletions pylib/openrazer/_fake_driver/razerblackwidowv4x.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# DO NOT EDIT THIS FILE!
# You can regenerate all fake driver files with ./scripts/generate_all_fake_drivers.sh -f
[device]
dir_name = 0003:1532:0293.0001
name = Razer BlackWidow V4 X
files = rw,device_mode,0x0000
r,device_serial,XX0000000293
r,device_type,%(name)s
r,firmware_version,v1.0
rw,game_led_state,0
r,kbd_layout,01
rw,macro_led_effect,0
rw,macro_led_state,0
rw,matrix_brightness,0
w,matrix_custom_frame
w,matrix_effect_breath
w,matrix_effect_custom
w,matrix_effect_none
w,matrix_effect_reactive
w,matrix_effect_spectrum
w,matrix_effect_starlight
w,matrix_effect_static
w,matrix_effect_wave
w,matrix_effect_wheel
rw,poll_rate,500
r,version,1.0.0