From 9916af79f6fcca7fc08b1670f975c0351c0e15d9 Mon Sep 17 00:00:00 2001 From: dragonpod <41897470+dragonpod@users.noreply.github.com> Date: Thu, 14 Apr 2022 02:14:58 -0700 Subject: Add support for Razer Blackwidow V3 Mini Hyperspeed (#33) Co-authored-by: ek <41897470+erickuang1@users.noreply.github.com> --- src/include/razerkbd_driver.h | 7 ++ src/lib/razerdevice.c | 2 + src/lib/razerkbd_driver.c | 194 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 200 insertions(+), 3 deletions(-) diff --git a/src/include/razerkbd_driver.h b/src/include/razerkbd_driver.h index 69a7054..99ab348 100644 --- a/src/include/razerkbd_driver.h +++ b/src/include/razerkbd_driver.h @@ -73,10 +73,12 @@ #define USB_DEVICE_ID_RAZER_CYNOSA_LITE 0x023F #define USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK 0x0a24 #define USB_DEVICE_ID_RAZER_HUNTSMAN_MINI 0x0257 +#define USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED 0x0258 #define USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_PRO_WIRED 0x025A #define USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG 0x0266 #define USB_DEVICE_ID_RAZER_HUNTSMAN_V2 0x026c #define USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL 0x026b +#define USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS 0x0271 /* Each keyboard report has 90 bytes*/ #define RAZER_BLACKWIDOW_REPORT_LEN 0x5A @@ -119,6 +121,9 @@ #define RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US 600 #define RAZER_BLACKWIDOW_CHROMA_WAIT_MAX_US 800 +#define RAZER_BLACKWIDOW_V3_WIRELESS_WAIT_MIN_US 4900 +#define RAZER_BLACKWIDOW_V3_WIRELESS_WAIT_MAX_US 5000 + #define RAZER_FIREFLY_WAIT_MIN_US 900 #define RAZER_FIREFLY_WAIT_MAX_US 1000 @@ -138,6 +143,8 @@ bool is_blade_laptop(IOUSBDeviceInterface **usb_dev); ssize_t razer_attr_read_mode_game(IOUSBDeviceInterface **usb_dev, char *buf); ssize_t razer_attr_write_mode_macro(IOUSBDeviceInterface **usb_dev, const char *buf, int count); ssize_t razer_attr_write_mode_macro_effect(IOUSBDeviceInterface **usb_dev, const char *buf, int count); +ssize_t razer_attr_read_mode_get_battery(IOUSBDeviceInterface **usb_dev, char *buf); +ssize_t razer_attr_read_mode_is_charging(IOUSBDeviceInterface **usb_dev, char *buf); ssize_t razer_attr_read_mode_macro_effect(IOUSBDeviceInterface **usb_dev, char *buf); ssize_t razer_attr_write_mode_pulsate(IOUSBDeviceInterface **usb_dev, const char *buf, int count); ssize_t razer_attr_read_mode_pulsate(IOUSBDeviceInterface **usb_dev, char *buf); diff --git a/src/lib/razerdevice.c b/src/lib/razerdevice.c index d2d9bdd..8a3c3ce 100755 --- a/src/lib/razerdevice.c +++ b/src/lib/razerdevice.c @@ -64,6 +64,8 @@ bool is_keyboard(IOUSBDeviceInterface **usb_dev) case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: return true; } diff --git a/src/lib/razerkbd_driver.c b/src/lib/razerkbd_driver.c index 8a1f682..3d8eef1 100644 --- a/src/lib/razerkbd_driver.c +++ b/src/lib/razerkbd_driver.c @@ -130,6 +130,7 @@ ssize_t razer_attr_write_mode_macro_effect(IOUSBDeviceInterface **usb_dev, const case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_standard_set_led_effect(NOSTORE, MACRO_LED, enabled); report.transaction_id.id = 0x1F; break; @@ -150,6 +151,62 @@ ssize_t razer_attr_write_mode_macro_effect(IOUSBDeviceInterface **usb_dev, const return count; } +/** + * Read device file "get_battery" + * + * Returns an integer which needs to be scaled from 0-255 -> 0-100 + */ +ssize_t razer_attr_read_mode_get_battery(IOUSBDeviceInterface **usb_dev, char *buf) +{ + struct razer_report report = razer_chroma_misc_get_battery_level(); + struct razer_report response_report = {0}; + + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: + report.transaction_id.id = 0x1F; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report.transaction_id.id = 0x9F; + break; + } + + response_report = razer_send_payload(usb_dev, &report); + + return sprintf(buf, "%d\n", response_report.arguments[1]); +} + +/** + * Read device file "is_charging" + * + * Returns 0 when not charging, 1 when charging + */ +ssize_t razer_attr_read_mode_is_charging(IOUSBDeviceInterface **usb_dev, char *buf) +{ + struct razer_report report = razer_chroma_misc_get_charging_status(); + struct razer_report response_report = {0}; + + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: + report.transaction_id.id = 0x1F; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report.transaction_id.id = 0x9F; + break; + } + + response_report = razer_send_payload(usb_dev, &report); + + return sprintf(buf, "%d\n", response_report.arguments[1]); +} + /** * Read device file "macro_mode_effect" * @@ -296,9 +353,15 @@ ssize_t razer_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *b case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_effect_none(VARSTORE, BACKLIGHT_LED); report.transaction_id.id = 0x1F; break; + + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_effect_none(VARSTORE, BACKLIGHT_LED); + report.transaction_id.id = 0x9F; + break; case USB_DEVICE_ID_RAZER_ANANSI: report = razer_chroma_standard_set_led_state(VARSTORE, BACKLIGHT_LED, OFF); @@ -365,9 +428,15 @@ ssize_t razer_attr_write_mode_wave(IOUSBDeviceInterface **usb_dev, const char *b case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction, speed); report.transaction_id.id = 0x1F; break; + + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction, speed); + report.transaction_id.id = 0x9F; + break; default: report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction); @@ -413,10 +482,16 @@ ssize_t razer_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const cha case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED); report.transaction_id.id = 0x1F; break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED); + report.transaction_id.id = 0x9F; + break; + case USB_DEVICE_ID_RAZER_ANANSI: report = razer_chroma_standard_set_led_state(VARSTORE, BACKLIGHT_LED, ON); razer_send_payload(usb_dev, &report); @@ -480,11 +555,17 @@ ssize_t razer_attr_write_mode_reactive(IOUSBDeviceInterface **usb_dev, const cha case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: - case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, BACKLIGHT_LED, speed, (struct razer_rgb *)&buf[1]); report.transaction_id.id = 0x1F; break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, BACKLIGHT_LED, speed, (struct razer_rgb *)&buf[1]); + report.transaction_id.id = 0x9F; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2: report = razer_chroma_standard_matrix_effect_reactive(VARSTORE, BACKLIGHT_LED, speed, (struct razer_rgb *)&buf[1]); report.transaction_id.id = 0x3F; // TODO move to a usb_device variable @@ -623,6 +704,7 @@ ssize_t razer_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: if (count == 3) { report = razer_chroma_extended_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]); @@ -634,6 +716,19 @@ ssize_t razer_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char printf("razerkbd: Static mode only accepts RGB (3byte)"); } break; + + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + if (count == 3) + { + report = razer_chroma_extended_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]); + report.transaction_id.id = 0x9F; + razer_send_payload(usb_dev, &report); + } + else + { + printf("razerkbd: Static mode only accepts RGB (3byte)"); + } + break; case USB_DEVICE_ID_RAZER_ANANSI: if (count == 3) @@ -778,6 +873,7 @@ ssize_t razer_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, co case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: if (count == 3) { report = razer_chroma_extended_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]); @@ -790,6 +886,19 @@ ssize_t razer_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, co } break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + if (count == 3) + { + report = razer_chroma_extended_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]); + report.transaction_id.id = 0x9F; + razer_send_payload(usb_dev, &report); + } + else + { + printf("razerkbd: Static mode only accepts RGB (3byte)"); + } + break; + case USB_DEVICE_ID_RAZER_ANANSI: if (count == 3) { @@ -882,6 +991,7 @@ ssize_t razer_attr_write_mode_starlight(IOUSBDeviceInterface **usb_dev, const ch case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: if (count == 7) { report = razer_chroma_extended_matrix_effect_starlight_dual(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1], (struct razer_rgb *)&buf[4]); @@ -903,6 +1013,28 @@ ssize_t razer_attr_write_mode_starlight(IOUSBDeviceInterface **usb_dev, const ch razer_send_payload(usb_dev, &report); break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + if (count == 7) + { + report = razer_chroma_extended_matrix_effect_starlight_dual(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1], (struct razer_rgb *)&buf[4]); + } + else if (count == 4) + { + report = razer_chroma_extended_matrix_effect_starlight_single(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1]); + } + else if (count == 1) + { + report = razer_chroma_extended_matrix_effect_starlight_random(VARSTORE, BACKLIGHT_LED, buf[0]); + } + else + { + printf("razerkbd: Starlight only accepts Speed (1byte). Speed, RGB (4byte). Speed, RGB, RGB (7byte)"); + break; + } + report.transaction_id.id = 0x9F; + razer_send_payload(usb_dev, &report); + break; + case USB_DEVICE_ID_RAZER_TARTARUS_V2: if (count == 7) { @@ -1058,6 +1190,7 @@ ssize_t razer_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: if (count == 3) { // Single colour mode report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]); @@ -1079,6 +1212,28 @@ ssize_t razer_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char razer_send_payload(usb_dev, &report); break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + if (count == 3) + { // Single colour mode + report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]); + } + else if (count == 6) + { // Dual colour mode + report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]); + } + else if (count == 1) + { // "Random" colour mode + report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED); + } + else + { + printf("razerkbd: Breathing only accepts '1' (1byte). RGB (3byte). RGB, RGB (6byte)"); + break; + } + report.transaction_id.id = 0x9F; + razer_send_payload(usb_dev, &report); + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2: switch (count) { @@ -1240,10 +1395,16 @@ ssize_t razer_attr_write_mode_custom(IOUSBDeviceInterface **usb_dev, const char case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_effect_custom_frame(); report.transaction_id.id = 0x1F; break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_effect_custom_frame(); + report.transaction_id.id = 0x9F; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2: report = razer_chroma_standard_matrix_effect_custom_frame(VARSTORE); // Possibly could use VARSTORE report.transaction_id.id = 0x3F; // TODO move to a usb_device variable @@ -1315,10 +1476,16 @@ ssize_t razer_attr_write_set_brightness(IOUSBDeviceInterface **usb_dev, ushort b case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_brightness(VARSTORE, BACKLIGHT_LED, brightness); report.transaction_id.id = 0x1F; break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_brightness(VARSTORE, BACKLIGHT_LED, brightness); + report.transaction_id.id = 0x9F; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH: case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION: case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012: @@ -1392,11 +1559,18 @@ ushort razer_attr_read_set_brightness(IOUSBDeviceInterface **usb_dev) case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_get_brightness(VARSTORE, BACKLIGHT_LED); report.transaction_id.id = 0x1F; is_matrix_brightness = true; break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_get_brightness(VARSTORE, BACKLIGHT_LED); + report.transaction_id.id = 0x9F; + is_matrix_brightness = true; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH: case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION: case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012: @@ -1507,11 +1681,17 @@ ssize_t razer_attr_write_matrix_custom_frame(IOUSBDeviceInterface **usb_dev, con case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: - case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: report = razer_chroma_extended_matrix_set_custom_frame(row_id, start_col, stop_col, (unsigned char *)&buf[offset]); report.transaction_id.id = 0x1F; break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: + report = razer_chroma_extended_matrix_set_custom_frame(row_id, start_col, stop_col, (unsigned char *)&buf[offset]); + report.transaction_id.id = 0x9F; + break; + case USB_DEVICE_ID_RAZER_DEATHSTALKER_CHROMA: report = razer_chroma_misc_one_row_set_custom_frame(start_col, stop_col, (unsigned char *)&buf[offset]); break; @@ -1565,6 +1745,8 @@ static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report uint report_index; uint response_index; + int wait_us = RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US; + switch (product) { case USB_DEVICE_ID_RAZER_ANANSI: @@ -1580,8 +1762,14 @@ static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_ANALOG: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2: case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TKL: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRED: + report_index = 0x03; + response_index = 0x03; + break; + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS: report_index = 0x03; response_index = 0x03; + wait_us = RAZER_BLACKWIDOW_V3_WIRELESS_WAIT_MIN_US; break; default: report_index = 0x01; @@ -1589,7 +1777,7 @@ static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report break; } - return razer_get_usb_response(usb_dev, report_index, request_report, response_index, response_report, RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US); + return razer_get_usb_response(usb_dev, report_index, request_report, response_index, response_report, wait_us); } /** -- cgit v1.2.3