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

Support Razer Pro Type Ultra keyboard #2136

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ The devices below are fully feature supported by OpenRazer, which means all avai
| Razer Blade 14 (2021) | 1532:0270 |
| Razer BlackWidow V3 Mini Hyperspeed (Wireless)| 1532:0271 |
| Razer Blade 15 Advanced (Mid 2021) | 1532:0276 |
| Razer Pro Type Ultra (Wired) | 1432:0277 |
| Razer Blade 17 Pro (Mid 2021) | 1532:0279 |
| Razer Blade 15 Base (2022) | 1432:027A |
| Razer Pro Type Ultra (Wireless) | 1432:027B |
| Razer Huntsman Mini Analog | 1532:0282 |
| Razer Blade 15 Advanced (Early 2022) | 1532:028A |
| Razer Blade 17 (2022) | 1532:028B |
Expand Down
22 changes: 22 additions & 0 deletions daemon/openrazer_daemon/hardware/keyboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -1946,3 +1946,25 @@ class RazerBlade182023(_RippleKeyboard):
'set_ripple_effect', 'set_ripple_effect_random_colour']

DEVICE_IMAGE = "https://dl.razerzone.com/src2/9676/9676-1-en-v1.png"


class RazerProTypeUltraWired(_RazerDeviceBrightnessSuspend):
"""
Class for the Razer Pro Type Ultra (Wired)
"""
EVENT_FILE_REGEX = re.compile(r'.*Razer_Pro_Type_Ultra(-if01)?-event-kbd')

USB_VID = 0x1532
USB_PID = 0x0277
METHODS = ['get_device_type_keyboard', 'set_static_effect', 'set_breath_single_effect', 'get_battery', 'is_charging', 'get_keyboard_layout']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The device really doesn't support more effects than this? At least set_none_effect maybe to turn off the lighting? Or brightness controls?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has brightness controls, both classes inherit RazerDeviceBrightnessSuspend so there's no need to declare those methods in the METHODS property.
Here are a few screenshots of that device from Razer Synapse on Windows to view the exact functionality:

Screenshot 2023-09-25 230124

Screenshot 2023-09-25 230146

Screenshot 2023-09-25 230231


DEVICE_IMAGE = "https://assets2.razerzone.com/images/pnx.assets/60218b01153078857f2fe8f0f62071eb/razer-pro-type-ultra-hero-1920x699-new.jpg"


class RazerProTypeUltraWireless(RazerProTypeUltraWired):
"""
Class for the Razer Pro Type Ultra (Wireless)
"""
EVENT_FILE_REGEX = re.compile(r'.*Razer_Pro_Type_Ultra_000000000000(-if01)?-event-kbd')

USB_PID = 0x027B
21 changes: 21 additions & 0 deletions driver/razerchromacommon.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,27 @@ struct razer_report razer_chroma_extended_matrix_set_custom_frame2(unsigned char
return report;
}

struct razer_report razer_pro_type_matrix_effect_static(unsigned char variable_storage, unsigned char led_id, unsigned char brightness)
{
struct razer_report report = razer_chroma_extended_matrix_effect_base(0x09, variable_storage, led_id, 0x01);

report.arguments[4] = 0x01;
report.arguments[5] = 0x01;
report.arguments[6] = brightness;
return report;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced making a custom function for this device is necessary.

The razer_chroma_extended_matrix_effect_static function doesn't work for this device? In the pcap I see rgb=0xFFFFFF there except that report.argument[4] = 0x01 , everything else looks to be the same.

Same with breathing effect.

}

struct razer_report razer_pro_type_matrix_effect_breathing(unsigned char variable_storage, unsigned char led_id, unsigned char brightness)
{
struct razer_report report = razer_chroma_extended_matrix_effect_base(0x09, variable_storage, led_id, 0x02);

report.arguments[4] = 0x01;
report.arguments[5] = 0x01;
report.arguments[6] = brightness;

return report;
}

/*
* Extended Matrix Effects (Mouse)
*/
Expand Down
2 changes: 2 additions & 0 deletions driver/razerchromacommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ struct razer_report razer_chroma_extended_matrix_brightness(unsigned char variab
struct razer_report razer_chroma_extended_matrix_get_brightness(unsigned char variable_storage, unsigned char led_id);
struct razer_report razer_chroma_extended_matrix_set_custom_frame(unsigned char row_index, unsigned char start_col, unsigned char stop_col, unsigned char *rgb_data);
struct razer_report razer_chroma_extended_matrix_set_custom_frame2(unsigned char row_index, unsigned char start_col, unsigned char stop_col, unsigned char *rgb_data, size_t packetLength);
struct razer_report razer_pro_type_matrix_effect_static(unsigned char variable_storage, unsigned char led_id, unsigned char brightness);
struct razer_report razer_pro_type_matrix_effect_breathing(unsigned char variable_storage, unsigned char led_id, unsigned char brightness);

/*
* Extended Matrix Effects (Mouse) Functions
Expand Down
65 changes: 55 additions & 10 deletions driver/razerkbd_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,14 @@ static int razer_get_report(struct usb_device *usb_dev, struct razer_report *req
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_PRO_TYPE_ULTRA_WIRED:
report_index = 0x02;
response_index = 0x02;
return razer_get_usb_response(usb_dev, report_index, request, response_index, response, RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US, RAZER_BLACKWIDOW_CHROMA_WAIT_MAX_US);
break;
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_WIRELESS:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
report_index = 0x02;
response_index = 0x02;
return razer_get_usb_response(usb_dev, report_index, request, response_index, response, RAZER_DEATHSTALKER_V2_WIRELESS_WAIT_MIN_US, RAZER_DEATHSTALKER_V2_WIRELESS_WAIT_MAX_US);
Expand Down Expand Up @@ -1116,6 +1118,14 @@ static ssize_t razer_attr_read_device_type(struct device *dev, struct device_att
device_type = "Razer Blade 18 (2023)\n";
break;

case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED:
device_type = "Razer Pro Type Ultra (Wired)\n";
break;

case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
device_type = "Razer Pro Type Ultra (Wireless)\n";
break;

default:
device_type = "Unknown Device\n";
}
Expand Down Expand Up @@ -1793,16 +1803,6 @@ static ssize_t razer_attr_write_matrix_effect_static(struct device *dev, struct

switch (device->usb_pid) {

case USB_DEVICE_ID_RAZER_TARTARUS_V2:
if (count != 3) {
printk(KERN_WARNING "razerkbd: Static mode only accepts RGB (3byte)\n");
return -EINVAL;
}
request = razer_chroma_extended_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
request.transaction_id.id = 0x1F;
razer_send_payload(device, &request, &response);
break;

case USB_DEVICE_ID_RAZER_ORBWEAVER:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_ESSENTIAL:
case USB_DEVICE_ID_RAZER_DEATHSTALKER_EXPERT:
Expand Down Expand Up @@ -1917,6 +1917,7 @@ static ssize_t razer_attr_write_matrix_effect_static(struct device *dev, struct
razer_send_payload(device, &request, &response);
break;

case USB_DEVICE_ID_RAZER_TARTARUS_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
case USB_DEVICE_ID_RAZER_CYNOSA_V2:
case USB_DEVICE_ID_RAZER_ORNATA_V2:
Expand Down Expand Up @@ -1965,6 +1966,17 @@ static ssize_t razer_attr_write_matrix_effect_static(struct device *dev, struct
razer_send_payload(device, &request, &response);
break;

case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
if (count != 1) {
printk(KERN_WARNING "razerkbd: Static mode only accepts brightness level (1byte).\n");
return -EINVAL;
}
request = razer_pro_type_matrix_effect_static(VARSTORE, BACKLIGHT_LED, buf[0]);
request.transaction_id.id = 0x1F;
razer_send_payload(device, &request, &response);
break;

default:
printk(KERN_WARNING "razerkbd: Cannot set static mode for this device\n");
return -EINVAL;
Expand Down Expand Up @@ -2300,6 +2312,17 @@ static ssize_t razer_attr_write_matrix_effect_breath(struct device *dev, struct
}
break;

case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
if (count != 1) {
printk(KERN_WARNING "razerkbd: Breathing only accepts brightness level (1byte).\n");
return -EINVAL;
}
request = razer_pro_type_matrix_effect_breathing(VARSTORE, BACKLIGHT_LED, buf[0]);
request.transaction_id.id = 0x1F;
razer_send_payload(device, &request, &response);
break;

default:
switch(count) {
case 3: // Single colour mode
Expand Down Expand Up @@ -2573,6 +2596,8 @@ static ssize_t razer_attr_write_matrix_brightness(struct device *dev, struct dev
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_PRO_TYPE_ULTRA_WIRED:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
request = razer_chroma_extended_matrix_brightness(VARSTORE, BACKLIGHT_LED, brightness);
request.transaction_id.id = 0x1F;
break;
Expand Down Expand Up @@ -2659,6 +2684,8 @@ static ssize_t razer_attr_read_matrix_brightness(struct device *dev, struct devi
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2_TENKEYLESS:
case USB_DEVICE_ID_RAZER_HUNTSMAN_V2:
case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
request = razer_chroma_extended_matrix_get_brightness(VARSTORE, BACKLIGHT_LED);
request.transaction_id.id = 0x1F;
break;
Expand Down Expand Up @@ -3909,6 +3936,14 @@ static int razer_kbd_probe(struct hid_device *hdev, const struct hid_device_id *
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_macro_led_state); // Enable macro LED
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_macro_led_effect); // Change macro LED effect (static, flashing)
break;

case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_matrix_effect_static); // Static effect
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_matrix_effect_breath); // Breathing effect
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_charge_level); // Battery charge level
CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_charge_status); // Battery charge status
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You patch the brightness function above but don't actually add it to the device?

}

// Set device to regular mode, not driver mode
Expand Down Expand Up @@ -4343,6 +4378,14 @@ static void razer_kbd_disconnect(struct hid_device *hdev)
device_remove_file(&hdev->dev, &dev_attr_macro_led_state); // Enable macro LED
device_remove_file(&hdev->dev, &dev_attr_macro_led_effect); // Change macro LED effect (static, flashing)
break;

case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED:
case USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS:
device_remove_file(&hdev->dev, &dev_attr_matrix_effect_static); // Static effect
device_remove_file(&hdev->dev, &dev_attr_matrix_effect_breath); // Breathing effect
device_remove_file(&hdev->dev, &dev_attr_charge_level); // Battery charge level
device_remove_file(&hdev->dev, &dev_attr_charge_status); // Battery charge status
break;
}
} else if(intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD) {
device_remove_file(&hdev->dev, &dev_attr_key_super);
Expand Down Expand Up @@ -4453,6 +4496,8 @@ static const struct hid_device_id razer_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_BLADE_16_2023) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_BLADE_18_2023) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS) },
{ 0 }
};

Expand Down
3 changes: 2 additions & 1 deletion driver/razerkbd_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@
#define USB_DEVICE_ID_RAZER_BLADE_14_2021 0x0270
#define USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_MINI_WIRELESS 0x0271
#define USB_DEVICE_ID_RAZER_BLADE_15_ADV_MID_2021 0x0276
#define USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRED 0x0277
#define USB_DEVICE_ID_RAZER_BLADE_17_PRO_MID_2021 0x0279
#define USB_DEVICE_ID_RAZER_BLADE_15_BASE_2022 0x027A
#define USB_DEVICE_ID_RAZER_PRO_TYPE_ULTRA_WIRELESS 0x027B
#define USB_DEVICE_ID_RAZER_HUNTSMAN_MINI_ANALOG 0x0282
#define USB_DEVICE_ID_RAZER_BLADE_15_ADV_EARLY_2022 0x028A
#define USB_DEVICE_ID_RAZER_BLADE_17_2022 0x028B
Expand Down Expand Up @@ -135,7 +137,6 @@
#define RAZER_STEALTH_ROW_LEN 0x10
#define RAZER_STEALTH_ROWS_NUM 6

#define RAZER_BLACKWIDOW_CHROMA_WAIT_MS 1
#define RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US 600
#define RAZER_BLACKWIDOW_CHROMA_WAIT_MAX_US 800

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,10 @@
<modalias>usb:v1532p0270d*</modalias>
<modalias>usb:v1532p0271d*</modalias>
<modalias>usb:v1532p0276d*</modalias>
<modalias>usb:v1532p0277d*</modalias>
<modalias>usb:v1532p0279d*</modalias>
<modalias>usb:v1532p027Ad*</modalias>
<modalias>usb:v1532p027Bd*</modalias>
<modalias>usb:v1532p0282d*</modalias>
<modalias>usb:v1532p028Ad*</modalias>
<modalias>usb:v1532p028Bd*</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|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|028a|028b|028c|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|024c|024d|024e|0252|0253|0255|0256|0257|0258|0259|025a|025d|025e|0266|0269|026a|026b|026c|026d|026e|026f|0270|0271|0276|0277|0279|027a|027b|0282|028a|028b|028c|0290|0292|0294|0295|0296|0298|029e|029f|02a0|02a2|0a24", \
ATTRS{idVendor}=="1532", \
ENV{ID_RAZER_CHROMA}="1", ENV{RAZER_DRIVER}="razerkbd"

Expand Down
16 changes: 16 additions & 0 deletions pylib/openrazer/_fake_driver/razerprotypeultrawired.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 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:0277.0001
name = Razer Pro Type Ultra (Wired)
files = r,charge_level,255
r,charge_status,1
rw,device_mode,0x0000
r,device_serial,XX0000000277
r,device_type,%(name)s
r,firmware_version,v1.0
r,kbd_layout,01
rw,matrix_brightness,0
w,matrix_effect_breath
w,matrix_effect_static
r,version,1.0.0
16 changes: 16 additions & 0 deletions pylib/openrazer/_fake_driver/razerprotypeultrawireless.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 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:027B.0001
name = Razer Pro Type Ultra (Wireless)
files = r,charge_level,255
r,charge_status,1
rw,device_mode,0x0000
r,device_serial,XX000000027B
r,device_type,%(name)s
r,firmware_version,v1.0
r,kbd_layout,01
rw,matrix_brightness,0
w,matrix_effect_breath
w,matrix_effect_static
r,version,1.0.0