aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorKen Chen <[email protected]>2021-05-28 17:54:41 +1000
committerKen Chen <[email protected]>2021-05-28 17:54:41 +1000
commit2ca85a2bcdbf5e4b3938b95754d06b96de382bd9 (patch)
tree6864859bf5e26cf5e700c386e40899d1d48ee740 /src/lib
parentefcf6e9bf010502f831dad0be5e01651c928281b (diff)
downloadlibrazermacos-2ca85a2bcdbf5e4b3938b95754d06b96de382bd9.tar.xz
librazermacos-2ca85a2bcdbf5e4b3938b95754d06b96de382bd9.zip
basic C cli frontend
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/razeraccessory_driver.c518
-rw-r--r--src/lib/razerchromacommon.c1242
-rw-r--r--src/lib/razercommon.c171
-rwxr-xr-xsrc/lib/razerdevice.c470
-rw-r--r--src/lib/razeregpu_driver.c281
-rwxr-xr-xsrc/lib/razerheadphone_driver.c223
-rw-r--r--src/lib/razerkbd_driver.c1560
-rw-r--r--src/lib/razerkraken_driver.c324
-rw-r--r--src/lib/razermouse_driver.c2210
-rw-r--r--src/lib/razermousedock_driver.c242
-rw-r--r--src/lib/razermousemat_driver.c333
11 files changed, 7574 insertions, 0 deletions
diff --git a/src/lib/razeraccessory_driver.c b/src/lib/razeraccessory_driver.c
new file mode 100644
index 0000000..7a429a5
--- /dev/null
+++ b/src/lib/razeraccessory_driver.c
@@ -0,0 +1,518 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "razeraccessory_driver.h"
+#include "razercommon.h"
+#include "razerchromacommon.h"
+
+/**
+ * Send report to the device
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_ACCESSORY_WAIT_MIN_US);
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report)
+{
+ int retval = -1;
+ struct razer_report response_report = {0};
+
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(usb_dev, request_report, &response_report);
+
+ if(retval == 0) {
+ // Check the packet number, class and command are the same
+ if(response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id) {
+ printf("Response doesn't match request (accessory)\n");
+ } else if (response_report.status == RAZER_CMD_BUSY) {
+ //printf("Device is busy (accessory)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (accessory)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (accessory)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (accessory)\n");
+ }
+ } else {
+ printf("Invalid Report Length (accessory)\n");
+ }
+
+ return response_report;
+}
+
+/**
+ * Write device file "mode_spectrum"
+ *
+ * Specrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_accessory_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = { 0 };
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ report = razer_chroma_standard_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_none"
+ *
+ * None effect mode is activated whenever the file is written to
+ */
+ssize_t razer_accessory_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = { 0 };
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ report = razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_blinking"
+ *
+ * Blinking effect mode is activated whenever the file is written to with 3 bytes
+ */
+ssize_t razer_accessory_attr_write_mode_blinking(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+
+ struct razer_report report_rgb = {0};
+ struct razer_report report_effect = razer_chroma_standard_set_led_effect(VARSTORE, BACKLIGHT_LED, 0x01);
+ report_effect.transaction_id.id = 0x3F;
+
+ if(count == 3) {
+ report_rgb = razer_chroma_standard_set_led_rgb(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ report_rgb.transaction_id.id = 0x3F;
+
+ razer_send_payload(usb_dev, &report_rgb);
+ usleep(5 * 1000);
+ razer_send_payload(usb_dev, &report_effect);
+
+ } else {
+ printf("razeraccessory: Blinking mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_custom"
+ *
+ * Sets the device to custom mode whenever the file is written to
+ */
+ssize_t razer_accessory_attr_write_mode_custom(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = { 0 };
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ report = razer_chroma_standard_matrix_effect_custom_frame(NOSTORE);
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ report = razer_chroma_extended_matrix_effect_custom_frame();
+ break;
+
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report = razer_chroma_extended_matrix_effect_custom_frame();
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * Static effect mode is activated whenever the file is written to with 3 bytes
+ */
+ssize_t razer_accessory_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = {0};
+
+ if(count == 3) {
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ report = razer_chroma_standard_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*) & buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb*) & buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb*) & buf[0]);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ } else {
+ printf("razeraccessory: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_wave"
+ *
+ * When 1 is written (as a character, 0x31) the wave effect is displayed moving anti clockwise
+ * if 2 is written (0x32) then the wave effect goes clockwise
+ */
+ssize_t razer_accessory_attr_write_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int speed)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = { 0 };
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, ZERO_LED, direction, speed);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, ZERO_LED, direction, speed);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_breath"
+ *
+ * Breathing effect mode is activated whenever the file is written to with 1, 3, or 6 bytes
+ */
+ssize_t razer_accessory_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = {0};
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+ }
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "device_mode"
+ */
+ssize_t razer_accessory_attr_write_device_mode(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = {0};
+
+ if (count != 2) {
+ printf("razeraccessory: Device mode only takes 2 bytes.");
+ } else {
+
+ report = razer_chroma_standard_set_device_mode(buf[0], buf[1]);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report.transaction_id.id = 0x1F;
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ }
+
+ return count;
+}
+
+ssize_t razer_accessory_attr_read_get_cup_state(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = get_razer_report(0x02, 0x81, 0x02);
+ struct razer_report response = {0};
+
+ response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%u\n", response.arguments[1]);
+}
+
+/**
+ * Read device file "device_mode"
+ *
+ * Returns a string
+ */
+ssize_t razer_accessory_attr_read_device_mode(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = razer_chroma_standard_get_device_mode();
+ struct razer_report response = {0};
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report.transaction_id.id = 0x1F;
+ break;
+ }
+
+ response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%d:%d\n", response.arguments[0], response.arguments[1]);
+}
+
+/**
+ * Write device file "set_brightness"
+ *
+ * Sets the brightness to the ASCII number written to this file.
+ */
+ssize_t razer_accessory_attr_write_set_brightness(IOUSBDeviceInterface **usb_dev, ushort brightness, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = {0};
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, ZERO_LED, brightness);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, BACKLIGHT_LED, brightness);
+ break;
+
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, ZERO_LED, brightness);
+ break;
+
+ default:
+ printf("razeraccessory: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Read device file "set_brightness"
+ *
+ * Returns brightness or -1 if the initial brightness is not known
+ */
+ushort razer_accessory_attr_read_set_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = razer_chroma_standard_get_led_brightness(VARSTORE, BACKLIGHT_LED);
+ struct razer_report response = {0};
+ unsigned char brightness = 0;
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ break;
+
+ default:
+ response = razer_send_payload(usb_dev, &report);
+ brightness = response.arguments[2];
+ break;
+ }
+
+ return brightness;
+} \ No newline at end of file
diff --git a/src/lib/razerchromacommon.c b/src/lib/razerchromacommon.c
new file mode 100644
index 0000000..6f6410e
--- /dev/null
+++ b/src/lib/razerchromacommon.c
@@ -0,0 +1,1242 @@
+#include <math.h>
+
+#include "razerchromacommon.h"
+
+
+static unsigned char orochi2011_led[] = { 0x01, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x03, 0x05, 0x06, 0x06, 0x10, 0x10, 0x10, 0x10, 0x24, 0x24, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x04, 0x01, 0x04, 0x04, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x06, 0x31, 0x88, 0x00, 0x07, 0x31, 0x87, 0x00, 0x08, 0x08, 0x01, 0x01, 0x09, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01 };
+static unsigned char orochi2011_dpi[] = { 0x01, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
+
+/*
+ * Standard Device Functions
+ */
+
+/**
+ * Set what mode the device will operate in.
+ *
+ * Currently known modes
+ * 0x00, 0x00: Normal Mode
+ * 0x02, 0x00: Unknown Mode
+ * 0x03, 0x00: Driver Mode
+ *
+ * 0x02, 0x00 Will make M1-5 and FN emit normal keystrokes. Some sort of factory test mode. Not recommended to be used.
+ */
+struct razer_report razer_chroma_standard_set_device_mode(unsigned char mode, unsigned char param)
+{
+ struct razer_report report = get_razer_report(0x00, 0x04, 0x02);
+
+ if(mode != 0x00 && mode != 0x03) { // Explicitly blocking the 0x02 mode
+ mode = 0x00;
+ }
+ if(param != 0x00) {
+ param = 0x00;
+ }
+
+ report.arguments[0] = mode;
+ report.arguments[1] = param;
+
+ return report;
+}
+
+/**
+ * Get what mode the device is operating in.
+ *
+ * Currently known modes
+ * 0x00, 0x00: Normal Mode
+ * 0x02, 0x00: Unknown Mode
+ * 0x03, 0x00: Driver Mode
+ *
+ * 0x02, 0x00 Will make M1-5 and FN emit normal keystrokes. Some sort of factory test mode. Not recommended to be used.
+ */
+struct razer_report razer_chroma_standard_get_device_mode(void)
+{
+ return get_razer_report(0x00, 0x84, 0x02);
+}
+
+/**
+ * Get serial from device
+ */
+struct razer_report razer_chroma_standard_get_serial(void)
+{
+ return get_razer_report(0x00, 0x82, 0x16);
+}
+
+/**
+ * Get firmware version from device
+ */
+struct razer_report razer_chroma_standard_get_firmware_version(void)
+{
+ return get_razer_report(0x00, 0x81, 0x02);
+}
+
+/*
+ * Standard Functions
+ */
+
+/**
+ * Set the state of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 03 03 00 010801 | SET LED STATE (VARSTR, GAMEMODE, ON)
+ * 00 3f 0000 00 03 03 00 010800 | SET LED STATE (VARSTR, GAMEMODE, OFF)
+ */
+struct razer_report razer_chroma_standard_set_led_state(unsigned char variable_storage, unsigned char led_id, unsigned char led_state)
+{
+ struct razer_report report = get_razer_report(0x03, 0x00, 0x03);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = clamp_u8(led_state, 0x00, 0x01);
+
+ return report;
+}
+
+struct razer_report razer_chroma_standard_set_led_blinking(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x04, 0x04);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = 0x05;
+ report.arguments[3] = 0x05;
+
+ return report;
+}
+
+/**
+ * Get the state of an LED on the device
+ */
+struct razer_report razer_chroma_standard_get_led_state(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x80, 0x03);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+
+ return report;
+}
+
+
+/**
+ * Set LED RGB parameters
+ */
+struct razer_report razer_chroma_standard_set_led_rgb(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1)
+{
+ struct razer_report report = get_razer_report(0x03, 0x01, 0x05);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = rgb1->r;
+ report.arguments[3] = rgb1->g;
+ report.arguments[4] = rgb1->b;
+
+ return report;
+}
+
+/**
+ * Get LED RGB parameters
+ */
+struct razer_report razer_chroma_standard_get_led_rgb(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x81, 0x05);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ return report;
+}
+
+
+
+
+
+/**
+ * Set the effect of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_set_led_effect(unsigned char variable_storage, unsigned char led_id, unsigned char led_effect)
+{
+ struct razer_report report = get_razer_report(0x03, 0x02, 0x03);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = clamp_u8(led_effect, 0x00, 0x05);
+
+ return report;
+}
+
+/**
+ * Get the effect of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_get_led_effect(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x82, 0x03);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+
+ return report;
+}
+
+/**
+ * Set the brightness of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_set_led_brightness(unsigned char variable_storage, unsigned char led_id, ushort brightness)
+{
+ struct razer_report report = get_razer_report(0x03, 0x03, 0x03);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = round(brightness * 2.55); //Razer macOS special: brightness is coming [0-100], matrix brightness range is from [0-255] though
+
+ return report;
+}
+
+/**
+ * Get the brightness of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_get_led_brightness(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x83, 0x03);
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+
+ return report;
+}
+
+
+/*
+ * Standard Matrix Effects Functions
+ */
+
+// TODO remove varstore and led_id
+/**
+ * Set the effect of the LED matrix to None
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_none(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x01);
+ report.arguments[0] = 0x00; // Effect ID
+
+ return report;
+}
+
+/**
+ * Set the effect of the LED matrix to Wave
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_wave(unsigned char variable_storage, unsigned char led_id, unsigned char wave_direction)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x02);
+ report.arguments[0] = 0x01; // Effect ID
+ report.arguments[1] = clamp_u8(wave_direction, 0x01, 0x02);
+
+ return report;
+}
+
+/**
+ * Set the effect of the LED matrix to Spectrum
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_spectrum(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x01);
+ report.arguments[0] = 0x04; // Effect ID
+
+ return report;
+}
+
+/**
+ * Set the effect of the LED matrix to Reactive
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_reactive(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb1)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x05);
+ report.arguments[0] = 0x02; // Effect ID
+ report.arguments[1] = clamp_u8(speed, 0x01, 0x04); // Time
+ report.arguments[2] = rgb1->r; /*rgb color definition*/
+ report.arguments[3] = rgb1->g;
+ report.arguments[4] = rgb1->b;
+
+ return report;
+}
+
+/**
+ * Set the effect of the LED matrix to Static
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_static(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x04);
+ report.arguments[0] = 0x06; // Effect ID
+ report.arguments[1] = rgb1->r; /*rgb color definition*/
+ report.arguments[2] = rgb1->g;
+ report.arguments[3] = rgb1->b;
+
+ return report;
+}
+
+/**
+ * Set the effect of the LED matrix to Starlight
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_starlight_single(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb1)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x01);
+
+ speed = clamp_u8(0x01, 0x01, 0x03); // For now only seen
+
+ report.arguments[0] = 0x19; // Effect ID
+ report.arguments[1] = 0x01; // Type one color
+ report.arguments[2] = speed; // Speed
+
+ report.arguments[3] = rgb1->r; // Red 1
+ report.arguments[4] = rgb1->g; // Green 1
+ report.arguments[5] = rgb1->b; // Blue 1
+
+ // For now haven't seen any chroma using this, seen the extended version
+ report.arguments[6] = 0x00; // Red 2
+ report.arguments[7] = 0x00; // Green 2
+ report.arguments[8] = 0x00; // Blue 2
+
+ return report;
+}
+
+/**
+ * Set the effect of the LED matrix to Starlight
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_standard_matrix_effect_starlight_dual(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb1, struct razer_rgb *rgb2)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x01);
+
+ speed = clamp_u8(speed, 0x01, 0x03); // For now only seen
+
+ report.arguments[0] = 0x19; // Effect ID
+ report.arguments[1] = 0x02; // Type two color
+ report.arguments[2] = speed; // Speed
+
+ report.arguments[3] = rgb1->r; // Red 1
+ report.arguments[4] = rgb1->g; // Green 1
+ report.arguments[5] = rgb1->b; // Blue 1
+
+ report.arguments[6] = rgb2->r; // Red 2
+ report.arguments[7] = rgb2->g; // Green 2
+ report.arguments[8] = rgb2->b; // Blue 2
+
+ return report;
+}
+
+struct razer_report razer_chroma_standard_matrix_effect_starlight_random(unsigned char variable_storage, unsigned char led_id, unsigned char speed)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x01);
+
+ speed = clamp_u8(speed, 0x01, 0x03); // For now only seen
+
+ report.arguments[0] = 0x19; // Effect ID
+ report.arguments[1] = 0x03; // Type random color
+ report.arguments[2] = speed; // Speed
+
+ return report;
+}
+
+/**
+ * Set the device to "Breathing" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ??
+ * ??
+ * ??
+ */
+struct razer_report razer_chroma_standard_matrix_effect_breathing_random(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x08);
+ report.arguments[0] = 0x03; // Effect ID
+ report.arguments[1] = 0x03; // Breathing type
+
+ return report;
+}
+struct razer_report razer_chroma_standard_matrix_effect_breathing_single(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x08);
+ report.arguments[0] = 0x03; // Effect ID
+ report.arguments[1] = 0x01; // Breathing type
+ report.arguments[2] = rgb1->r;
+ report.arguments[3] = rgb1->g;
+ report.arguments[4] = rgb1->b;
+
+ return report;
+}
+struct razer_report razer_chroma_standard_matrix_effect_breathing_dual(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1, struct razer_rgb *rgb2)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x08);
+ report.arguments[0] = 0x03; // Effect ID
+ report.arguments[1] = 0x02; // Breathing type
+ report.arguments[2] = rgb1->r;
+ report.arguments[3] = rgb1->g;
+ report.arguments[4] = rgb1->b;
+ report.arguments[5] = rgb2->r;
+ report.arguments[6] = rgb2->g;
+ report.arguments[7] = rgb2->b;
+
+ return report;
+}
+
+/**
+ * Set the device to "Custom" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ??
+ *
+ * Apparently Ultimate2016, Stealth and Stealth2016 need frame id to be 0x00, I don't think it's needed (depending on set_custom_frame)
+ */
+struct razer_report razer_chroma_standard_matrix_effect_custom_frame(unsigned char variable_storage)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x02);
+ report.arguments[0] = 0x05; // Effect ID
+ report.arguments[1] = variable_storage; // Data frame ID
+ // report.arguments[1] = 0x01; // Data frame ID
+
+ return report;
+}
+
+/**
+ * Set the RGB or a row
+ *
+ * Start and stop columns are inclusive
+ *
+ * This sets the colour of a row on the keyboard. Takes in an array of RGB bytes.
+ * The mappings below are correct for the BlackWidow Chroma. The BlackWidow Ultimate 2016
+ * contains LEDs under the spacebar and the FN key so there will be changes once I get the
+ * hardware.
+ *
+ * Row 0:
+ * 0 Unused
+ * 1 ESC
+ * 2 Unused
+ * 3-14 F1-F12
+ * 15-17 PrtScr, ScrLk, Pause
+ * 18-19 Unused
+ * 20 Razer Logo
+ * 21 Unused
+ *
+ * Row 1:
+ * 0-21 M1 -> NP Minus
+ *
+ * Row 2:
+ * 0-13 M2 -> Right Square Bracket ]
+ * 14 Unused
+ * 15-21 Delete -> NP Plus
+ *
+ * Row 3:
+ * 0-14 M3 -> Return
+ * 15-17 Unused
+ * 18-20 NP4 -> NP6
+ *
+ * Row 4:
+ * 0-12 M4 -> Forward Slash /
+ * 13 Unused
+ * 14 Right Shift
+ * 15 Unused
+ * 16 Up Arrow Key
+ * 17 Unused
+ * 18-21 NP1 -> NP Enter
+ *
+ * Row 5:
+ * 0-3 M5 -> Alt
+ * 4-10 Unused
+ * 11 Alt GR
+ * 12 Unused
+ * 13-17 Context Menu Key -> Right Arrow Key
+ * 18 Unused
+ * 19-20 NP0 -> NP.
+ * 21 Unused
+ */
+struct razer_report razer_chroma_standard_matrix_set_custom_frame(unsigned char row_index, unsigned char start_col, unsigned char stop_col, unsigned char *rgb_data)
+{
+ size_t row_length = (size_t) (((stop_col + 1) - start_col) * 3);
+ struct razer_report report = get_razer_report(0x03, 0x0B, 0x46); // In theory should be able to leave data size at max as we have start/stop
+
+ // printk(KERN_ALERT "razerkbd: Row ID: %d, Start: %d, Stop: %d, row length: %d\n", row_index, start_col, stop_col, (unsigned char)row_length);
+
+ report.arguments[0] = 0xFF; // Frame ID
+ report.arguments[1] = row_index;
+ report.arguments[2] = start_col;
+ report.arguments[3] = stop_col;
+ memcpy(&report.arguments[4], rgb_data, row_length);
+
+ return report;
+}
+
+
+/*
+ * Extended Matrix Effects
+ */
+
+/**
+ * Sets up the extended matrix effect payload
+ */
+struct razer_report razer_chroma_extended_matrix_effect_base(unsigned char arg_size, unsigned char variable_storage, unsigned char led_id, unsigned char effect_id)
+{
+ struct razer_report report = get_razer_report(0x0F, 0x02, arg_size);
+ report.transaction_id.id = 0x3F;
+
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = effect_id; // Effect ID
+
+ return report;
+}
+
+/**
+ * Set the device to "None" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 06 0f 02 010500000000 | SET LED MATRIX Effect (VARSTR, Backlight, None 0x00, 0x000000)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_none(unsigned char variable_storage, unsigned char led_id)
+{
+ return razer_chroma_extended_matrix_effect_base(0x06, variable_storage, led_id, 0x00);
+}
+
+/**
+ * Set the device to "Static" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 09 0f 02 010501000001ff0000 | SET LED MATRIX Effect (VARSTR, Backlight, Static 0x01, ? 0x000001, RGB 0xFF0000)
+ * 00 3f 0000 00 09 0f 02 01050100000100ff00 | SET LED MATRIX Effect (VARSTR, Backlight, Static 0x01, ? 0x000001, RGB 0x00FF00)
+ * 00 3f 0000 00 09 0f 02 010501000001008000 | SET LED MATRIX Effect (VARSTR, Backlight, Static 0x01, ? 0x000001, RGB 0x008000)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_static(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x09, variable_storage, led_id, 0x01);
+
+ report.arguments[5] = 0x01;
+ report.arguments[6] = rgb->r;
+ report.arguments[7] = rgb->g;
+ report.arguments[8] = rgb->b;
+ return report;
+}
+
+/**
+ * Set the device to "Wave" effect
+ *
+ * Seems like direction is now 0x00, 0x01 for Left/Right, used to be 0x01, 0x02
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 06 0f 02 010504002800 | SET LED MATRIX Effect (VARSTR, Backlight, Wave 0x04, Dir 0x00, ? 0x2800)
+ * 00 3f 0000 00 06 0f 02 010504012800 | SET LED MATRIX Effect (VARSTR, Backlight, Wave 0x04, Dir 0x01, ? 0x2800)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_wave(unsigned char variable_storage, unsigned char led_id, unsigned char direction, int speed)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x06, variable_storage, led_id, 0x04);
+
+ // Some devices use values 0x00, 0x01
+ // Others use values 0x01, 0x02
+ direction = clamp_u8(direction, 0x00, 0x02);
+
+ report.arguments[3] = direction;
+ report.arguments[4] = speed; // Speed, lower values are faster (). The default used to be 0x28
+ return report;
+}
+
+/**
+ * Set the device to "Starlight" effect
+ *
+ * Speed is 0x01 - 0x03
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 06 0f 02 010507000100 | SET LED MATRIX Effect (VARSTR, Backlight, Starlight 0x07, ? 0x00, Speed 0x01, Colours 0x00)
+ * 00 3f 0000 00 06 0f 02 010507000200 | SET LED MATRIX Effect (VARSTR, Backlight, Starlight 0x07, ? 0x00, Speed 0x02, Colours 0x00)
+ * 00 3f 0000 00 06 0f 02 010507000300 | SET LED MATRIX Effect (VARSTR, Backlight, Starlight 0x07, ? 0x00, Speed 0x03, Colours 0x00)
+ * 00 3f 0000 00 09 0f 02 010507000301ff0000 | SET LED MATRIX Effect (VARSTR, Backlight, Starlight 0x07, ? 0x00, Speed 0x03, Colours 0x01, RGB 0xFF0000)
+ * 00 3f 0000 00 0c 0f 02 010507000302ff000000ff00 | SET LED MATRIX Effect (VARSTR, Backlight, Starlight 0x07, ? 0x00, Speed 0x03, Colours 0x02, RGB 0xFF0000, RGB 0x00FF00)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_starlight_random(unsigned char variable_storage, unsigned char led_id, unsigned char speed)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x06, variable_storage, led_id, 0x07);
+
+ speed = clamp_u8(speed, 0x01, 0x03);
+
+ report.arguments[4] = speed;
+ return report;
+}
+struct razer_report razer_chroma_extended_matrix_effect_starlight_single(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb1)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x09, variable_storage, led_id, 0x07);
+
+ speed = clamp_u8(speed, 0x01, 0x03);
+
+ report.arguments[4] = speed;
+ report.arguments[5] = 0x01;
+ report.arguments[6] = rgb1->r;
+ report.arguments[7] = rgb1->g;
+ report.arguments[8] = rgb1->b;
+
+ return report;
+}
+struct razer_report razer_chroma_extended_matrix_effect_starlight_dual(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb1, struct razer_rgb *rgb2)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x0C, variable_storage, led_id, 0x07);
+
+ speed = clamp_u8(speed, 0x01, 0x03);
+
+ report.arguments[4] = speed;
+ report.arguments[5] = 0x02;
+ report.arguments[6] = rgb1->r;
+ report.arguments[7] = rgb1->g;
+ report.arguments[8] = rgb1->b;
+ report.arguments[9] = rgb2->r;
+ report.arguments[10] = rgb2->g;
+ report.arguments[11] = rgb2->b;
+
+ return report;
+}
+
+/**
+ * Set the device to "Spectrum" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 06 0f 02 010503000000 | SET LED MATRIX Effect (VARSTR, Backlight, Spectrum 0x03, 0x000000)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_spectrum(unsigned char variable_storage, unsigned char led_id)
+{
+ return razer_chroma_extended_matrix_effect_base(0x06, variable_storage, led_id, 0x03);
+}
+
+/**
+ * Set the device to "Reactive" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 09 0f 02 010505000101ffff00 | SET LED MATRIX Effect (VARSTR, Backlight, Reactive 0x05, ? 0x00, Speed 0x01, Colours 0x01, RGB 0xFFFF00)
+ * 00 3f 0000 00 09 0f 02 010505000101ff0000 | SET LED MATRIX Effect (VARSTR, Backlight, Reactive 0x05, ? 0x00, Speed 0x02, Colours 0x01, RGB 0xFF0000)
+ * 00 3f 0000 00 09 0f 02 010505000301ff0000 | SET LED MATRIX Effect (VARSTR, Backlight, Reactive 0x05, ? 0x00, Speed 0x03, Colours 0x01, RGB 0xFF0000)
+ * 00 3f 0000 00 09 0f 02 010505000401ff0000 | SET LED MATRIX Effect (VARSTR, Backlight, Reactive 0x05, ? 0x00, Speed 0x04, Colours 0x01, RGB 0xFF0000)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_reactive(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x09, variable_storage, led_id, 0x05);
+
+ speed = clamp_u8(speed, 0x01, 0x04);
+
+ report.arguments[4] = speed;
+ report.arguments[5] = 0x01;
+ report.arguments[6] = rgb->r;
+ report.arguments[7] = rgb->g;
+ report.arguments[8] = rgb->b;
+
+ return report;
+}
+
+/**
+ * Set the device to "Breathing" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 09 0f 02 01050201000100ff00 | SET LED MATRIX Effect (VARSTR, Backlight, Breathing 0x02, Colours 0x01, ? 0x00, Colours 0x01, RGB 0x00FF00)
+ * 00 3f 0000 00 0c 0f 02 01050202000200ff00ff0000 | SET LED MATRIX Effect (VARSTR, Backlight, Breathing 0x02, Colours 0x02, ? 0x00, Colours 0x02, RGB 0x00FF00, RGB 0xFF0000)
+ * 00 3f 0000 00 06 0f 02 010502000000 | SET LED MATRIX Effect (VARSTR, Backlight, Breathing 0x02, Colours 0x00, ? 0x0000)
+ */
+struct razer_report razer_chroma_extended_matrix_effect_breathing_random(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x06, variable_storage, led_id, 0x02);
+ return report;
+}
+struct razer_report razer_chroma_extended_matrix_effect_breathing_single(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x09, variable_storage, led_id, 0x02);
+
+ report.arguments[3] = 0x01;
+ report.arguments[5] = 0x01;
+
+ report.arguments[6] = rgb1->r;
+ report.arguments[7] = rgb1->g;
+ report.arguments[8] = rgb1->b;
+
+ return report;
+}
+struct razer_report razer_chroma_extended_matrix_effect_breathing_dual(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1, struct razer_rgb *rgb2)
+{
+ struct razer_report report = razer_chroma_extended_matrix_effect_base(0x0C, variable_storage, led_id, 0x02);
+
+ report.arguments[3] = 0x02;
+ report.arguments[5] = 0x02;
+
+ report.arguments[6] = rgb1->r;
+ report.arguments[7] = rgb1->g;
+ report.arguments[8] = rgb1->b;
+ report.arguments[9] = rgb2->r;
+ report.arguments[10] = rgb2->g;
+ report.arguments[11] = rgb2->b;
+
+ return report;
+}
+
+/**
+ * Set the device to "Custom" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 0c 0f 02 000008000000000000000000 | DRAW LED MATRIX Frame
+ */
+struct razer_report razer_chroma_extended_matrix_effect_custom_frame(void)
+{
+ return razer_chroma_extended_matrix_effect_base(0x0C, 0x00, 0x00, 0x08);
+}
+
+/**
+ * Set the device brightness
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 03 0f 04 0104b7
+ */
+struct razer_report razer_chroma_extended_matrix_brightness(unsigned char variable_storage, unsigned char led_id, unsigned char brightness)
+{
+ struct razer_report report = get_razer_report(0x0F, 0x04, 0x03);
+ report.transaction_id.id = 0x3F;
+
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = round(brightness * 2.55); //Razer macOS special: brightness is coming [0-100], matrix brightness range is from [0-255] though
+
+ return report;
+}
+
+/**
+ * Get the device brightness
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 03 0f 84 0104
+ */
+struct razer_report razer_chroma_extended_matrix_get_brightness(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = get_razer_report(0x0F, 0x84, 0x03);
+ report.transaction_id.id = 0x3F;
+
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+
+ return report;
+}
+
+/**
+ * Set the RGB or a row
+ *
+ * Start and stop columns are inclusive
+ */
+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)
+{
+ return razer_chroma_extended_matrix_set_custom_frame2(row_index, start_col, stop_col, rgb_data, 0x47);
+}
+
+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)
+{
+ const size_t row_length = (size_t) (((stop_col + 1) - start_col) * 3);
+ // Some devices need a specific packet length, most devices are happy with 0x47
+ // e.g. the Mamba Elite needs a "row_length + 5" packet length
+ const size_t data_length = (packetLength != 0) ? packetLength : row_length + 5;
+ struct razer_report report = get_razer_report(0x0F, 0x03, data_length);
+
+ report.transaction_id.id = 0x3F;
+
+ // printk(KERN_ALERT "razerkbd: Row ID: %d, Start: %d, Stop: %d, row length: %d\n", row_index, start_col, stop_col, (unsigned char)row_length);
+
+ report.arguments[2] = row_index;
+ report.arguments[3] = start_col;
+ report.arguments[4] = stop_col;
+ memcpy(&report.arguments[5], rgb_data, row_length);
+
+ return report;
+}
+
+/*
+ * Extended Matrix Effects (Mouse)
+ */
+/**
+ * Sets up the extended matrix effect payload for mouse devices
+ */
+struct razer_report razer_chroma_mouse_extended_matrix_effect_base(unsigned char arg_size, unsigned char variable_storage, unsigned char led_id, unsigned char effect_id)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0D, arg_size);
+ report.transaction_id.id = 0x3F;
+
+ report.arguments[0] = variable_storage;
+ report.arguments[1] = led_id;
+ report.arguments[2] = effect_id; // Effect ID
+
+ return report;
+}
+
+/**
+ * Set the device to "None" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * * 00 3f 0000 00 03 03 0d 010100 | SET Extended Matrix Effect (VARSTORE, LOGO_LED, OFF)
+ */
+struct razer_report razer_chroma_mouse_extended_matrix_effect_none(unsigned char variable_storage, unsigned char led_id)
+{
+ return razer_chroma_mouse_extended_matrix_effect_base(0x03, variable_storage, led_id, 0x00);
+}
+
+/**
+ * Set the device to "Static" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 06 03 0d 010106 00ff00 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, STATIC, RGB)
+ */
+struct razer_report razer_chroma_mouse_extended_matrix_effect_static(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb)
+{
+ struct razer_report report = razer_chroma_mouse_extended_matrix_effect_base(0x06, variable_storage, led_id, 0x06);
+
+ report.arguments[3] = rgb->r;
+ report.arguments[4] = rgb->g;
+ report.arguments[5] = rgb->b;
+ return report;
+}
+
+/**
+ * Set the device to "Spectrum" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 03 03 0d 010104 | SET Extended Matrix Effect (VARSTORE, LOGO_LED, SPECTRUM)
+ */
+struct razer_report razer_chroma_mouse_extended_matrix_effect_spectrum(unsigned char variable_storage, unsigned char led_id)
+{
+ return razer_chroma_mouse_extended_matrix_effect_base(0x03, variable_storage, led_id, 0x04);
+}
+
+/**
+ * Set the device to "Reactive" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 07 03 0d 010102 0300ff00 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, REACTIVE, TIME, RGB)
+ * 00 3f 0000 00 07 03 0d 010102 0200ff00 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, REACTIVE, TIME, RGB)
+ * 00 3f 0000 00 07 03 0d 010102 0100ff00 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, REACTIVE, TIME, RGB)
+ */
+struct razer_report razer_chroma_mouse_extended_matrix_effect_reactive(unsigned char variable_storage, unsigned char led_id, unsigned char speed, struct razer_rgb *rgb)
+{
+ struct razer_report report = razer_chroma_mouse_extended_matrix_effect_base(0x07, variable_storage, led_id, 0x02);
+
+ speed = clamp_u8(speed, 0x01, 0x04);
+
+ report.arguments[3] = speed;
+ report.arguments[4] = rgb->r;
+ report.arguments[5] = rgb->g;
+ report.arguments[6] = rgb->b;
+
+ return report;
+}
+
+/**
+ * Set the device to "Breathing" effect
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * 00 3f 0000 00 0a 03 0d 010103 0100ff00000000 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, BREATHING, single, RGB, RGB-none)
+ * 00 3f 0000 00 0a 03 0d 010103 0200ff00ff0000 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, BREATHING, dual, RGB, RGB)
+ * 00 3f 0000 00 0a 03 0d 010103 03000000000000 | SET Extended Matrix Effect (VARSTORE, SCROLL_WHEEL, BREATHING, random, RGB-none, RGB-none)
+ */
+struct razer_report razer_chroma_mouse_extended_matrix_effect_breathing_random(unsigned char variable_storage, unsigned char led_id)
+{
+ struct razer_report report = razer_chroma_mouse_extended_matrix_effect_base(0x0A, variable_storage, led_id, 0x03);
+
+ report.arguments[3] = 0x03;
+
+ return report;
+}
+struct razer_report razer_chroma_mouse_extended_matrix_effect_breathing_single(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1)
+{
+ struct razer_report report = razer_chroma_mouse_extended_matrix_effect_base(0x0A, variable_storage, led_id, 0x03);
+
+ report.arguments[3] = 0x01;
+
+ report.arguments[4] = rgb1->r;
+ report.arguments[5] = rgb1->g;
+ report.arguments[6] = rgb1->b;
+
+ return report;
+}
+struct razer_report razer_chroma_mouse_extended_matrix_effect_breathing_dual(unsigned char variable_storage, unsigned char led_id, struct razer_rgb *rgb1, struct razer_rgb *rgb2)
+{
+ struct razer_report report = razer_chroma_mouse_extended_matrix_effect_base(0x0A, variable_storage, led_id, 0x03);
+
+ report.arguments[3] = 0x02;
+
+ report.arguments[4] = rgb1->r;
+ report.arguments[5] = rgb1->g;
+ report.arguments[6] = rgb1->b;
+
+ report.arguments[7] = rgb2->r;
+ report.arguments[8] = rgb2->g;
+ report.arguments[9] = rgb2->b;
+
+ return report;
+}
+
+
+
+
+/*
+ * Misc Functions
+ */
+/**
+ * Toggled whether F1-12 act as F1-12 or if they act as the function options (without Fn pressed)
+ *
+ * If 0 should mean that the F-keys work as normal F-keys
+ * If 1 should mean that the F-keys act as if the FN key is held
+ */
+struct razer_report razer_chroma_misc_fn_key_toggle(unsigned char state)
+{
+ struct razer_report report = get_razer_report(0x02, 0x06, 0x02);
+ report.arguments[0] = 0x00; // ?? Variable storage maybe
+ report.arguments[1] = clamp_u8(state, 0x00, 0x01); // State
+
+ return report;
+}
+
+/**
+ * Set the brightness of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_misc_set_blade_brightness(unsigned char brightness)
+{
+ struct razer_report report = get_razer_report(0x0E, 0x04, 0x02);
+ report.arguments[0] = 0x01;
+ report.arguments[1] = brightness;
+
+ return report;
+}
+
+/**
+ * Get the brightness of an LED on the device
+ *
+ * Status Trans Packet Proto DataSize Class CMD Args
+ * ? TODO fill this
+ */
+struct razer_report razer_chroma_misc_get_blade_brightness(void)
+{
+ struct razer_report report = get_razer_report(0x0E, 0x84, 0x02);
+ report.arguments[0] = 0x01;
+
+ return report;
+}
+
+/**
+ * Sets custom frame for the firefly
+ */
+struct razer_report razer_chroma_misc_one_row_set_custom_frame(unsigned char start_col, unsigned char stop_col, unsigned char *rgb_data) // TODO recheck custom frame hex
+{
+ struct razer_report report = get_razer_report(0x03, 0x0C, 0x32);
+ size_t row_length = (size_t) (((stop_col + 1) - start_col) * 3);
+
+ report.arguments[0] = start_col;
+ report.arguments[1] = stop_col;
+
+ memcpy(&report.arguments[2], rgb_data, row_length);
+
+ return report;
+}
+
+/**
+ * Trigger reactive on Firefly
+ */
+struct razer_report razer_chroma_misc_matrix_reactive_trigger(void)
+{
+ struct razer_report report = get_razer_report(0x03, 0x0A, 0x05);
+ report.arguments[0] = 0x02; // Effect ID
+ report.arguments[1] = 0; // this speed triggers reactive
+ report.arguments[2] = 0;
+ report.arguments[3] = 0;
+ report.arguments[4] = 0;
+
+ return report;
+}
+
+/**
+ * Gets battery level
+ *
+ * 0->255 is in arg[1]
+ */
+struct razer_report razer_chroma_misc_get_battery_level(void)
+{
+ return get_razer_report(0x07, 0x80, 0x02);
+}
+
+/**
+ * Gets charging status
+ *
+ * 0->1 is in arg[1]
+ */
+struct razer_report razer_chroma_misc_get_charging_status(void)
+{
+ return get_razer_report(0x07, 0x84, 0x02);
+}
+
+/**
+ * Set the charging effect, think if I remember correctly, it's either static colour, or "whatever the mouse was last on"
+ */
+struct razer_report razer_chroma_misc_set_dock_charge_type(unsigned char charge_type)
+{
+ struct razer_report report = get_razer_report(0x03, 0x10, 0x01);
+ report.arguments[0] = clamp_u8(charge_type, 0x00, 0x01);
+
+ return report;
+}
+
+/**
+ * Get the polling rate from the device
+ *
+ * Identifier is in arg[0]
+ *
+ * 0x01 = 1000Hz
+ * 0x02 = 500Hz
+ * 0x08 = 125Hz
+ */
+struct razer_report razer_chroma_misc_get_polling_rate(void)
+{
+ return get_razer_report(0x00, 0x85, 0x01);
+}
+
+/**
+ * Set the polling rate of the device
+ *
+ * 0x01 = 1000Hz
+ * 0x02 = 500Hz
+ * 0x08 = 125Hz
+ */
+struct razer_report razer_chroma_misc_set_polling_rate(unsigned short polling_rate)
+{
+ struct razer_report report = get_razer_report(0x00, 0x05, 0x01);
+
+ switch(polling_rate) {
+ case 1000:
+ report.arguments[0] = 0x01;
+ break;
+ case 500:
+ report.arguments[0] = 0x02;
+ break;
+ case 125:
+ report.arguments[0] = 0x08;
+ break;
+ default: // 500Hz
+ report.arguments[0] = 0x02;
+ break;
+ }
+
+ return report;
+}
+
+/**
+ * Get brightness of charging dock
+ */
+struct razer_report razer_chroma_misc_get_dock_brightness(void)
+{
+ return get_razer_report(0x07, 0x82, 0x01);
+
+}
+
+/**
+ * Set brightness of charging dock
+ */
+struct razer_report razer_chroma_misc_set_dock_brightness(unsigned char brightness)
+{
+ struct razer_report report = get_razer_report(0x07, 0x02, 0x01);
+ report.arguments[0] = brightness;
+
+ return report;
+}
+
+/**
+ * Set the DPI of the device
+ */
+struct razer_report razer_chroma_misc_set_dpi_xy(unsigned char variable_storage, unsigned short dpi_x,unsigned short dpi_y)
+{
+ struct razer_report report = get_razer_report(0x04, 0x05, 0x07);
+
+ // Keep the DPI within bounds
+ dpi_x = clamp_u16(dpi_x, 128, 20000);
+ dpi_y = clamp_u16(dpi_y, 128, 20000);
+
+ report.arguments[0] = VARSTORE;
+
+ report.arguments[1] = (dpi_x >> 8) & 0x00FF;
+ report.arguments[2] = dpi_x & 0x00FF;
+ report.arguments[3] = (dpi_y >> 8) & 0x00FF;
+ report.arguments[4] = dpi_y & 0x00FF;
+ report.arguments[5] = 0x00;
+ report.arguments[6] = 0x00;
+
+ return report;
+}
+
+/**
+ * Get the DPI of the device
+ */
+struct razer_report razer_chroma_misc_get_dpi_xy(unsigned char variable_storage)
+{
+ struct razer_report report = get_razer_report(0x04, 0x85, 0x07);
+
+ report.arguments[0] = VARSTORE;
+
+ return report;
+}
+
+/**
+ * Set the DPI of the device (Some stupid turd scaled 5600 dpi into a single byte)
+ */
+struct razer_report razer_chroma_misc_set_dpi_xy_byte(unsigned char dpi_x,unsigned char dpi_y)
+{
+ struct razer_report report = get_razer_report(0x04, 0x01, 0x03);
+
+ report.arguments[0] = dpi_x;
+ report.arguments[1] = dpi_y;
+ report.arguments[2] = 0x00;
+
+ return report;
+}
+
+/**
+ * Get the DPI of the device (Some stupid turd scaled 5600 dpi into a single byte)
+ */
+struct razer_report razer_chroma_misc_get_dpi_xy_byte(void)
+{
+ struct razer_report report = get_razer_report(0x04, 0x81, 0x03);
+
+ return report;
+}
+
+/**
+ * Set device idle time
+ *
+ * Device will go into powersave after this time.
+ *
+ * Idle time is in seconds, must be between 60sec-900sec
+ */
+struct razer_report razer_chroma_misc_set_idle_time(unsigned short idle_time)
+{
+ struct razer_report report = get_razer_report(0x07, 0x03, 0x02);
+
+ // Keep the idle time within bounds
+ idle_time = clamp_u16(idle_time, 60, 900);
+
+ report.arguments[0] = (idle_time >> 8) & 0x00FF;
+ report.arguments[1] = idle_time & 0x00FF;
+
+ return report;
+}
+
+/**
+ * Set low battery threshold
+ *
+ * 0x3F = 25%
+ * 0x26 = 15%
+ * 0x0C = 5%
+ */
+struct razer_report razer_chroma_misc_set_low_battery_threshold(unsigned char battery_threshold)
+{
+ struct razer_report report = get_razer_report(0x07, 0x01, 0x01);
+
+ // Keep the idle time within bounds
+ battery_threshold = clamp_u8(battery_threshold, 0x0C, 0x3F);
+
+ report.arguments[0] = battery_threshold;
+
+ return report;
+}
+
+struct razer_report razer_chroma_misc_set_orochi2011_led(unsigned char led_bitfield)
+{
+ struct razer_report report = {0};
+ memcpy(&report, &orochi2011_led, sizeof(orochi2011_led));
+
+ // Keep the idle time within bounds
+ report.arguments[1] = led_bitfield;
+
+ return report;
+}
+
+struct razer_report razer_chroma_misc_set_orochi2011_poll_dpi(unsigned short poll_rate, unsigned char dpi_x, unsigned char dpi_y)
+{
+ struct razer_report report = {0};
+ memcpy(&report, &orochi2011_dpi, sizeof(orochi2011_dpi));
+
+ switch(poll_rate) {
+ case 1000:
+ poll_rate = 0x01;
+ break;
+ case 500:
+ poll_rate = 0x02;
+ break;
+ case 125:
+ poll_rate = 0x08;
+ break;
+ default: // 500Hz
+ poll_rate = 0x02;
+ break;
+ }
+
+ report.arguments[1] = poll_rate;
+
+ report.arguments[3] = clamp_u8(dpi_x, 0x15, 0x9C);
+ report.arguments[4] = clamp_u8(dpi_y, 0x15, 0x9C);
+
+ return report;
+}
+
+/**
+ * Set the Naga Trinity to "Static" effect
+ */
+struct razer_report razer_naga_trinity_effect_static(struct razer_rgb *rgb)
+{
+ struct razer_report report = get_razer_report(0x0f, 0x03, 0x0e);
+
+ report.arguments[0] = 0x00; // Variable storage
+ report.arguments[1] = 0x00; // LED ID
+ report.arguments[2] = 0x00; // Unknown
+ report.arguments[3] = 0x00; // Unknown
+ report.arguments[4] = 0x02; // Effect ID
+ report.arguments[5] = rgb->r; // RGB 3x
+ report.arguments[6] = rgb->g;
+ report.arguments[7] = rgb->b;
+ report.arguments[8] = rgb->r;
+ report.arguments[9] = rgb->g;
+ report.arguments[10] = rgb->b;
+ report.arguments[11] = rgb->r;
+ report.arguments[12] = rgb->g;
+ report.arguments[13] = rgb->b;
+ report.transaction_id.id = 0x1f;
+
+ return report;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/razercommon.c b/src/lib/razercommon.c
new file mode 100644
index 0000000..4c8424a
--- /dev/null
+++ b/src/lib/razercommon.c
@@ -0,0 +1,171 @@
+//
+// razercommon.c
+// RazerBlade
+//
+// Based on Linux razer-driver kernel drivers: https://github.com/terrycain/razer-drivers/blob/master/driver/razercommon.h
+//
+#include <stdio.h>
+#include <string.h>
+
+#include "razercommon.h"
+
+/**
+ * Send USB control report to the keyboard
+ * USUALLY index = 0x02
+ * FIREFLY is 0
+ */
+IOReturn razer_send_control_msg(IOUSBDeviceInterface **dev, void const *data, uint report_index) {
+ IOUSBDevRequest request;
+
+ request.bRequest = HID_REQ_SET_REPORT; // 0x09
+ request.bmRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT;
+ request.wValue = 0x300;
+ request.wIndex = report_index;
+ request.wLength = RAZER_USB_REPORT_LEN;
+ request.pData = (void*)data;
+
+ return (*dev)->DeviceRequest(dev, &request);
+}
+
+
+/**
+ * Get a response from the razer device
+ *
+ * Makes a request like normal, this must change a variable in the device as then we
+ * tell it give us data and it gives us a report.
+ *
+ * Supported Devices:
+ * Razer Chroma
+ * Razer Mamba
+ * Razer BlackWidow Ultimate 2013*
+ * Razer Firefly*
+ *
+ * Request report is the report sent to the device specifing what response we want
+ * Response report will get populated with a response
+ *
+ * Returns kIOReturnSuccess when successful
+ */
+IOReturn razer_get_usb_response(IOUSBDeviceInterface **dev, uint report_index, struct razer_report* request_report, uint response_index, struct razer_report* response_report, int wait_us) {
+ IOReturn retval;
+ char buffer[sizeof(struct razer_report)];
+
+ // Send the request to the device.
+ // TODO look to see if index needs to be different for the request and the response
+ retval = razer_send_control_msg(dev, request_report, report_index);
+
+ if(retval != kIOReturnSuccess) {
+ printf("razer_send_control_msg failed!\n");
+
+ return retval;
+ }
+
+ usleep(wait_us);
+
+ IOUSBDevRequest request;
+
+ request.bRequest = HID_REQ_GET_REPORT;
+ request.bmRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN;
+ request.wValue = 0x300;
+ request.wIndex = report_index;
+ request.wLength = RAZER_USB_REPORT_LEN;
+ request.pData = buffer;
+
+ retval = (*dev)->DeviceRequest(dev, &request);
+
+ if(retval != kIOReturnSuccess) {
+ printf("razer_get_usb_response failed\n");
+
+ return retval;
+ }
+
+ memcpy(response_report, buffer, sizeof(struct razer_report));
+
+
+ return retval;
+}
+
+
+/**
+ * Get initialised razer report
+ */
+struct razer_report get_razer_report(unsigned char command_class, unsigned char command_id, unsigned char data_size) {
+ struct razer_report new_report = get_empty_razer_report();
+
+ new_report.status = 0x00;
+ new_report.transaction_id.id = 0xFF;
+ new_report.remaining_packets = 0x00;
+ new_report.protocol_type = 0x00;
+ new_report.command_class = command_class;
+ new_report.command_id.id = command_id;
+ new_report.data_size = data_size;
+
+ return new_report;
+}
+
+
+/**
+ * Get empty razer report
+ */
+struct razer_report get_empty_razer_report(void) {
+ struct razer_report new_report = {0};
+ memset(&new_report, 0, sizeof(struct razer_report));
+
+ return new_report;
+}
+
+
+/**
+ * Calculate the checksum for the usb message
+ *
+ * Checksum byte is stored in the 2nd last byte in the messages payload.
+ * The checksum is generated by XORing all the bytes in the report starting
+ * at byte number 2 (0 based) and ending at byte 88.
+ */
+unsigned char razer_calculate_crc(struct razer_report *report) {
+ /*second to last byte of report is a simple checksum*/
+ /*just xor all bytes up with overflow and you are done*/
+ unsigned char crc = 0;
+ unsigned char *_report = (unsigned char*)report;
+
+ unsigned int i;
+ for(i = 2; i < 88; i++)
+ {
+ crc ^= _report[i];
+ }
+
+ return crc;
+}
+
+
+/**
+ * Clamp a value to a min,max
+ */
+unsigned char clamp_u8(unsigned char value, unsigned char min, unsigned char max) {
+ if(value > max)
+ return max;
+ if(value < min)
+ return min;
+ return value;
+}
+
+unsigned short clamp_u16(unsigned short value, unsigned short min, unsigned short max) {
+ if(value > max)
+ return max;
+ if(value < min)
+ return min;
+ return value;
+}
+
+IOReturn razer_send_control_msg_old_device(IOUSBDeviceInterface **dev, void const *data, uint report_value, uint report_index, uint report_size)
+{
+ IOUSBDevRequest request;
+
+ request.bRequest = HID_REQ_SET_REPORT; // 0x09
+ request.bmRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT; // 0x21
+ request.wValue = report_value;
+ request.wIndex = report_index;
+ request.wLength = report_size;
+ request.pData = (void*)data;
+
+ return (*dev)->DeviceRequest(dev, &request);
+}
diff --git a/src/lib/razerdevice.c b/src/lib/razerdevice.c
new file mode 100755
index 0000000..2b1bda7
--- /dev/null
+++ b/src/lib/razerdevice.c
@@ -0,0 +1,470 @@
+#include <stdlib.h>
+#include "razerdevice.h"
+
+bool is_razer_device(IOUSBDeviceInterface **dev)
+{
+ kern_return_t kr;
+ UInt16 vendor;
+ UInt16 product;
+ UInt16 release;
+
+ kr = (*dev)->GetDeviceVendor(dev, &vendor);
+ kr = (*dev)->GetDeviceProduct(dev, &product);
+ kr = (*dev)->GetDeviceReleaseNumber(dev, &release);
+
+ return vendor == USB_VENDOR_ID_RAZER;
+}
+
+bool is_keyboard(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_NOSTROMO:
+ case USB_DEVICE_ID_RAZER_ORBWEAVER:
+ case USB_DEVICE_ID_RAZER_ORBWEAVER_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2016:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_TARTARUS:
+ case USB_DEVICE_ID_RAZER_TARTARUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_OVERWATCH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA:
+ case USB_DEVICE_ID_RAZER_DEATHSTALKER_EXPERT:
+ case USB_DEVICE_ID_RAZER_DEATHSTALKER_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ case USB_DEVICE_ID_RAZER_ANANSI:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ return true;
+ }
+
+ return false;
+}
+
+bool is_mouse(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_OROCHI_2011:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_3_5G:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_1800:
+ case USB_DEVICE_ID_RAZER_MAMBA_2012_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_2012_WIRELESS:
+ case USB_DEVICE_ID_RAZER_NAGA_2012:
+ case USB_DEVICE_ID_RAZER_IMPERATOR:
+ case USB_DEVICE_ID_RAZER_OUROBOROS:
+ case USB_DEVICE_ID_RAZER_TAIPAN:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_RED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_2013:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_1800:
+ case USB_DEVICE_ID_RAZER_OROCHI_2013:
+ case USB_DEVICE_ID_RAZER_NAGA_2014:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX:
+ case USB_DEVICE_ID_RAZER_ABYSSUS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_CHROMA:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS:
+ case USB_DEVICE_ID_RAZER_MAMBA_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_OROCHI_CHROMA:
+ case USB_DEVICE_ID_RAZER_DIAMONDBACK_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_3500:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_2000:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_ATHERIS_RECEIVER:
+ return true;
+ }
+
+ return false;
+}
+
+bool is_mouse_dock(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ return true;
+ }
+
+ return false;
+}
+
+bool is_mouse_mat(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_FIREFLY:
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ return true;
+ }
+
+ return false;
+}
+
+bool is_egpu(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ return true;
+ }
+
+ return false;
+}
+
+
+bool is_headphone(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ case USB_DEVICE_ID_RAZER_KRAKEN_ULTIMATE:
+ return true;
+ }
+
+ return false;
+}
+
+bool is_accessory(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+ case USB_DEVICE_ID_RAZER_NOMMO_PRO:
+ case USB_DEVICE_ID_RAZER_CHROMA_MUG:
+ case USB_DEVICE_ID_RAZER_CHROMA_BASE:
+ case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+ case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+ case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA:
+ return true;
+ }
+
+ return false;
+}
+
+IOUSBDeviceInterface **getRazerUSBDeviceInterface(int type)
+{
+ CFMutableDictionaryRef matchingDict;
+ matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
+ if (matchingDict == NULL)
+ {
+ return NULL;
+ }
+
+ io_iterator_t iter;
+ kern_return_t kReturn =
+ IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
+ if (kReturn != kIOReturnSuccess)
+ {
+ return NULL;
+ }
+
+ io_service_t usbDevice;
+ while ((usbDevice = IOIteratorNext(iter)))
+ {
+ IOCFPlugInInterface **plugInInterface = NULL;
+ SInt32 score;
+
+ kReturn = IOCreatePlugInInterfaceForService(
+ usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
+
+ IOObjectRelease(usbDevice); // Not needed after plugin created
+ if ((kReturn != kIOReturnSuccess) || plugInInterface == NULL)
+ {
+ // printf("Unable to create plugin (0x%08x)\n", kReturn);
+ continue;
+ }
+
+ IOUSBDeviceInterface **dev = NULL;
+ HRESULT hResult = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev);
+
+ (*plugInInterface)->Release(plugInInterface); // Not needed after device interface created
+ if (hResult || !dev)
+ {
+ // printf("Couldn’t create a device interface (0x%08x)\n", (int) hResult);
+ continue;
+ }
+
+ // Filter out non-Razer devices
+ if (!is_razer_device(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+
+ switch (type)
+ {
+ case TYPE_KEYBOARD:
+ case TYPE_BLADE:
+ // Filter out non-keyboards and non-blade laptops
+ if (!(is_keyboard(dev) || is_blade_laptop(dev)))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+
+ case TYPE_MOUSE:
+ // Filter out non-mice
+ if (!is_mouse(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+
+ case TYPE_MOUSE_DOCK:
+ // Filter out non-mice-mats
+ if (!is_mouse_dock(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+
+ case TYPE_MOUSE_MAT:
+ // Filter out non-mice-mats
+ if (!is_mouse_mat(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+
+ case TYPE_HEADPHONE:
+ if (!is_headphone(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+
+ case TYPE_EGPU:
+ // Filter out non-mice-mats
+ if (!is_egpu(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+ case TYPE_ACCESSORY:
+ if (!is_accessory(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+ break;
+
+ default:
+ // Unsupported Razer peripheral type
+ (*dev)->Release(dev);
+ continue;
+ }
+
+ kReturn = (*dev)->USBDeviceOpen(dev);
+ if (kReturn != kIOReturnSuccess)
+ {
+ printf("Unable to open USB device: %08x\n", kReturn);
+ (*dev)->Release(dev);
+ continue;
+ }
+
+ // Success. We found the Razer USB device.
+ // Caller is responsible for closing USB and release device.
+ IOObjectRelease(iter);
+ return dev;
+ }
+
+ IOObjectRelease(iter);
+ return NULL;
+}
+
+void closeRazerUSBDeviceInterface(IOUSBDeviceInterface **dev)
+{
+ kern_return_t kr;
+ kr = (*dev)->USBDeviceClose(dev);
+ kr = (*dev)->Release(dev);
+}
+
+RazerDevices getAllRazerDevices()
+{
+ RazerDevices allDevices = { .devices = NULL, .size = 0 };
+
+ CFMutableDictionaryRef matchingDict;
+ matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
+ if (matchingDict == NULL)
+ {
+ return allDevices;
+ }
+
+ io_iterator_t iter;
+ kern_return_t kReturn =
+ IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
+ if (kReturn != kIOReturnSuccess)
+ {
+ return allDevices;
+ }
+
+ int array_size = 0;
+ int array_index = -1;
+ RazerDevice *razerDevices = malloc(array_size * sizeof(RazerDevice));
+
+ io_service_t usbDevice;
+ while ((usbDevice = IOIteratorNext(iter)))
+ {
+ IOCFPlugInInterface **plugInInterface = NULL;
+ SInt32 score;
+
+ kReturn = IOCreatePlugInInterfaceForService(
+ usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
+
+ IOObjectRelease(usbDevice); // Not needed after plugin created
+ if ((kReturn != kIOReturnSuccess) || plugInInterface == NULL)
+ {
+ // printf("Unable to create plugin (0x%08x)\n", kReturn);
+ continue;
+ }
+
+ IOUSBDeviceInterface **dev = NULL;
+ HRESULT hResult = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev);
+
+ (*plugInInterface)->Release(plugInInterface); // Not needed after device interface created
+ if (hResult || !dev)
+ {
+ // printf("Couldn’t create a device interface (0x%08x)\n", (int) hResult);
+ continue;
+ }
+
+ // Filter out non-Razer devices
+ if (!is_razer_device(dev))
+ {
+ (*dev)->Release(dev);
+ continue;
+ }
+
+ if(!is_keyboard(dev)
+ && !is_blade_laptop(dev)
+ && !is_mouse(dev)
+ && !is_mouse_dock(dev)
+ && !is_mouse_dock(dev)
+ && !is_mouse_mat(dev)
+ && !is_headphone(dev)
+ && !is_egpu(dev)
+ && !is_accessory(dev)
+ ) {
+ (*dev)->Release(dev);
+ continue;
+ }
+
+ kReturn = (*dev)->USBDeviceOpen(dev);
+ if (kReturn != kIOReturnSuccess)
+ {
+ printf("Unable to open USB device: %08x\n", kReturn);
+ (*dev)->Release(dev);
+ continue;
+ }
+
+ // Success. We found the Razer USB device.
+ // Caller is responsible for closing USB and release device.
+ array_size++;
+ razerDevices = realloc(razerDevices, array_size * sizeof(RazerDevice));
+ array_index++;
+
+ UInt16 productId;
+ (*dev)->GetDeviceProduct(dev, &productId);
+
+ RazerDevice newDevice = { .usbDevice = dev, .internalDeviceId = array_index, .productId = productId };
+ razerDevices[array_index] = newDevice;
+ }
+
+ IOObjectRelease(iter);
+ allDevices.devices = razerDevices;
+ allDevices.size = array_size;
+ return allDevices;
+}
+
+void closeAllRazerDevices(RazerDevices devices)
+{
+ for(int counter=0; counter < devices.size; ++counter) {
+ IOUSBDeviceInterface **dev = devices.devices[counter].usbDevice;
+ (*dev)->USBDeviceClose(dev);
+ (*dev)->Release(dev);
+ }
+ free(devices.devices);
+ devices.devices = NULL;
+}
diff --git a/src/lib/razeregpu_driver.c b/src/lib/razeregpu_driver.c
new file mode 100644
index 0000000..8965c97
--- /dev/null
+++ b/src/lib/razeregpu_driver.c
@@ -0,0 +1,281 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "razeregpu_driver.h"
+#include "razercommon.h"
+#include "razerchromacommon.h"
+
+/**
+ * Send report to the mouse mat
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_EGPU_WAIT_MIN_US);
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report)
+{
+ IOReturn retval = -1;
+
+ struct razer_report response_report = {0};
+
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(usb_dev, request_report, &response_report);
+
+ if (retval == 0) {
+ // Check the packet number, class and command are the same
+ if (response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id)
+ {
+ printf("Response doesn't match request (egpu)\n");
+ } else if (response_report.status == RAZER_CMD_BUSY) {
+ //printf("Device is busy (egpu)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (egpu)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (egpu)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (egpu)\n");
+ }
+ } else {
+ printf("Invalid Report Length (egpu)\n");
+ }
+
+ return response_report;
+}
+
+/**
+ * Write device file "mode_none"
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_egpu_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_wave"
+ *
+ * When 1 is written (as a character, 0x31) the wave effect is displayed moving anti clockwise
+ * if 2 is written (0x32) then the wave effect goes clockwise
+ */
+ssize_t razer_egpu_attr_write_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, ZERO_LED, direction, 0x28);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "mode_breath"
+ */
+ssize_t razer_egpu_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, ZERO_LED);
+ break;
+ }
+ break;
+
+ default:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * Set the mousemat to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_egpu_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if (count == 3)
+ {
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razermousemat: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Set the mousemat to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_egpu_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if (count == 3)
+ {
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razermousemat: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_spectrum"
+ *
+ * Specrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_egpu_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_CORE_X_CHROMA:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+} \ No newline at end of file
diff --git a/src/lib/razerheadphone_driver.c b/src/lib/razerheadphone_driver.c
new file mode 100755
index 0000000..a09316e
--- /dev/null
+++ b/src/lib/razerheadphone_driver.c
@@ -0,0 +1,223 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "razerheadphone_driver.h"
+#include "razercommon.h"
+#include "razerchromacommon.h"
+#include "razerkraken_driver.h"
+
+/**
+ * Send report to the headphone
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_HEADPHONE_WAIT_MIN_US);
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report)
+{
+ IOReturn retval = -1;
+
+ struct razer_report response_report = {0};
+
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(usb_dev, request_report, &response_report);
+
+ if(retval == 0) {
+ // Check the packet number, class and command are the same
+ if(response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id) {
+ printf("Response doesn't match request (headphone)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (headphone)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (headphone)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (headphone)\n");
+ }
+ } else {
+ printf("Invalid Report Length (headphone)\n");
+ }
+
+ return response_report;
+}
+
+/**
+ * Write device file "mode_none"
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_headphone_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+ case USB_DEVICE_ID_RAZER_KRAKEN_ULTIMATE:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ return razer_kraken_attr_write_mode_none(usb_dev, buf, count);
+ default:
+ report = razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_breath"
+ */
+ssize_t razer_headphone_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+ case USB_DEVICE_ID_RAZER_KRAKEN_ULTIMATE:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+ }
+ break;
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ // "Random" colour mode
+ if(count == 1) {
+ count = 3;
+ char color[3] = {(unsigned char)rand(), (unsigned char)rand(), (unsigned char)rand()};
+ return razer_kraken_attr_write_mode_breath(usb_dev, color, count);
+ }
+ return razer_kraken_attr_write_mode_breath(usb_dev, buf, count);
+ default:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * Set the headphone to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_headphone_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+ case USB_DEVICE_ID_RAZER_KRAKEN_ULTIMATE:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x1F;
+ break;
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ return razer_kraken_attr_write_mode_static(usb_dev, buf, count);
+ default:
+ report = razer_chroma_standard_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razerheadphone: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Set the headphone to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_headphone_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+ case USB_DEVICE_ID_RAZER_KRAKEN_ULTIMATE:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x1F;
+ break;
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ return razer_kraken_attr_write_mode_static(usb_dev, buf, count);
+ default:
+ report = razer_chroma_standard_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razerheadphone: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+ssize_t razer_headphone_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ return razer_kraken_attr_write_mode_spectrum(usb_dev, buf, count);
+ }
+ return count;
+} \ No newline at end of file
diff --git a/src/lib/razerkbd_driver.c b/src/lib/razerkbd_driver.c
new file mode 100644
index 0000000..054e8af
--- /dev/null
+++ b/src/lib/razerkbd_driver.c
@@ -0,0 +1,1560 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "razerkbd_driver.h"
+#include "razerchromacommon.h"
+#include "razercommon.h"
+
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **dev, struct razer_report *request_report);
+
+bool is_blade_laptop(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_2018:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_ADV:
+ case USB_DEVICE_ID_RAZER_BLADE_MID_2019_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_STUDIO_EDITION_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_QHD:
+ case USB_DEVICE_ID_RAZER_BLADE_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_MID_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017_FULLHD:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2019:
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Read device file "game_mode"
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_mode_game(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_led_state(VARSTORE, GAME_LED);
+ struct razer_report response;
+
+ response = razer_send_payload(usb_dev, &report);
+ return sprintf(buf, "%d\n", response.arguments[2]);
+}
+
+/**
+ * Write device file "mode_macro"
+ *
+ * When 1 is written (as a character, 0x31) Macro mode will be enabled, if 0 is written (0x30)
+ * then game mode will be disabled
+ */
+ssize_t razer_attr_write_mode_macro(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ unsigned char enabled = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = razer_chroma_standard_set_led_state(VARSTORE, MACRO_LED, enabled);
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_macro_effect"
+ *
+ * When 1 is written the LED will blink, 0 will static
+ */
+ssize_t razer_attr_write_mode_macro_effect(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+
+ struct razer_report report = {0};
+ unsigned char enabled = (unsigned char)strtoul(buf, NULL, 10);
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_standard_set_led_effect(NOSTORE, MACRO_LED, enabled);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ report = razer_chroma_standard_set_led_effect(NOSTORE, MACRO_LED, enabled);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_ANANSI:
+ report = razer_chroma_standard_set_led_effect(NOSTORE, MACRO_LED, enabled);
+ razer_send_payload(usb_dev, &report);
+
+ report = razer_chroma_standard_set_led_blinking(NOSTORE, MACRO_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_set_led_effect(VARSTORE, MACRO_LED, enabled);
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Read device file "macro_mode_effect"
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_mode_macro_effect(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_led_effect(VARSTORE, MACRO_LED);
+ struct razer_report response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%d\n", response.arguments[2]);
+}
+
+/**
+ * Write device file "mode_pulsate"
+ *
+ * The brightness oscillates between fully on and fully off generating a pulsing effect
+ */
+ssize_t razer_attr_write_mode_pulsate(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = razer_chroma_standard_set_led_effect(VARSTORE, BACKLIGHT_LED, 0x02);
+ razer_send_payload(usb_dev, &report);
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013:
+ report = razer_chroma_standard_set_led_effect(VARSTORE, LOGO_LED, 0x02);
+ break;
+ }
+
+ return count;
+}
+
+/**
+ * Read device file "mode_pulsate"
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_mode_pulsate(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_led_effect(VARSTORE, LOGO_LED);
+ struct razer_report response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%d\n", response.arguments[2]);
+}
+
+/**
+ * Read device file "profile_led_red"
+ *
+ * Actually a Yellow LED
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_tartarus_profile_led_red(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_led_state(VARSTORE, RED_PROFILE_LED);
+ struct razer_report response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%d\n", response.arguments[2]);
+}
+
+/**
+ * Read device file "profile_led_green"
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_tartarus_profile_led_green(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_led_state(VARSTORE, GREEN_PROFILE_LED);
+ struct razer_report response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%d\n", response.arguments[2]);
+}
+
+/**
+ * Read device file "profile_led_blue"
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_tartarus_profile_led_blue(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_led_state(VARSTORE, BLUE_PROFILE_LED);
+ struct razer_report response = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "%d\n", response.arguments[2]);
+}
+
+/**
+ * Read device file "get_firmware_version"
+ *
+ * Returns a string
+ */
+ssize_t razer_attr_read_get_firmware_version(IOUSBDeviceInterface **usb_dev, char *buf)
+{
+ struct razer_report report = razer_chroma_standard_get_firmware_version();
+ struct razer_report response_report = razer_send_payload(usb_dev, &report);
+
+ return sprintf(buf, "v%d.%d\n", response_report.arguments[0], response_report.arguments[1]);
+}
+
+/**
+ * Write device file "mode_none"
+ *
+ * No keyboard effect is activated whenever this file is written to
+ */
+ssize_t razer_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+ razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ 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_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_ANANSI:
+ report = razer_chroma_standard_set_led_state(VARSTORE, BACKLIGHT_LED, OFF);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ report = razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_wave"
+ *
+ * When 1 is written (as a character, 0x31) the wave effect is displayed moving left across the keyboard
+ * if 2 is written (0x32) then the wave effect goes right
+ *
+ * For the extended its 0x00 and 0x01
+ */
+ssize_t razer_attr_write_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, int count, int speed)
+{
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report;
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction, speed);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ 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_CHROMA_V2:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction, speed);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+/**
+ * Write device file "mode_spectrum"
+ *
+ * Specrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_ANANSI:
+ report = razer_chroma_standard_set_led_state(VARSTORE, BACKLIGHT_LED, ON);
+ razer_send_payload(usb_dev, &report);
+ report = razer_chroma_standard_set_led_effect(VARSTORE, BACKLIGHT_LED, LED_SPECTRUM_CYCLING);
+ break;
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x1F; // TODO move to a usb_device variable
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ report = razer_chroma_standard_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_reactive"
+ *
+ * Sets reactive mode when this file is written to. A speed byte and 3 RGB bytes should be written
+ */
+ssize_t razer_attr_write_mode_reactive(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report;
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ if (count == 4)
+ {
+ unsigned char speed = (unsigned char)buf[0];
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, BACKLIGHT_LED, speed, (struct razer_rgb *)&buf[1]);
+ 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_CHROMA_V2:
+ 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_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
+ break;
+ default:
+ report = razer_chroma_standard_matrix_effect_reactive(VARSTORE, BACKLIGHT_LED, speed, (struct razer_rgb *)&buf[1]);
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Reactive only accepts Speed, RGB (4byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * Set the keyboard to mode when 3 RGB bytes are written
+ */
+ssize_t razer_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_ORBWEAVER:
+ case USB_DEVICE_ID_RAZER_DEATHSTALKER_EXPERT:
+ report = razer_chroma_standard_set_led_effect(VARSTORE, BACKLIGHT_LED, 0x00);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013: // Doesn't need any parameters as can only do one type of static
+ report = razer_chroma_standard_set_led_effect(VARSTORE, LOGO_LED, 0x00);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_OVERWATCH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA:
+ case USB_DEVICE_ID_RAZER_DEATHSTALKER_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2016:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_MID_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_QHD:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_2018:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_ADV:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_MID_2019_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_STUDIO_EDITION_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017_FULLHD:
+ case USB_DEVICE_ID_RAZER_TARTARUS:
+ case USB_DEVICE_ID_RAZER_TARTARUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_ORBWEAVER_CHROMA:
+ if (count == 3)
+ {
+ report = razer_chroma_standard_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Static mode only accepts RGB (3byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ if (count == 3)
+ {
+ report = razer_chroma_standard_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Static mode only accepts RGB (3byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ if (count == 3)
+ {
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Static mode only accepts RGB (3byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ if (count == 3)
+ {
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x1F;
+ 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)
+ {
+ report = razer_chroma_standard_set_led_state(VARSTORE, BACKLIGHT_LED, ON);
+ razer_send_payload(usb_dev, &report);
+ report = razer_chroma_standard_set_led_effect(VARSTORE, BACKLIGHT_LED, LED_STATIC);
+ razer_send_payload(usb_dev, &report);
+ report = razer_chroma_standard_set_led_rgb(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ printf("razerkbd: Static mode only accepts RGB (3byte)\n");
+ break;
+
+ default:
+ printf("razerkbd: Cannot set static mode for this device\n");
+ break;
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Set the keyboard to mode when 3 RGB bytes are written
+ */
+ssize_t razer_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_ORBWEAVER:
+ case USB_DEVICE_ID_RAZER_DEATHSTALKER_EXPERT:
+ report = razer_chroma_standard_set_led_effect(NOSTORE, BACKLIGHT_LED, 0x00);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013: // Doesn't need any parameters as can only do one type of static
+ report = razer_chroma_standard_set_led_effect(NOSTORE, LOGO_LED, 0x00);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_OVERWATCH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA:
+ case USB_DEVICE_ID_RAZER_DEATHSTALKER_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2016:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_MID_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_QHD:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_2018:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_ADV:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_MID_2019_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_STUDIO_EDITION_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017_FULLHD:
+ case USB_DEVICE_ID_RAZER_TARTARUS:
+ case USB_DEVICE_ID_RAZER_TARTARUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_ORBWEAVER_CHROMA:
+ if (count == 3)
+ {
+ report = razer_chroma_standard_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Static mode only accepts RGB (3byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ if (count == 3)
+ {
+ report = razer_chroma_standard_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Static mode only accepts RGB (3byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ if (count == 3)
+ {
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Static mode only accepts RGB (3byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ if (count == 3)
+ {
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x1F;
+ 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)
+ {
+ report = razer_chroma_standard_set_led_state(NOSTORE, BACKLIGHT_LED, ON);
+ razer_send_payload(usb_dev, &report);
+ report = razer_chroma_standard_set_led_effect(NOSTORE, BACKLIGHT_LED, LED_STATIC);
+ razer_send_payload(usb_dev, &report);
+ report = razer_chroma_standard_set_led_rgb(NOSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ printf("razerkbd: Static mode only accepts RGB (3byte)\n");
+ break;
+
+ default:
+ printf("razerkbd: Cannot set static mode for this device\n");
+ break;
+ }
+
+ return count;
+}
+
+/**
+* Write device file "mode_starlight"
+*
+* Starlight keyboard effect is activated whenever this file is written to (for bw2016)
+*
+* Or if an Ornata
+* 7 bytes, speed, rgb, rgb
+* 4 bytes, speed, rgb
+* 1 byte, speed
+*/
+ssize_t razer_attr_write_mode_starlight(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+ struct razer_rgb rgb1 = {.r = 0x00, .g = 0xFF, .b = 0x00};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ if (count == 4)
+ {
+ report = razer_chroma_extended_matrix_effect_starlight_single(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Starlight only accepts Speed (1byte). Speed, RGB (4byte). Speed, RGB, RGB (7byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ 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]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else if (count == 4)
+ {
+ report = razer_chroma_extended_matrix_effect_starlight_single(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else if (count == 1)
+ {
+ report = razer_chroma_extended_matrix_effect_starlight_random(VARSTORE, BACKLIGHT_LED, buf[0]);
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Starlight only accepts Speed (1byte). Speed, RGB (4byte). Speed, RGB, RGB (7byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ 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 = 0x1F;
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ 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]);
+ report.transaction_id.id = 0x1F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else if (count == 4)
+ {
+ report = razer_chroma_extended_matrix_effect_starlight_single(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1]);
+ report.transaction_id.id = 0x1F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else if (count == 1)
+ {
+ report = razer_chroma_extended_matrix_effect_starlight_random(VARSTORE, BACKLIGHT_LED, buf[0]);
+ report.transaction_id.id = 0x1F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Starlight only accepts Speed (1byte). Speed, RGB (4byte). Speed, RGB, RGB (7byte)");
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ if (count == 7)
+ {
+ report = razer_chroma_standard_matrix_effect_starlight_dual(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1], (struct razer_rgb *)&buf[4]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else if (count == 4)
+ {
+ report = razer_chroma_standard_matrix_effect_starlight_single(VARSTORE, BACKLIGHT_LED, buf[0], (struct razer_rgb *)&buf[1]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else if (count == 1)
+ {
+ report = razer_chroma_standard_matrix_effect_starlight_random(VARSTORE, BACKLIGHT_LED, buf[0]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ }
+ else
+ {
+ printf("razerkbd: Starlight only accepts Speed (1byte). Speed, RGB (4byte). Speed, RGB, RGB (7byte)");
+ }
+ break;
+
+ default: // BW2016 can do normal starlight
+ report = razer_chroma_standard_matrix_effect_starlight_single(VARSTORE, BACKLIGHT_LED, 0x01, &rgb1);
+ razer_send_payload(usb_dev, &report);
+ break;
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_breath"
+ */
+ssize_t razer_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ default:
+ printf("razerkbd: Breathing only accepts '1' (1byte). RGB (3byte). RGB, RGB (6byte)");
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case 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]);
+ razer_send_payload(usb_dev, &report);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case 1: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ razer_send_payload(usb_dev, &report);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ default:
+ printf("razerkbd: Breathing only accepts '1' (1byte). RGB (3byte). RGB, RGB (6byte)");
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case 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]);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case 1: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ default:
+ printf("razerkbd: Breathing only accepts '1' (1byte). RGB (3byte). RGB, RGB (6byte)");
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ 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 = 0x1F;
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ razer_send_payload(usb_dev, &report);
+ break;
+ // TODO move default to case 1:. Then default: printk(warning). Also remove pointless buffer
+ }
+ break;
+
+ default:
+ switch (count)
+ {
+ case 3: // Single colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0]);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ razer_send_payload(usb_dev, &report);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ razer_send_payload(usb_dev, &report);
+ break;
+ // TODO move default to case 1:. Then default: printk(warning). Also remove pointless buffer
+ }
+ break;
+ }
+
+ return count;
+}
+
+ssize_t has_inverted_led_state(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_QHD:
+ case USB_DEVICE_ID_RAZER_BLADE_LATE_2016:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Read device file "set_logo"
+ *
+ * Sets the logo lighting state to the ASCII number written to this file.
+ */
+ssize_t razer_attr_read_set_logo(IOUSBDeviceInterface **usb_dev, char *buf, int count)
+{
+ struct razer_report report = razer_chroma_standard_get_led_effect(VARSTORE, LOGO_LED);
+ struct razer_report response = get_empty_razer_report();
+ int state;
+
+ // Blade laptops don't use effect for logo on/off, and mode 2 ("blink") is technically unsupported.
+ if (is_blade_laptop(usb_dev))
+ {
+ report = razer_chroma_standard_get_led_state(VARSTORE, LOGO_LED);
+ }
+
+ response = razer_send_payload(usb_dev, &report);
+ state = response.arguments[2];
+
+ if (has_inverted_led_state(usb_dev) && (state == 0 || state == 1))
+ {
+ state = !state;
+ }
+
+ return sprintf(buf, "%d\n", state);
+}
+
+/**
+ * Write device file "set_logo"
+ *
+ * Sets the logo lighting state to the ASCII number written to this file.
+ */
+ssize_t razer_attr_write_set_logo(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ unsigned char state = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = {0};
+
+ if (has_inverted_led_state(usb_dev) && (state == 0 || state == 1))
+ {
+ state = !state;
+ }
+
+ // Blade laptops are... different. They use state instead of effect.
+ // Note: This does allow setting of mode 2 ("blink"), but this is an undocumented feature.
+ if (is_blade_laptop(usb_dev) && (state == 0 || state == 1))
+ {
+ report = razer_chroma_standard_set_led_state(VARSTORE, LOGO_LED, state);
+ }
+ else
+ {
+ report = razer_chroma_standard_set_led_effect(VARSTORE, LOGO_LED, state);
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_custom"
+ *
+ * Sets the keyboard to custom mode whenever the file is written to
+ */
+ssize_t razer_attr_write_mode_custom(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_effect_custom_frame();
+ 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_CHROMA_V2:
+ report = razer_chroma_extended_matrix_effect_custom_frame();
+ report.transaction_id.id = 0x1F;
+ 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
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_custom_frame(VARSTORE); // Possibly could use VARSTORE
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "set_fn_toggle"
+ *
+ * Sets the logo lighting state to the ASCII number written to this file.
+ */
+ssize_t razer_attr_write_set_fn_toggle(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ unsigned char state = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = razer_chroma_misc_fn_key_toggle(state);
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "set_brightness"
+ *
+ * Sets the brightness to the ASCII number written to this file.
+ */
+ssize_t razer_attr_write_set_brightness(IOUSBDeviceInterface **usb_dev, ushort brightness, int count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, ZERO_LED, brightness);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, BACKLIGHT_LED, brightness);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, BACKLIGHT_LED, brightness);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, LOGO_LED, brightness);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NOSTROMO:
+ default:
+ if (is_blade_laptop(usb_dev))
+ {
+ report = razer_chroma_misc_set_blade_brightness(brightness);
+ }
+ else
+ {
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, BACKLIGHT_LED, brightness);
+ }
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Read device file "macro_mode"
+ *
+ * Returns a string
+ */
+ushort razer_attr_read_set_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ bool is_matrix_brightness = false;
+ unsigned char brightness = 0;
+ struct razer_report report = {0};
+ struct razer_report response = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product)
+ {
+
+ case USB_DEVICE_ID_RAZER_TARTARUS_V2:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, ZERO_LED);
+ report.transaction_id.id = 0x1F;
+ is_matrix_brightness = true;
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE:
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_CYNOSA_LITE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, BACKLIGHT_LED);
+ is_matrix_brightness = true;
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE:
+ case USB_DEVICE_ID_RAZER_CYNOSA_V2:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ 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_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, LOGO_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NOSTROMO:
+ default:
+ if (is_blade_laptop(usb_dev))
+ {
+ report = razer_chroma_misc_get_blade_brightness();
+ }
+ else
+ {
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, BACKLIGHT_LED);
+ }
+ break;
+ }
+
+ response = razer_send_payload(usb_dev, &report);
+
+ // Brightness is stored elsewhere for the stealth cmds
+ if (is_blade_laptop(usb_dev))
+ {
+ brightness = response.arguments[1];
+ }
+ else
+ {
+ brightness = response.arguments[2];
+ }
+
+ if(is_matrix_brightness) {
+ brightness = round(brightness / 2.55);
+ }
+
+ return brightness;
+}
+
+/**
+ * Write device file "matrix_custom_frame"
+ *
+ * Format
+ * ROW_ID START_COL STOP_COL RGB...
+ */
+ssize_t razer_attr_write_matrix_custom_frame(IOUSBDeviceInterface **usb_dev, const char *buf, int count)
+{
+ struct razer_report report;
+ int offset = 0;
+ unsigned char row_id;
+ unsigned char start_col;
+ unsigned char stop_col;
+ unsigned char row_length;
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ //printk(KERN_ALERT "razerkbd: Total count: %d\n", (unsigned char)count);
+
+ while (offset < count)
+ {
+ if (offset + 3 > count)
+ {
+ printf("razerkbd: Wrong Amount of data provided: Should be ROW_ID, START_COL, STOP_COL, N_RGB\n");
+ break;
+ }
+
+ row_id = buf[offset++];
+ start_col = buf[offset++];
+ stop_col = buf[offset++];
+ row_length = ((stop_col + 1) - start_col) * 3;
+
+ // printk(KERN_ALERT "razerkbd: Row ID: %d, Start: %d, Stop: %d, row length: %d\n", row_id, start_col, stop_col, row_length);
+
+ if (start_col > stop_col)
+ {
+ printf("razerkbd: Start column is greater than end column\n");
+ break;
+ }
+
+ if (offset + row_length > count)
+ {
+ printf("razerkbd: Not enough RGB to fill row\n");
+ break;
+ }
+
+ // Offset now at beginning of RGB data
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ORNATA:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN:
+ case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report = razer_chroma_extended_matrix_set_custom_frame(row_id, start_col, stop_col, (unsigned char *)&buf[offset]);
+ 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_CHROMA_V2:
+ 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_DEATHSTALKER_CHROMA:
+ report = razer_chroma_misc_one_row_set_custom_frame(start_col, stop_col, (unsigned char *)&buf[offset]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLADE_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2:
+ report = razer_chroma_standard_matrix_set_custom_frame(row_id, start_col, stop_col, (unsigned char *)&buf[offset]);
+ report.transaction_id.id = 0x3F; // TODO move to a usb_device variable
+ break;
+
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_MID_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_LATE_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_STEALTH_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_QHD:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_LATE_2016:
+ case USB_DEVICE_ID_RAZER_BLADE_2018:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_2018_BASE:
+ case USB_DEVICE_ID_RAZER_BLADE_2019_ADV:
+ case USB_DEVICE_ID_RAZER_BLADE_MID_2019_MERCURY:
+ case USB_DEVICE_ID_RAZER_BLADE_STUDIO_EDITION_2019:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017:
+ case USB_DEVICE_ID_RAZER_BLADE_PRO_2017_FULLHD:
+ report.transaction_id.id = 0x80; // Fall into the 2016/blade/blade2016 to set device id
+ /* fall through */
+ default:
+ report = razer_chroma_standard_matrix_set_custom_frame(row_id, start_col, stop_col, (unsigned char *)&buf[offset]);
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+
+ // *3 as its 3 bytes per col (RGB)
+ offset += row_length;
+ }
+
+ return count;
+}
+
+/**
+ * Send report to the keyboard
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ uint report_index;
+ uint response_index;
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_ANANSI:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_TE:
+ case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2:
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK:
+ case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI:
+ report_index = 0x02;
+ response_index = 0x02;
+ break;
+ case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3:
+ report_index = 0x03;
+ response_index = 0x03;
+ break;
+ default:
+ report_index = 0x01;
+ response_index = 0x01;
+ break;
+ }
+
+ return razer_get_usb_response(usb_dev, report_index, request_report, response_index, response_report, RAZER_BLACKWIDOW_CHROMA_WAIT_MIN_US);
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **dev, struct razer_report *request_report)
+{
+ IOReturn retval = -1;
+
+ struct razer_report response_report = {0};
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(dev, request_report, &response_report);
+
+ if (retval == kIOReturnSuccess)
+ {
+ // Check the packet number, class and command are the same
+ if (response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id)
+ {
+ printf("Response doesnt match request (keyboard)\n");
+ } else if (response_report.status == RAZER_CMD_BUSY) {
+ //printf("Device is busy (keyboard)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (keyboard)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (keyboard)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (keyboard)\n");
+ }
+ } else {
+ printf("Invalid Report Length (keyboard)\n");
+ }
+
+ return response_report;
+}
diff --git a/src/lib/razerkraken_driver.c b/src/lib/razerkraken_driver.c
new file mode 100644
index 0000000..df7d9e1
--- /dev/null
+++ b/src/lib/razerkraken_driver.c
@@ -0,0 +1,324 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "razerkraken_driver.h"
+#include "razercommon.h"
+
+/**
+ * Send USB control report to the keyboard
+ * USUALLY index = 0x02
+ * FIREFLY is 0
+ */
+IOReturn razer_kraken_send_control_msg(IOUSBDeviceInterface **dev, struct razer_kraken_request_report* data, unsigned char skip) {
+ IOUSBDevRequest request;
+
+ request.bRequest = HID_REQ_SET_REPORT; // 0x09
+ request.bmRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT;
+ request.wValue = 0x0204;
+ request.wIndex = 0x0003;
+ request.wLength = 37;
+ request.pData = (void*)data;
+
+ IOReturn result = (*dev)->DeviceRequest(dev, &request);
+
+ // Wait
+ if(skip != 1) {
+ usleep(data->length * 15 * 1000);
+ }
+ return result;
+}
+
+static struct razer_kraken_device get_kraken_device(IOUSBDeviceInterface **dev)
+{
+ UInt16 product = -1;
+ (*dev)->GetDeviceProduct(dev, &product);
+
+ struct razer_kraken_device device;
+ device.usb_pid = product;
+
+ switch (product)
+ {
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ device.led_mode_address = KYLIE_SET_LED_ADDRESS;
+ device.custom_address = KYLIE_CUSTOM_ADDRESS_START;
+ device.breathing_address[0] = KYLIE_BREATHING1_ADDRESS_START;
+ device.breathing_address[1] = KYLIE_BREATHING2_ADDRESS_START;
+ device.breathing_address[2] = KYLIE_BREATHING3_ADDRESS_START;
+ break;
+ }
+
+ return device;
+}
+
+/**
+ * Get a request report
+ *
+ * report_id - The type of report
+ * destination - where data is going (like ram)
+ * length - amount of data
+ * address - where to write data to
+ */
+static struct razer_kraken_request_report get_kraken_request_report(unsigned char report_id, unsigned char destination, unsigned char length, unsigned short address)
+{
+ struct razer_kraken_request_report report;
+ memset(&report, 0, sizeof(struct razer_kraken_request_report));
+
+ report.report_id = report_id;
+ report.destination = destination;
+ report.length = length;
+ report.addr_h = (address >> 8);
+ report.addr_l = (address & 0xFF);
+
+ return report;
+}
+
+/**
+ * Get a union containing the effect bitfield
+ */
+static union razer_kraken_effect_byte get_kraken_effect_byte(void)
+{
+ union razer_kraken_effect_byte effect_byte;
+ memset(&effect_byte, 0, sizeof(union razer_kraken_effect_byte));
+
+ return effect_byte;
+}
+
+/**
+ * Write device file "mode_spectrum"
+ *
+ * Specrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_kraken_attr_write_mode_spectrum(IOUSBDeviceInterface **dev, const char *buf, size_t count)
+{
+ struct razer_kraken_device device = get_kraken_device(dev);
+ struct razer_kraken_request_report report = get_kraken_request_report(0x04, 0x40, 0x01, device.led_mode_address);
+ union razer_kraken_effect_byte effect_byte = get_kraken_effect_byte();
+
+ // Spectrum Cycling | ON
+ effect_byte.bits.on_off_static = 1;
+ effect_byte.bits.spectrum_cycling = 1;
+
+ report.arguments[0] = effect_byte.value;
+
+ // Lock access to sending USB as adhering to the razer len*15ms delay
+ razer_kraken_send_control_msg(dev, &report, 0);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_none"
+ *
+ * None effect mode is activated whenever the file is written to
+ */
+ssize_t razer_kraken_attr_write_mode_none(IOUSBDeviceInterface **dev, const char *buf, size_t count)
+{
+ struct razer_kraken_device device = get_kraken_device(dev);
+ struct razer_kraken_request_report report = get_kraken_request_report(0x04, 0x40, 0x01, device.led_mode_address);
+ union razer_kraken_effect_byte effect_byte = get_kraken_effect_byte();
+
+ // Spectrum Cycling | OFF
+ effect_byte.bits.on_off_static = 0;
+ effect_byte.bits.spectrum_cycling = 0;
+
+ report.arguments[0] = effect_byte.value;
+
+ // Lock access to sending USB as adhering to the razer len*15ms delay
+ razer_kraken_send_control_msg(dev, &report, 0);
+
+ return count;
+}
+
+
+/**
+ * Write device file "mode_static"
+ *
+ * Static effect mode is activated whenever the file is written to with 3 bytes
+ */
+ssize_t razer_kraken_attr_write_mode_static(IOUSBDeviceInterface **dev, const char *buf, size_t count)
+{
+ struct razer_kraken_device device = get_kraken_device(dev);
+ struct razer_kraken_request_report rgb_report = get_kraken_request_report(0x04, 0x40, count, device.breathing_address[0]);
+ struct razer_kraken_request_report effect_report = get_kraken_request_report(0x04, 0x40, 0x01, device.led_mode_address);
+ union razer_kraken_effect_byte effect_byte = get_kraken_effect_byte();
+
+ if(count == 3 || count == 4) {
+
+ rgb_report.arguments[0] = buf[0];
+ rgb_report.arguments[1] = buf[1];
+ rgb_report.arguments[2] = buf[2];
+
+ if(count == 4) {
+ rgb_report.arguments[3] = buf[3];
+ }
+
+ // ON/Static
+ effect_byte.bits.on_off_static = 1;
+ effect_report.arguments[0] = effect_byte.value;
+
+ // Basically Kraken Classic doesn't take RGB arguments so only do it for the KrakenV1,V2,Ultimate
+ switch(device.usb_pid) {
+ case USB_DEVICE_ID_RAZER_KRAKEN_V2:
+ razer_kraken_send_control_msg(dev, &rgb_report, 0);
+ break;
+ }
+ // Send Set static command
+ razer_kraken_send_control_msg(dev, &effect_report, 0);
+
+ } else {
+ printf("razerkraken: Static mode only accepts RGB (3byte) or RGB with intensity (4byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_custom"
+ *
+ * Custom effect mode is activated whenever the file is written to with 3 bytes
+ */
+ssize_t razer_kraken_attr_write_mode_custom(IOUSBDeviceInterface **dev, const char *buf, size_t count)
+{
+ struct razer_kraken_device device = get_kraken_device(dev);
+ struct razer_kraken_request_report rgb_report = get_kraken_request_report(0x04, 0x40, count, device.custom_address);
+ struct razer_kraken_request_report effect_report = get_kraken_request_report(0x04, 0x40, 0x01, device.led_mode_address);
+ union razer_kraken_effect_byte effect_byte = get_kraken_effect_byte();
+
+ if(count == 3 || count == 4) {
+
+ rgb_report.arguments[0] = buf[0];
+ rgb_report.arguments[1] = buf[1];
+ rgb_report.arguments[2] = buf[2];
+
+ if(count == 4) {
+ rgb_report.arguments[3] = buf[3];
+ }
+
+ // ON/Static
+ effect_byte.bits.on_off_static = 1;
+ effect_report.arguments[0] = 1; //effect_byte.value;
+
+ // Lock sending of the 2 commands
+ razer_kraken_send_control_msg(dev, &rgb_report, 1);
+ razer_kraken_send_control_msg(dev, &effect_report, 1);
+
+ } else {
+ printf("razerkraken: Custom mode only accepts RGB (3byte) or RGB with intensity (4byte)\n");
+ }
+
+ return count;
+}
+
+
+/**
+ * Write device file "mode_breath"
+ *
+ * Breathing effect mode is activated whenever the file is written to with 3,6 or 9 bytes
+ */
+ssize_t razer_kraken_attr_write_mode_breath(IOUSBDeviceInterface **dev, const char *buf, size_t count)
+{
+ struct razer_kraken_device device = get_kraken_device(dev);
+ struct razer_kraken_request_report effect_report = get_kraken_request_report(0x04, 0x40, 0x01, device.led_mode_address);
+ union razer_kraken_effect_byte effect_byte = get_kraken_effect_byte();
+
+ // Short circuit here as rainie only does breathing1
+ if(device.usb_pid == USB_DEVICE_ID_RAZER_KRAKEN && count != 3) {
+ printf("razerkraken: Breathing mode only accepts RGB (3byte)\n");
+ return count;
+ }
+
+ if(count == 3) {
+ struct razer_kraken_request_report rgb_report = get_kraken_request_report(0x04, 0x40, 0x03, device.breathing_address[0]);
+
+ rgb_report.arguments[0] = buf[0];
+ rgb_report.arguments[1] = buf[1];
+ rgb_report.arguments[2] = buf[2];
+
+ // ON/Static
+ effect_byte.bits.on_off_static = 1;
+ effect_byte.bits.single_colour_breathing = 1;
+ effect_byte.bits.sync = 1;
+ effect_report.arguments[0] = effect_byte.value;
+
+ // Lock sending of the 2 commands
+ razer_kraken_send_control_msg(dev, &rgb_report, 0);
+
+ razer_kraken_send_control_msg(dev, &effect_report, 0);
+ } else if(count == 6) {
+ struct razer_kraken_request_report rgb_report = get_kraken_request_report(0x04, 0x40, 0x03, device.breathing_address[1]);
+ struct razer_kraken_request_report rgb_report2 = get_kraken_request_report(0x04, 0x40, 0x03, device.breathing_address[1]+4); // Address the 2nd set of colours
+
+ rgb_report.arguments[0] = buf[0];
+ rgb_report.arguments[1] = buf[1];
+ rgb_report.arguments[2] = buf[2];
+ rgb_report2.arguments[0] = buf[3];
+ rgb_report2.arguments[1] = buf[4];
+ rgb_report2.arguments[2] = buf[5];
+
+ // ON/Static
+ effect_byte.bits.on_off_static = 1;
+ effect_byte.bits.two_colour_breathing = 1;
+ effect_byte.bits.sync = 1;
+ effect_report.arguments[0] = effect_byte.value;
+
+ // Lock sending of the 2 commands
+ razer_kraken_send_control_msg(dev, &rgb_report, 0);
+
+ razer_kraken_send_control_msg(dev, &rgb_report2, 0);
+
+ razer_kraken_send_control_msg(dev, &effect_report, 0);
+
+ } else if(count == 9) {
+ struct razer_kraken_request_report rgb_report = get_kraken_request_report(0x04, 0x40, 0x03, device.breathing_address[2]);
+ struct razer_kraken_request_report rgb_report2 = get_kraken_request_report(0x04, 0x40, 0x03, device.breathing_address[2]+4); // Address the 2nd set of colours
+ struct razer_kraken_request_report rgb_report3 = get_kraken_request_report(0x04, 0x40, 0x03, device.breathing_address[2]+8); // Address the 3rd set of colours
+
+ rgb_report.arguments[0] = buf[0];
+ rgb_report.arguments[1] = buf[1];
+ rgb_report.arguments[2] = buf[2];
+ rgb_report2.arguments[0] = buf[3];
+ rgb_report2.arguments[1] = buf[4];
+ rgb_report2.arguments[2] = buf[5];
+ rgb_report3.arguments[0] = buf[6];
+ rgb_report3.arguments[1] = buf[7];
+ rgb_report3.arguments[2] = buf[8];
+
+ // ON/Static
+ effect_byte.bits.on_off_static = 1;
+ effect_byte.bits.three_colour_breathing = 1;
+ effect_byte.bits.sync = 1;
+ effect_report.arguments[0] = effect_byte.value;
+
+ // Lock sending of the 2 commands
+ razer_kraken_send_control_msg(dev, &rgb_report, 0);
+
+ razer_kraken_send_control_msg(dev, &rgb_report2, 0);
+
+ razer_kraken_send_control_msg(dev, &rgb_report3, 0);
+
+ razer_kraken_send_control_msg(dev, &effect_report, 0);
+
+ } else {
+ printf("razerkraken: Breathing mode only accepts RGB (3byte), RGB RGB (6byte) or RGB RGB RGB (9byte)\n");
+ }
+
+ return count;
+} \ No newline at end of file
diff --git a/src/lib/razermouse_driver.c b/src/lib/razermouse_driver.c
new file mode 100644
index 0000000..68002d9
--- /dev/null
+++ b/src/lib/razermouse_driver.c
@@ -0,0 +1,2210 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "razermouse_driver.h"
+#include "razercommon.h"
+#include "razerchromacommon.h"
+
+/**
+ * Static values for mouse devices
+ */
+// Setup orochi2011
+int orochi2011_dpi = 0x4c;
+int orochi2011_poll = 500;
+
+// Setup default values for DeathAdder 3.5G
+DeathAdder3_5g da3_5g = {
+ .leds = 3, // Lights up all lights
+ .dpi = 1, // 3500 DPI
+ .profile = 1, // Profile 1
+ .poll = 1 // Poll rate 1000
+};
+
+/**
+ * Send report to the mouse
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product) {
+ // These devices require longer waits to read their firmware, serial, and other setting values
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_NEW_MOUSE_RECEIVER_WAIT_MIN_US);
+ break;
+
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_VIPER_MOUSE_RECEIVER_WAIT_MIN_US);
+ break;
+
+ default:
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_MOUSE_WAIT_MIN_US);
+ }
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report)
+{
+ IOReturn retval = -1;
+
+ struct razer_report response_report = {0};
+
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(usb_dev, request_report, &response_report);
+
+ if(retval == 0) {
+ // Check the packet number, class and command are the same
+ if(response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id) {
+ printf("Response doesn't match request (mouse)\n");
+ } else if (response_report.status == RAZER_CMD_BUSY) {
+ //printf("Device is busy (mouse)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (mouse)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (mouse)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (mouse)\n");
+ }
+ } else {
+ printf("Invalid Report Length (mouse)\n");
+ }
+
+ return response_report;
+}
+
+ssize_t razer_attr_write_side_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, side, direction, 0x28);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, side, direction, 0x28);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_wave not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+ssize_t razer_attr_write_side_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_static(VARSTORE, side, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, side, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, side, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_static not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Static mode only accepts RGB (3byte)\n");
+ }
+ return count;
+}
+
+ssize_t razer_attr_write_side_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_static(NOSTORE, side, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, side, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, side, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: side_mode_static_no_store not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Static mode only accepts RGB (3byte)\n");
+ }
+ return count;
+}
+
+ssize_t razer_attr_write_side_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_spectrum(VARSTORE, side);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, side);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, side);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: side_mode_spectrum not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+ssize_t razer_attr_write_side_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_single(VARSTORE, side, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_dual(VARSTORE, side, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_random(VARSTORE, side);
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, side, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, side, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, side);
+ break;
+ }
+ break;
+ }
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ report.transaction_id.id = 0x3f;
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+ssize_t razer_attr_write_side_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_none(VARSTORE, LOGO_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, side);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, side);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_none not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "logo_mode_wave" (for extended mouse matrix effects)
+ *
+ * Wave effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_logo_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, LOGO_LED, direction, 0x28);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, LOGO_LED, direction, 0x28);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_wave not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "scroll_mode_wave" (for extended mouse matrix effects)
+ *
+ * Wave effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_scroll_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, SCROLL_WHEEL_LED, direction, 0x28);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, SCROLL_WHEEL_LED, direction, 0x28);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_wave not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "left_mode_wave" (for extended mouse matrix effects)
+ *
+ * Wave effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_left_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_wave(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_wave" (for extended mouse matrix effects)
+ *
+ * Wave effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_right_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_wave(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+/**
+ * Write device file "logo_mode_static" (for extended mouse matrix effects)
+ *
+ * Set the mouse to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_attr_write_logo_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_static(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+ case USB_DEVICE_ID_RAZER_ABYSSUS_V2:
+ report = razer_chroma_standard_set_led_rgb(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+ default:
+ printf("razermouse: logo_mode_static not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "logo_mode_static" (for extended mouse matrix effects)
+ *
+ * Set the mouse to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_attr_write_scroll_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_static(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+ case USB_DEVICE_ID_RAZER_ABYSSUS_V2:
+ report = razer_chroma_standard_set_led_rgb(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_static not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "left_mode_wave" (for extended mouse matrix effects)
+ *
+ * Wave effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_left_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_static(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_static" (for extended mouse matrix effects)
+ *
+ * Static effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_right_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_static(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+
+/**
+ * Write device file "logo_mode_static" (for extended mouse matrix effects)
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Set the mouse to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_attr_write_logo_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_static(NOSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+ case USB_DEVICE_ID_RAZER_ABYSSUS_V2:
+ report = razer_chroma_standard_set_led_rgb(NOSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_static not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "logo_mode_static" (for extended mouse matrix effects)
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Set the mouse to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_attr_write_scroll_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_static(NOSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x1f;
+ break;
+ case USB_DEVICE_ID_RAZER_ABYSSUS_V2:
+ report = razer_chroma_standard_set_led_rgb(NOSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_static not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "left_mode_no_store" (for extended mouse matrix effects)
+ *
+ * NOSTORE version for efficiency in custom lighting configurations
+ */
+ssize_t razer_attr_write_left_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_static_no_store(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_no_store" (for extended mouse matrix effects)
+ *
+ * NOSTORE version for efficiency in custom lighting configurations
+ */
+ssize_t razer_attr_write_right_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_static_no_store(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+/**
+ * Write device file "logo_mode_spectrum" (for extended mouse matrix effects)
+ *
+ * Spectrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_logo_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_spectrum(VARSTORE, LOGO_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, LOGO_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, LOGO_LED);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_spectrum not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "logo_mode_spectrum" (for extended mouse matrix effects)
+ *
+ * Spectrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_scroll_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_spectrum(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, SCROLL_WHEEL_LED);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_spectrum not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "left_mode_spectrum" (for extended mouse matrix effects)
+ *
+ * Spectrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_left_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_spectrum(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_spectrum" (for extended mouse matrix effects)
+ *
+ * Spectrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_attr_write_right_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_spectrum(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+
+/**
+ * Write device file "logo_mode_breath" (for extended mouse matrix effects)
+ *
+ * Sets breathing mode by writing 1, 3 or 6 bytes
+ */
+ssize_t razer_attr_write_logo_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_single(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_dual(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_random(VARSTORE, LOGO_LED);
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, LOGO_LED);
+ break;
+ }
+ break;
+ }
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ report.transaction_id.id = 0x3f;
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "scroll_mode_breath" (for extended mouse matrix effects)
+ *
+ * Sets breathing mode by writing 1, 3 or 6 bytes
+ */
+ssize_t razer_attr_write_scroll_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_single(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_dual(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_mouse_extended_matrix_effect_breathing_random(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+ }
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, SCROLL_WHEEL_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+ }
+ break;
+ }
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ report.transaction_id.id = 0x3f;
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "left_mode_breath" (for extended mouse matrix effects)
+ *
+ * Sets breathing mode by writing 1, 3 or 6 bytes
+ */
+ssize_t razer_attr_write_left_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_breath(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_breath" (for extended mouse matrix effects)
+ *
+ * Sets breathing mode by writing 1, 3 or 6 bytes
+ */
+ssize_t razer_attr_write_right_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_breath(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+/**
+ * Write device file "logo_mode_none" (for extended mouse matrix effects)
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_attr_write_logo_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_none(VARSTORE, LOGO_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, LOGO_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, LOGO_LED);
+ report.transaction_id.id = 0x1f;
+ break;
+
+
+ default:
+ printf("razermouse: logo_mode_none not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "logo_mode_none" (for extended mouse matrix effects)
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_attr_write_scroll_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_none(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, SCROLL_WHEEL_LED);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_none not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "left_mode_none" (for extended mouse matrix effects)
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_attr_write_left_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_none(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_none" (for extended mouse matrix effects)
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_attr_write_right_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_none(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+// These are for older mice, eg DeathAdder 2013
+
+/**
+ * Write device file "scroll_led_effect"
+ */
+ssize_t razer_attr_write_scroll_led_effect(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ unsigned char effect = (unsigned char)strtoul(buf, NULL, 10);
+ struct razer_report report = razer_chroma_standard_set_led_effect(VARSTORE, SCROLL_WHEEL_LED, effect);
+ report.transaction_id.id = 0x3F;
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "logo_led_effect"
+ */
+ssize_t razer_attr_write_logo_led_effect(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ unsigned char effect = (unsigned char)strtoul(buf, NULL, 10);
+ struct razer_report report = razer_chroma_standard_set_led_effect(VARSTORE, LOGO_LED, effect);
+ report.transaction_id.id = 0x3F;
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "logo_led_rgb"
+ */
+ssize_t razer_attr_write_logo_led_rgb(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ if(count == 3) {
+ report = razer_chroma_standard_set_led_rgb(VARSTORE, LOGO_LED, (struct razer_rgb*)&buf[0]);
+ report.transaction_id.id = 0x3F;
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermouse: Logo LED mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_reactive"
+ *
+ * Sets reactive mode when this file is written to. A speed byte and 3 RGB bytes should be written
+ */
+ssize_t razer_attr_write_logo_mode_reactive(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 4) {
+ unsigned char speed = (unsigned char)buf[0];
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_mouse_extended_matrix_effect_reactive(VARSTORE, LOGO_LED, speed, (struct razer_rgb*)&buf[1]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_8KHZ:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, LOGO_LED, speed, (struct razer_rgb*)&buf[1]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, LOGO_LED, speed, (struct razer_rgb*)&buf[1]);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: logo_mode_reactive not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ } else {
+ printf("razermouse: Reactive only accepts Speed, RGB (4byte)\n");
+ }
+ return count;
+}
+
+/**
+ * Write device file "scroll_mode_reactive" (for extended mouse matrix effects)
+ *
+ * Sets reactive mode when this file is written to. A speed byte and 3 RGB bytes should be written
+ */
+ssize_t razer_attr_write_scroll_mode_reactive(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 4) {
+ unsigned char speed = (unsigned char)buf[0];
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ case USB_DEVICE_ID_RAZER_NAGA_CHROMA:
+ report = razer_chroma_mouse_extended_matrix_effect_reactive(VARSTORE, SCROLL_WHEEL_LED, speed, (struct razer_rgb*)&buf[1]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, SCROLL_WHEEL_LED, speed, (struct razer_rgb*)&buf[1]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, SCROLL_WHEEL_LED, speed, (struct razer_rgb*)&buf[1]);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: scroll_mode_reactive not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ } else {
+ printf("razermouse: Reactive only accepts Speed, RGB (4byte)\n");
+ }
+ return count;
+}
+
+ssize_t razer_attr_write_side_mode_reactive(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 4) {
+ unsigned char speed = (unsigned char)buf[0];
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, side, speed, (struct razer_rgb*)&buf[1]);
+ break;
+
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_effect_reactive(VARSTORE, side, speed, (struct razer_rgb*)&buf[1]);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ printf("razermouse: left/right mode_reactive not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ } else {
+ printf("razermouse: Reactive only accepts Speed, RGB (4byte)\n");
+ }
+ return count;
+}
+
+/**
+ * Write device file "left_mode_reactive" (for extended mouse matrix effects)
+ *
+ * Sets reactive mode when this file is written to. A speed byte and 3 RGB bytes should be written
+ */
+ssize_t razer_attr_write_left_mode_reactive(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_reactive(usb_dev, buf, count, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_mode_reactive" (for extended mouse matrix effects)
+ *
+ * Sets reactive mode when this file is written to. A speed byte and 3 RGB bytes should be written
+ */
+ssize_t razer_attr_write_right_mode_reactive(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ return razer_attr_write_side_mode_reactive(usb_dev, buf, count, RIGHT_SIDE_LED);
+}
+
+ushort razer_attr_read_dpi(IOUSBDeviceInterface **usb_dev)
+{
+ struct razer_report report, response_report;
+ report = razer_chroma_misc_get_dpi_xy(0x01);
+ response_report = razer_send_payload(usb_dev, &report);
+ ushort dpi_x = (response_report.arguments[1] << 8) | (response_report.arguments[2] & 0xFF);
+ return dpi_x;
+}
+
+void razer_attr_write_dpi(IOUSBDeviceInterface **usb_dev, ushort dpi_x, ushort dpi_y)
+{
+ struct razer_report report = razer_chroma_misc_set_dpi_xy(0x01, dpi_x, dpi_y);
+ razer_send_payload(usb_dev, &report);
+}
+
+ssize_t razer_attr_read_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_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ report.transaction_id.id = 0x3f;
+ break;
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ report.transaction_id.id = 0x1f;
+ 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_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_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE:
+ case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ report.transaction_id.id = 0x3f;
+ break;
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ report.transaction_id.id = 0x1f;
+ break;
+ }
+
+ response_report = razer_send_payload(usb_dev, &report);
+ return sprintf(buf, "%d\n", response_report.arguments[1]);
+}
+
+/**
+ * Read device file "poll_rate"
+ *
+ * Returns a string
+ */
+ushort razer_attr_read_poll_rate(IOUSBDeviceInterface **usb_dev)
+{
+ struct razer_report report = razer_chroma_misc_get_polling_rate();
+ struct razer_report response_report = {0};
+ unsigned short polling_rate = 0;
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_DEATHADDER_3_5G:
+ switch(da3_5g.poll) {
+ case 0x01:
+ polling_rate = 1000;
+ break;
+ case 0x02:
+ polling_rate = 500;
+ break;
+ case 0x03:
+ polling_rate = 125;
+ break;
+ }
+ return polling_rate;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report.transaction_id.id = 0x3f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_ATHERIS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report.transaction_id.id = 0x1f;
+ break;
+ }
+
+ if(product == USB_DEVICE_ID_RAZER_OROCHI_2011) {
+ response_report.arguments[0] = orochi2011_poll;
+ } else {
+ response_report = razer_send_payload(usb_dev, &report);
+ }
+
+ switch(response_report.arguments[0]) {
+ case 0x01:
+ polling_rate = 1000;
+ break;
+ case 0x02:
+ polling_rate = 500;
+ break;
+ case 0x08:
+ polling_rate = 125;
+ break;
+ }
+
+ return polling_rate;
+}
+
+void deathadder3_5g_set_poll_rate(IOUSBDeviceInterface **usb_dev, unsigned short poll_rate)
+{
+ switch(poll_rate) {
+ case 1000:
+ da3_5g.poll = 1;
+ break;
+ case 500:
+ da3_5g.poll = 2;
+ break;
+ case 125:
+ da3_5g.poll = 3;
+ break;
+ default: // 500
+ da3_5g.poll = 2;
+ break;
+ }
+
+ razer_send_control_msg_old_device(usb_dev, &da3_5g, 0x10, 0x00, 4);
+}
+
+/**
+ * Write device file "poll_rate"
+ *
+ * Sets the poll rate
+ */
+void razer_attr_write_poll_rate(IOUSBDeviceInterface **usb_dev, ushort polling_rate)
+{
+ struct razer_report report = razer_chroma_misc_set_polling_rate(polling_rate);
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_DEATHADDER_3_5G:
+ deathadder3_5g_set_poll_rate(usb_dev, polling_rate);
+ return;
+
+ case USB_DEVICE_ID_RAZER_OROCHI_2011:
+ orochi2011_poll = polling_rate;
+ report = razer_chroma_misc_set_orochi2011_poll_dpi(orochi2011_poll, orochi2011_dpi, orochi2011_dpi);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRED:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report.transaction_id.id = 0x3f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_ATHERIS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report.transaction_id.id = 0x1f;
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+}
+
+/**
+ * Write device file "matrix_brightness"
+ *
+ * Sets the brightness to the ASCII number written to this file.
+ */
+
+void razer_attr_write_matrix_brightness(IOUSBDeviceInterface **usb_dev, unsigned char brightness)
+{
+ brightness = round(brightness * 2.55);
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS:
+ report = razer_chroma_misc_set_dock_brightness(brightness);
+ break;
+
+ case USB_DEVICE_ID_RAZER_OROCHI_CHROMA:
+ // Orochi sets brightness of scroll wheel apparently
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, SCROLL_WHEEL_LED, brightness);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, BACKLIGHT_LED, brightness);
+ report.transaction_id.id = 0x3f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, 0x00, brightness);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ // Naga Trinity uses the LED 0x00 and Matrix Brightness
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, 0x00, brightness);
+ break;
+
+ default:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, BACKLIGHT_LED, brightness);
+ break;
+ }
+ razer_send_payload(usb_dev, &report);
+}
+
+/**
+ * Read device file "matrix_brightness"
+ *
+ * Returns a string
+ */
+ushort razer_attr_read_matrix_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ struct razer_report report = {0};
+ struct razer_report response = {0};
+ unsigned char brightness_index = 0x02;
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS:
+ report = razer_chroma_misc_get_dock_brightness();
+ brightness_index = 0x00;
+ break;
+
+ case USB_DEVICE_ID_RAZER_OROCHI_CHROMA:
+ // Orochi sets brightness of scroll wheel apparently
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ // Orochi sets brightness of scroll wheel apparently
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, BACKLIGHT_LED);
+ report.transaction_id.id = 0x3f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, 0x00);
+ report.transaction_id.id = 0x1F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_TRINITY:
+ // Naga Trinity uses the LED 0x00 and Matrix Brightness
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, 0x00);
+ break;
+
+ default:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+ response = razer_send_payload(usb_dev, &report);
+
+ if (response.status != RAZER_CMD_SUCCESSFUL) {
+ return 0;
+ }
+ // Brightness is at arg[0] for dock and arg[1] for led_brightness
+ ushort brightness = response.arguments[brightness_index];
+ brightness = round(brightness / 2.55);
+ return brightness;
+}
+
+/**
+ * Read device file "scroll_led_brightness"
+ */
+ushort razer_attr_read_scroll_led_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ struct razer_report report = razer_chroma_standard_get_led_brightness(VARSTORE, SCROLL_WHEEL_LED);
+ struct razer_report response = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, SCROLL_WHEEL_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, SCROLL_WHEEL_LED);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, SCROLL_WHEEL_LED);
+ break;
+ }
+
+ response = razer_send_payload(usb_dev, &report);
+
+ ushort brightness = response.arguments[2];
+ brightness = round(brightness / 2.55);
+ return brightness;
+}
+
+/**
+ * Write device file "scroll_led_brightness"
+ */
+void razer_attr_write_scroll_led_brightness(IOUSBDeviceInterface **usb_dev, unsigned char brightness)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, SCROLL_WHEEL_LED, brightness);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, SCROLL_WHEEL_LED, brightness);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, SCROLL_WHEEL_LED, brightness);
+ break;
+
+ default:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, SCROLL_WHEEL_LED, brightness);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+}
+
+/**
+ * Read device file "logo_led_brightness"
+ */
+ushort razer_attr_read_logo_led_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ struct razer_report report = {0};
+ struct razer_report response = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, LOGO_LED);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, LOGO_LED);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, LOGO_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, LOGO_LED);
+ break;
+ }
+
+ response = razer_send_payload(usb_dev, &report);
+
+ ushort brightness = response.arguments[2];
+ brightness = round(brightness / 2.55);
+ return brightness;
+}
+
+/**
+ * Write device file "logo_led_brightness"
+ */
+void razer_attr_write_logo_led_brightness(IOUSBDeviceInterface **usb_dev, unsigned char brightness)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_NAGA_HEX_V2:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, LOGO_LED, brightness);
+ report.transaction_id.id = 0x3F;
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ case USB_DEVICE_ID_RAZER_BASILISK_V2:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, LOGO_LED, brightness);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION:
+ case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL:
+ case USB_DEVICE_ID_RAZER_VIPER:
+ case USB_DEVICE_ID_RAZER_VIPER_MINI:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED:
+ case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS:
+ case USB_DEVICE_ID_RAZER_BASILISK:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS:
+ case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, LOGO_LED, brightness);
+ break;
+
+ default:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, LOGO_LED, brightness);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+}
+
+ushort razer_attr_read_side_led_brightness(IOUSBDeviceInterface **usb_dev, int side)
+{
+ struct razer_report report = {0};
+ struct razer_report response = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, side);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ report = razer_chroma_extended_matrix_get_brightness(VARSTORE, side);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ report = razer_chroma_standard_get_led_brightness(VARSTORE, side);
+ break;
+ }
+
+ response = razer_send_payload(usb_dev, &report);
+
+ ushort brightness = response.arguments[2];
+ brightness = round(brightness / 2.55);
+ return brightness;
+}
+
+void razer_attr_write_side_led_brightness(IOUSBDeviceInterface **usb_dev, unsigned char brightness, int side)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER:
+ case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, side, brightness);
+ break;
+
+ case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020:
+ case USB_DEVICE_ID_RAZER_MAMBA_ELITE:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, side, brightness);
+ report.transaction_id.id = 0x1f;
+ break;
+
+ default:
+ report = razer_chroma_standard_set_led_brightness(VARSTORE, side, brightness);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+}
+
+/**
+ * Read device file "left_led_brightness"
+ */
+ushort razer_attr_read_left_led_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ return razer_attr_read_side_led_brightness(usb_dev, LEFT_SIDE_LED);
+}
+
+/**
+ * Write device file "left_led_brightness"
+ */
+void razer_attr_write_left_led_brightness(IOUSBDeviceInterface **usb_dev, unsigned char brightness)
+{
+ return razer_attr_write_side_led_brightness(usb_dev, brightness, LEFT_SIDE_LED);
+}
+
+/**
+ * Read device file "right_led_brightness"
+ */
+ushort razer_attr_read_right_led_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ return razer_attr_read_side_led_brightness(usb_dev, RIGHT_SIDE_LED);
+}
+
+/**
+ * Write device file "right_led_brightness"
+ */
+void razer_attr_write_right_led_brightness(IOUSBDeviceInterface **usb_dev, unsigned char brightness)
+{
+ return razer_attr_write_side_led_brightness(usb_dev, brightness, RIGHT_SIDE_LED);
+}
diff --git a/src/lib/razermousedock_driver.c b/src/lib/razermousedock_driver.c
new file mode 100644
index 0000000..7545a54
--- /dev/null
+++ b/src/lib/razermousedock_driver.c
@@ -0,0 +1,242 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "razermousedock_driver.h"
+#include "razercommon.h"
+#include "razerchromacommon.h"
+
+/**
+ * Send report to the dock
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch (product) {
+ // These devices require longer waits to read their firmware, serial, and other setting values
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_MOUSE_DOCK_WAIT_MIN_US);
+ break;
+
+ default:
+ return -1;
+ }
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report)
+{
+ IOReturn retval = -1;
+
+ struct razer_report response_report = {0};
+
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(usb_dev, request_report, &response_report);
+
+ if(retval == 0) {
+ // Check the packet number, class and command are the same
+ if(response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id) {
+ printf("Response doesn't match request (mousedock)\n");
+ } else if (response_report.status == RAZER_CMD_BUSY) {
+ //printf("Device is busy (mousedock)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (mousedock)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (mousedock)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (mousedock)\n");
+ }
+ } else {
+ printf("Invalid Report Length (mousedock)\n");
+ }
+
+ return response_report;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * Static effect mode is activated whenever the file is written to with 3 bytes
+ */
+ssize_t razer_mouse_dock_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb*) & buf[0]);
+ break;
+
+ default:
+ printf("razerdock: logo_mode_static not supported for this model\n");
+ break;
+ }
+
+ report.transaction_id.id = 0x3F;
+
+ razer_send_payload(usb_dev, &report);
+
+ } else {
+ printf("razerdock: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+
+/**
+ * Write device file "mode_static"
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Static effect mode is activated whenever the file is written to with 3 bytes
+ */
+ssize_t razer_mouse_dock_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, ZERO_LED, (struct razer_rgb*) & buf[0]);
+ break;
+
+ default:
+ printf("razerdock: logo_mode_static not supported for this model\n");
+ break;
+ }
+
+ report.transaction_id.id = 0x3F;
+
+ razer_send_payload(usb_dev, &report);
+
+ } else {
+ printf("razerdock: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+
+/**
+ * Write device file "logo_mode_spectrum" (for extended mouse matrix effects)
+ *
+ * Spectrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_mouse_dock_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+ break;
+
+ default:
+ printf("razerdock: logo_mode_spectrum not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+
+/**
+ * Write device file "logo_mode_breath" (for extended mouse matrix effects)
+ *
+ * Sets breathing mode by writing 1, 3 or 6 bytes
+ */
+ssize_t razer_mouse_dock_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, ZERO_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, ZERO_LED);
+ break;
+ }
+ break;
+ }
+
+ report.transaction_id.id = 0x3f;
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+
+/**
+ * Write device file "logo_mode_none" (for extended mouse matrix effects)
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_mouse_dock_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
+ break;
+
+ default:
+ printf("razerdock: logo_mode_none not supported for this model\n");
+ return count;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
diff --git a/src/lib/razermousemat_driver.c b/src/lib/razermousemat_driver.c
new file mode 100644
index 0000000..430c822
--- /dev/null
+++ b/src/lib/razermousemat_driver.c
@@ -0,0 +1,333 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to Terry Cain <[email protected]>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "razermousemat_driver.h"
+#include "razercommon.h"
+#include "razerchromacommon.h"
+
+/**
+ * Send report to the mouse mat
+ */
+static int razer_get_report(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report, struct razer_report *response_report)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ return razer_get_usb_response(usb_dev, 0x00, request_report, 0x00, response_report, RAZER_MOUSEMAT_WAIT_MIN_US);
+}
+
+/**
+ * Function to send to device, get response, and actually check the response
+ */
+static struct razer_report razer_send_payload(IOUSBDeviceInterface **usb_dev, struct razer_report *request_report)
+{
+ IOReturn retval = -1;
+
+ struct razer_report response_report = {0};
+
+ request_report->crc = razer_calculate_crc(request_report);
+
+ retval = razer_get_report(usb_dev, request_report, &response_report);
+
+ if(retval == 0) {
+ // Check the packet number, class and command are the same
+ if(response_report.remaining_packets != request_report->remaining_packets ||
+ response_report.command_class != request_report->command_class ||
+ response_report.command_id.id != request_report->command_id.id) {
+ printf("Response doesn't match request (mousemat)\n");
+ } else if (response_report.status == RAZER_CMD_BUSY) {
+ //printf("Device is busy (mousemat)\n");
+ } else if (response_report.status == RAZER_CMD_FAILURE) {
+ printf("Command failed (mousemat)\n");
+ } else if (response_report.status == RAZER_CMD_NOT_SUPPORTED) {
+ printf("Command not supported (mousemat)\n");
+ } else if (response_report.status == RAZER_CMD_TIMEOUT) {
+ printf("Command timed out (mousemat)\n");
+ }
+ } else {
+ printf("Invalid Report Length (mousemat)\n");
+ }
+
+ return response_report;
+}
+
+/**
+ * Write device file "mode_none"
+ *
+ * No effect is activated whenever this file is written to
+ */
+ssize_t razer_mouse_mat_attr_write_mode_none(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_none(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_wave"
+ *
+ * When 1 is written (as a character, 0x31) the wave effect is displayed moving anti clockwise
+ * if 2 is written (0x32) then the wave effect goes clockwise
+ */
+ssize_t razer_mouse_mat_attr_write_mode_wave(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ unsigned char direction = (unsigned char)strtol(buf, NULL, 10);
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ report = razer_chroma_extended_matrix_effect_wave(VARSTORE, ZERO_LED, direction, 0x28);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+}
+
+/**
+ * Write device file "mode_breath"
+ */
+ssize_t razer_mouse_mat_attr_write_mode_breath(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_dual(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0], (struct razer_rgb *)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_extended_matrix_effect_breathing_random(VARSTORE, ZERO_LED);
+ break;
+ }
+ break;
+
+ default:
+ switch(count) {
+ case 3: // Single colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_single(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ break;
+
+ case 6: // Dual colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_dual(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0], (struct razer_rgb*)&buf[3]);
+ break;
+
+ default: // "Random" colour mode
+ report = razer_chroma_standard_matrix_effect_breathing_random(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * Set the mousemat to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_mouse_mat_attr_write_mode_static(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_static(VARSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermousemat: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+/**
+ * Write device file "mode_static"
+ *
+ * ** NOSTORE version for efficiency in custom lighting configurations
+ *
+ * Set the mousemat to static mode when 3 RGB bytes are written
+ */
+ssize_t razer_mouse_mat_attr_write_mode_static_no_store(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ if(count == 3) {
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ report = razer_chroma_extended_matrix_effect_static(NOSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_static(NOSTORE, BACKLIGHT_LED, (struct razer_rgb*)&buf[0]);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ } else {
+ printf("razermousemat: Static mode only accepts RGB (3byte)\n");
+ }
+
+ return count;
+}
+
+ssize_t razer_mouse_mat_attr_write_set_brightness(IOUSBDeviceInterface **usb_dev, ushort brightness, size_t count)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+ struct razer_report report = {0};
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ report = razer_chroma_extended_matrix_brightness(VARSTORE, ZERO_LED, brightness);
+ break;
+
+ default:
+ printf("razermousemat: Unknown device\n");
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+
+ return count;
+}
+
+ushort razer_mouse_mat_attr_read_set_brightness(IOUSBDeviceInterface **usb_dev)
+{
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ struct razer_report report = razer_chroma_standard_get_led_brightness(VARSTORE, BACKLIGHT_LED);
+ struct razer_report response = {0};
+ unsigned char brightness = 0;
+
+ switch (product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ brightness = 0xff; // Unfortunately, we can't read the brightness from the device directly. return dummy value.
+ break;
+
+ default:
+ response = razer_send_payload(usb_dev, &report);
+ brightness = response.arguments[2];
+ break;
+ }
+ brightness = round(brightness / 2.55);
+ return brightness;
+}
+
+/**
+ * Write device file "mode_spectrum"
+ *
+ * Specrum effect mode is activated whenever the file is written to
+ */
+ssize_t razer_mouse_mat_attr_write_mode_spectrum(IOUSBDeviceInterface **usb_dev, const char *buf, size_t count)
+{
+ struct razer_report report = {0};
+
+ UInt16 product = -1;
+ (*usb_dev)->GetDeviceProduct(usb_dev, &product);
+
+ switch(product) {
+ case USB_DEVICE_ID_RAZER_FIREFLY_V2:
+ case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
+ case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
+ report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+ break;
+
+ default:
+ report = razer_chroma_standard_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+ break;
+ }
+
+ razer_send_payload(usb_dev, &report);
+ return count;
+} \ No newline at end of file