diff --git a/Controllers/CoolerMasterController/CMRGBController.cpp b/Controllers/CoolerMasterController/CMRGBController.cpp new file mode 100644 index 00000000..b18c38f3 --- /dev/null +++ b/Controllers/CoolerMasterController/CMRGBController.cpp @@ -0,0 +1,367 @@ +/*-------------------------------------------------------------------*\ +| CMRGBController.cpp | +| | +| Driver for Coolermaster RGB USB Controller | +| | +| Nic W (midgetspy) 13th Apr 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include "RGBController_CMRGBController.h" +#include "CMRGBController.h" +#include + +CMRGBController::CMRGBController(hid_device* dev_handle, char* path) +{ + const int szTemp = 256; + wchar_t tmpName[szTemp]; + + dev = dev_handle; + location = path; + + hid_get_manufacturer_string(dev, tmpName, szTemp); + std::wstring wName = std::wstring(tmpName); + device_name = std::string(wName.begin(), wName.end()); + + hid_get_product_string(dev, tmpName, szTemp); + wName = std::wstring(tmpName); + device_name.append(" ").append(std::string(wName.begin(), wName.end())); + + hid_get_serial_number_string(dev, tmpName, szTemp); + wName = std::wstring(tmpName); + serial = std::string(wName.begin(), wName.end()); + + ReadCurrentMode(); +} + +void CMRGBController::SendFlowControl(unsigned char byte_flag) +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { 0x00, CM_RGBC_OPCODE_OP_FLOW_CONTROL }; //Packets on Windows need a 0x00 if they don't use ReportIDs + + buffer[0x02] = byte_flag; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); +} + +void CMRGBController::SendApply() +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { 0x00, CM_RGBC_OPCODE_OP_UNKNOWN_50, CM_RGBC_OPCODE_TYPE_UNKNOWN_55 }; //Packets on Windows need a 0x00 if they don't use ReportIDs + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); +} + +void CMRGBController::SendReadMode() +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_READ; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = CM_RGBC_OPCODE_TYPE_MODE; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); + + current_mode = buffer[CM_RGBC_PACKET_OFFSET_MODE]; +} + +void CMRGBController::SendSetMode(unsigned char mode) +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_WRITE; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = CM_RGBC_OPCODE_TYPE_MODE; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MODE] = mode; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); +} + +void CMRGBController::SendSetCustomColors(RGBColor color_1, RGBColor color_2, RGBColor color_3, RGBColor color_4) +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + current_port1_color = color_1; + current_port2_color = color_2; + current_port3_color = color_3; + current_port4_color = color_4; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_WRITE; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = CM_RGBC_OPCODE_TYPE_LED_INFO; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1] = RGBGetRValue(color_1); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1 + 1] = RGBGetGValue(color_1); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1 + 2] = RGBGetBValue(color_1); + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2] = RGBGetRValue(color_2); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2 + 1] = RGBGetGValue(color_2); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2 + 2] = RGBGetBValue(color_2); + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3] = RGBGetRValue(color_3); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3 + 1] = RGBGetGValue(color_3); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3 + 2] = RGBGetBValue(color_3); + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4] = RGBGetRValue(color_4); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4 + 1] = RGBGetGValue(color_4); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4 + 2] = RGBGetBValue(color_4); + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); +} + +void CMRGBController::SendReadCustomColors() +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_READ; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = CM_RGBC_OPCODE_TYPE_LED_INFO; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); + + current_port1_color = ToRGBColor( + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1 + 1], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1 + 2]); + current_port2_color = ToRGBColor( + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2 + 1], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2 + 2]); + current_port3_color = ToRGBColor( + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3 + 1], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3 + 2]); + current_port4_color = ToRGBColor( + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4 + 1], + buffer[CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4 + 2]); +} + +void CMRGBController::SendSetConfig(unsigned char mode, unsigned char speed, unsigned char brightness, RGBColor color_1, RGBColor color_2, bool simplified=false, bool multilayer=false) +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + current_mode = mode; + current_speed = speed; + current_brightness = brightness; + current_mode_color_1 = color_1; + current_mode_color_2 = color_2; + + /*---------------------------------------------*\ + | Handle special cases | + \*---------------------------------------------*/ + switch(mode) + { + case CM_RGBC_MODE_COLOR_CYCLE: + brightness = 0xDF; + color_1 = 0xFFFFFF; + color_2 = 0x000000; + break; + + case CM_RGBC_MODE_OFF: + brightness = 0x03; + break; + } + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_WRITE; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = simplified ? CM_RGBC_OPCODE_TYPE_CONFIG_SIMPLIFIED : CM_RGBC_OPCODE_TYPE_CONFIG_FULL; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MODE] = mode; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_SPEED] = speed; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_BRIGHTNESS] = brightness; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_COLOR_1] = RGBGetRValue(color_1); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_COLOR_1 + 1] = RGBGetGValue(color_1); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_COLOR_1 + 2] = RGBGetBValue(color_1); + + /*---------------------------------------------*\ + | Magic values, meaning unknown | + \*---------------------------------------------*/ + buffer[REPORT_ID_OFFSET + 0x06] = (mode == CM_RGBC_MODE_BREATHING) ? 0x20 : 0x00; + buffer[REPORT_ID_OFFSET + 0x07] = (mode == CM_RGBC_MODE_STAR) ? 0x19 : 0xFF; + buffer[REPORT_ID_OFFSET + 0x08] = 0xFF; + + if(!simplified) + { + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MULTILAYER] = multilayer ? 0x01 : 0x00; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_COLOR_2] = RGBGetRValue(color_2); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_COLOR_2 + 1] = RGBGetGValue(color_2); + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_COLOR_2 + 2] = RGBGetBValue(color_2); + + for(int i = REPORT_ID_OFFSET + 16; i < CM_RGBC_PACKET_SIZE; i++) + { + buffer[i] = 0xFF; + } + } + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); +} + +void CMRGBController::SendReadConfig(unsigned char mode) +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_READ; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = CM_RGBC_OPCODE_TYPE_CONFIG_FULL; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_MODE] = mode; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); + + current_mode = mode; + current_speed = buffer[CM_RGBC_PACKET_OFFSET_SPEED]; + current_brightness = buffer[CM_RGBC_PACKET_OFFSET_BRIGHTNESS]; + + current_mode_color_1 = ToRGBColor( + buffer[CM_RGBC_PACKET_OFFSET_COLOR_1], + buffer[CM_RGBC_PACKET_OFFSET_COLOR_1 + 1], + buffer[CM_RGBC_PACKET_OFFSET_COLOR_1 + 2]); + current_mode_color_2 = ToRGBColor( + buffer[CM_RGBC_PACKET_OFFSET_COLOR_2], + buffer[CM_RGBC_PACKET_OFFSET_COLOR_2 + 1], + buffer[CM_RGBC_PACKET_OFFSET_COLOR_2 + 2]); +} + +void CMRGBController::SendCustomColorStart() +{ + const unsigned char buffer_size = CM_RGBC_PACKET_SIZE; + unsigned char buffer[buffer_size] = { }; + + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_OP] = CM_RGBC_OPCODE_OP_WRITE; + buffer[REPORT_ID_OFFSET + CM_RGBC_PACKET_OFFSET_TYPE] = CM_RGBC_OPCODE_TYPE_UNKNOWN_30; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_RGBC_INTERRUPT_TIMEOUT); +} + +void CMRGBController::ReadCurrentMode() +{ + SendFlowControl(CM_RGBC_OPCODE_FLOW_01); + + SendReadMode(); +} + +void CMRGBController::ReadModeConfig(unsigned char mode) +{ + SendFlowControl(CM_RGBC_OPCODE_FLOW_00); + + SendReadConfig(mode); + + if(mode == CM_RGBC_MODE_MULTIPLE) + { + SendReadCustomColors(); + } +} + +void CMRGBController::SetMode(unsigned char mode, unsigned char speed, unsigned char brightness, RGBColor color_1, RGBColor color_2) +{ + SendFlowControl(CM_RGBC_OPCODE_FLOW_01); + + SendSetConfig(mode, speed, brightness, color_1, color_2, false); + + SendSetMode(mode); + + SendApply(); + + SendFlowControl(CM_RGBC_OPCODE_FLOW_00); +} + +void CMRGBController::SetLedsDirect(RGBColor color_1, RGBColor color_2, RGBColor color_3, RGBColor color_4) +{ + SendFlowControl(CM_RGBC_OPCODE_FLOW_80); + + SendCustomColorStart(); + + SendSetCustomColors(color_1, color_2, color_3, color_4); + + SendSetMode(CM_RGBC_MODE_MULTIPLE); + + SendCustomColorStart(); + + SendSetConfig(CM_RGBC_MODE_MULTIPLE, 0x00, 0xFF, color_1, 0x000000, false); + + SendApply(); + + SendFlowControl(CM_RGBC_OPCODE_FLOW_00); +} + +std::string CMRGBController::GetDeviceName() +{ + return(device_name); +} + +std::string CMRGBController::GetSerial() +{ + return(serial); +} + +std::string CMRGBController::GetLocation() +{ + return("HID: " + location); +} + +unsigned char CMRGBController::GetMode() +{ + return(current_mode); +} + +unsigned char CMRGBController::GetSpeed() +{ + return(current_speed); +} + +unsigned char CMRGBController::GetBrightness() +{ + return(current_brightness); +} + +RGBColor CMRGBController::GetModeColor(int color_number) +{ + switch(color_number) + { + case 0: + return(current_mode_color_1); + + case 1: + return(current_mode_color_2); + + default: + return(ToRGBColor(0, 0, 0)); + } +} + +RGBColor CMRGBController::GetPortColor(int port_number) +{ + switch(port_number) + { + case 0: + return(current_port1_color); + + case 1: + return(current_port2_color); + + case 2: + return(current_port3_color); + + case 3: + return(current_port4_color); + + default: + return(ToRGBColor(0, 0, 0)); + } +} + +CMRGBController::~CMRGBController() +{ + if(dev) + { + hid_close(dev); + } +} diff --git a/Controllers/CoolerMasterController/CMRGBController.h b/Controllers/CoolerMasterController/CMRGBController.h new file mode 100644 index 00000000..4ea1a2ae --- /dev/null +++ b/Controllers/CoolerMasterController/CMRGBController.h @@ -0,0 +1,149 @@ +/*-------------------------------------------------------------------*\ +| CMRGBController.h | +| | +| Driver for Coolermaster RGB USB Controller | +| | +| Nic W (midgetspy) 13th Apr 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include +#include +#include "RGBController.h" + +#pragma once +#define CM_RGBC_NUM_LEDS 4 + +#define REPORT_ID_OFFSET 1 +#define CM_RGBC_PACKET_SIZE 64 + REPORT_ID_OFFSET //This needs to have one byte extra for the report ID thing +#define CM_RGBC_PACKET_OFFSET_OP 0x00 +#define CM_RGBC_PACKET_OFFSET_TYPE 0x01 +#define CM_RGBC_PACKET_OFFSET_MULTILAYER 0x02 +#define CM_RGBC_PACKET_OFFSET_MODE 0x04 +#define CM_RGBC_PACKET_OFFSET_SPEED 0x05 +#define CM_RGBC_PACKET_OFFSET_BRIGHTNESS 0x09 +#define CM_RGBC_PACKET_OFFSET_COLOR_1 0x0A +#define CM_RGBC_PACKET_OFFSET_COLOR_2 0x0D + +#define CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_1 0x04 +#define CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_2 0x07 +#define CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_3 0x0A +#define CM_RGBC_PACKET_OFFSET_MULTIPLE_COLOR_4 0x0D + +#define CM_RGBC_INTERRUPT_TIMEOUT 250 + +#define CM_RGBC_SPEED_NONE 0x05 +#define CM_RGBC_BRIGHTNESS_OFF 0x03 + +/*-------------------------------------------------*\ +| OP OPCODES | +\*-------------------------------------------------*/ +enum +{ + CM_RGBC_OPCODE_OP_FLOW_CONTROL = 0x41, + CM_RGBC_OPCODE_OP_UNKNOWN_50 = 0x50, + CM_RGBC_OPCODE_OP_WRITE = 0x51, + CM_RGBC_OPCODE_OP_READ = 0x52, +}; + +/*-------------------------------------------------*\ +| CONTROL FLOW OPCODES | +\*-------------------------------------------------*/ +enum +{ + CM_RGBC_OPCODE_FLOW_00 = 0x00, + CM_RGBC_OPCODE_FLOW_01 = 0x01, + CM_RGBC_OPCODE_FLOW_80 = 0x80, +}; + +/*-------------------------------------------------*\ +| OP TYPE OPCODES | +\*-------------------------------------------------*/ +enum +{ + CM_RGBC_OPCODE_TYPE_MODE = 0x28, + CM_RGBC_OPCODE_TYPE_CONFIG_SIMPLIFIED = 0x2B, + CM_RGBC_OPCODE_TYPE_CONFIG_FULL = 0x2C, + CM_RGBC_OPCODE_TYPE_UNKNOWN_30 = 0x30, + CM_RGBC_OPCODE_TYPE_UNKNOWN_55 = 0x55, + CM_RGBC_OPCODE_TYPE_LED_INFO = 0xA8, +}; + +/*-------------------------------------------------*\ +| MODES | +\*-------------------------------------------------*/ +enum +{ + CM_RGBC_MODE_STATIC = 0x00, + CM_RGBC_MODE_BREATHING = 0x01, + CM_RGBC_MODE_COLOR_CYCLE = 0x02, + CM_RGBC_MODE_STAR = 0x03, + CM_RGBC_MODE_MULTIPLE = 0x04, + CM_RGBC_MODE_MULTILAYER = 0xE0, + CM_RGBC_MODE_OFF = 0xFE, +}; + +/*-------------------------------------------------*\ +| SPEED | +\*-------------------------------------------------*/ +enum +{ + CM_RGBC_SPEED_BREATHING_SLOWEST = 0x3C, + CM_RGBC_SPEED_BREATHING_FASTEST = 0x26, + CM_RGBC_SPEED_COLOR_CYCLE_SLOWEST = 0x96, + CM_RGBC_SPEED_COLOR_CYCLE_FASTEST = 0x68, + CM_RGBC_SPEED_STAR_SLOWEST = 0x46, + CM_RGBC_SPEED_STAR_FASTEST = 0x32, +}; + +class CMRGBController +{ +public: + CMRGBController(hid_device* dev_handle, char* path); + ~CMRGBController(); + + std::string GetDeviceName(); + std::string GetSerial(); + std::string GetLocation(); + + unsigned char GetMode(); + unsigned char GetSpeed(); + unsigned char GetBrightness(); + RGBColor GetModeColor(int color_number); + RGBColor GetPortColor(int port_number); + + void SetMode(unsigned char mode, unsigned char speed, unsigned char brightness, RGBColor color_1, RGBColor color_2); + void SetLedsDirect(RGBColor color_1, RGBColor color_2, RGBColor color_3, RGBColor color_4); + + void ReadCurrentMode(); + void ReadModeConfig(unsigned char mode); + +private: + std::string device_name; + std::string serial; + std::string location; + hid_device* dev; + + unsigned char current_mode; + unsigned char current_speed; + unsigned char current_brightness; + RGBColor current_mode_color_1; + RGBColor current_mode_color_2; + RGBColor current_port1_color; + RGBColor current_port2_color; + RGBColor current_port3_color; + RGBColor current_port4_color; + + void SendFlowControl(unsigned char byte_flag); + void SendApply(); + void SendCustomColorStart(); + + void SendReadMode(); + void SendSetMode(unsigned char mode); + + void SendReadCustomColors(); + void SendSetCustomColors(RGBColor color_1, RGBColor color_2, RGBColor color_3, RGBColor color_4); + + void SendReadConfig(unsigned char mode); + void SendSetConfig(unsigned char mode, unsigned char speed, unsigned char brightness, RGBColor color_1, RGBColor color_2, bool simplified, bool multilayer); +}; diff --git a/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp b/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp index 714d909f..f6254400 100644 --- a/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp +++ b/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp @@ -2,12 +2,14 @@ #include "CMMP750Controller.h" #include "CMARGBcontroller.h" #include "CMSmallARGBController.h" +#include "CMRGBController.h" #include "CMR6000Controller.h" #include "CMMKController.h" #include "RGBController.h" #include "RGBController_CMMP750Controller.h" #include "RGBController_CMARGBController.h" #include "RGBController_CMSmallARGBController.h" +#include "RGBController_CMRGBController.h" #include "RGBController_CMR6000Controller.h" #include "RGBController_CMMKController.h" #include @@ -18,6 +20,7 @@ #define COOLERMASTER_MP750_MEDIUM_PID 0x0105 #define COOLERMASTER_ARGB_PID 0x1011 #define COOLERMASTER_SMALL_ARGB_PID 0x1000 +#define COOLERMASTER_RGB_PID 0x004F #define COOLERMASTER_RADEON_6000_PID 0x014D #define COOLERMASTER_MASTERKEYS_PRO_L_PID CMMK_USB_MASTERKEYS_MK750 #define COOLERMASTER_MASTERKEYS_PRO_L_WHITE_PID CMMK_USB_MASTERKEYS_PRO_L_WHITE @@ -73,6 +76,18 @@ void DetectCoolerMasterSmallARGB(hid_device_info* info, const std::string&) } } +void DetectCoolerMasterRGB(hid_device_info* info, const std::string&) +{ + hid_device* dev = hid_open_path(info->path); + if(dev) + { + CMRGBController* controller = new CMRGBController(dev, info->path); + RGBController_CMRGBController* rgb_controller = new RGBController_CMRGBController(controller); + // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + void DetectCoolerMasterGPU(hid_device_info* info, const std::string&) { hid_device* dev = hid_open_path(info->path); @@ -108,4 +123,5 @@ REGISTER_HID_DETECTOR_IPU("Cooler Master SK630", DetectCooler REGISTER_HID_DETECTOR_IPU("Cooler Master SK650", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_SK650_PID, 1, 0xFF00, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master ARGB", DetectCoolerMasterARGB, COOLERMASTER_VID, COOLERMASTER_ARGB_PID, 0, 0xFF00, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master Small ARGB", DetectCoolerMasterSmallARGB, COOLERMASTER_VID, COOLERMASTER_SMALL_ARGB_PID, 0, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master RGB", DetectCoolerMasterRGB, COOLERMASTER_VID, COOLERMASTER_RGB_PID, 0, 0xFF00, 1); REGISTER_HID_DETECTOR_I ("Cooler Master Radeon 6000 GPU", DetectCoolerMasterGPU, COOLERMASTER_VID, COOLERMASTER_RADEON_6000_PID, 1 ); diff --git a/Controllers/CoolerMasterController/RGBController_CMRGBController.cpp b/Controllers/CoolerMasterController/RGBController_CMRGBController.cpp new file mode 100644 index 00000000..faaea9a8 --- /dev/null +++ b/Controllers/CoolerMasterController/RGBController_CMRGBController.cpp @@ -0,0 +1,274 @@ +/*-------------------------------------------------------------------*\ +| RGBController_CMRGBController.cpp | +| | +| Driver for Coolermaster RGB USB Controller | +| | +| Nic W (midgetspy) 13th Apr 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include "RGBController_CMRGBController.h" + +/*-----------------------------------------------------------------------------------------------------------------------------------------*\ +| This controller has 4 ports, each for a 12v non-addressable LED item. | +| | +| It supports the following modes: | +| Static: All 4 ports a single color. Has brightness option. | +| Breathing: All ports a single color, fading in and out. Has brightness and speed option. | +| Star: Some weird effect using all 4 ports and a single color. Has brightness and speed option. | +| Color Cycle: All ports cycle through the rainbow in unison. Has brightness and speed option. | +| Off: All 4 ports off | +| | +| Plus some "special" modes: | +| Multilayer: Each of the 4 ports can have any of the modes above applied individually | +| Multiple Color/Customize: Each port can be set to its own static color | +| Mirage: A strobe effect that varies the LED pulse frequency which affects any of the above modes | +| | +| Note: | +| Multiple Color/Customize is equivalent to Multilayer + Static, but the device supports both separately | +| Static is equivalent to Multiple Color/Customize with the same color on each port, but the device supports both separately | +| | +| It can be controlled with 2 different pieces of software: MasterPlus+ or "RGB LED Controller". They appear to use different protocols. | +| | +| RGB LED Controller: | +| Sets changes temporarily and then applies them or cancels the changes separately | +| Supports all modes above | +| Has 3 brightness increments | +| Has two different colors for the Star effect (Star/Sky) | +| | +| MasterPlus+: | +| Sets changes permanently as soon as you change anything in the UI | +| Doesn't support Multilayer or Mirage | +| Has 5 brightness increments | +| Single color for Star | +\*-----------------------------------------------------------------------------------------------------------------------------------------*/ + +RGBController_CMRGBController::RGBController_CMRGBController(CMRGBController *cmrgb_ptr) +{ + cmrgb = cmrgb_ptr; + + name = "Cooler Master RGB Controller"; + vendor = "Cooler Master"; + type = DEVICE_TYPE_LEDSTRIP; + description = cmrgb->GetDeviceName(); + version = ""; + serial = cmrgb->GetSerial(); + location = cmrgb->GetLocation(); + + mode Static; + Static.name = "Static"; + Static.value = CM_RGBC_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(Static.colors_max); + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.brightness_min = 0x00; + Static.brightness_max = 0xFF; + Static.brightness = 0xFF; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = CM_RGBC_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(Breathing.colors_max); + Breathing.speed_min = CM_RGBC_SPEED_BREATHING_SLOWEST; + Breathing.speed_max = CM_RGBC_SPEED_BREATHING_FASTEST; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed = CM_RGBC_SPEED_BREATHING_SLOWEST; + Breathing.brightness_min = 0x00; + Breathing.brightness_max = 0xFF; + Breathing.brightness = 0xFF; + modes.push_back(Breathing); + + mode ColorCycle; + ColorCycle.name = "Spectrum Cycle"; + ColorCycle.value = CM_RGBC_MODE_COLOR_CYCLE; + ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR; + ColorCycle.speed_min = CM_RGBC_SPEED_COLOR_CYCLE_SLOWEST; + ColorCycle.speed_max = CM_RGBC_SPEED_COLOR_CYCLE_FASTEST; + ColorCycle.color_mode = MODE_COLORS_RANDOM; + ColorCycle.speed = CM_RGBC_SPEED_COLOR_CYCLE_SLOWEST; + ColorCycle.brightness_min = 0x00; + ColorCycle.brightness_max = 0xFF; + ColorCycle.brightness = 0xFF; + modes.push_back(ColorCycle); + + mode Star; + Star.name = "Star"; + Star.value = CM_RGBC_MODE_STAR; + Star.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Star.colors_min = 2; + Star.colors_max = 2; + Star.colors.resize(Star.colors_max); + Star.speed_min = CM_RGBC_SPEED_STAR_SLOWEST; + Star.speed_max = CM_RGBC_SPEED_STAR_FASTEST; + Star.color_mode = MODE_COLORS_MODE_SPECIFIC; + Star.speed = CM_RGBC_SPEED_STAR_SLOWEST; + Star.brightness_min = 0x00; + Star.brightness_max = 0xFF; + Star.brightness = 0xFF; + modes.push_back(Star); + + mode Multiple; + Multiple.name = "Custom"; + Multiple.value = CM_RGBC_MODE_MULTIPLE; + Multiple.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Multiple.colors_min = 1; + Multiple.colors_max = 1; + Multiple.colors.resize(Multiple.colors_max); + Multiple.color_mode = MODE_COLORS_PER_LED; + Multiple.speed = 0; + Multiple.brightness_min = 0x00; + Multiple.brightness_max = 0xFF; + Multiple.brightness = 0xFF; + modes.push_back(Multiple); + + mode Off; + Off.name = "Off"; + Off.value = CM_RGBC_MODE_OFF; + Off.color_mode = MODE_COLORS_NONE; + Off.flags = 0; + modes.push_back(Off); + + SetupZones(); + + ReadAllModeConfigsFromDevice(); +} + +RGBController_CMRGBController::~RGBController_CMRGBController() +{ + delete cmrgb; +} + +void RGBController_CMRGBController::ReadAllModeConfigsFromDevice() +{ + int device_mode = cmrgb->GetMode(); + + for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++) + { + if(device_mode == modes[mode_idx].value) + { + active_mode = mode_idx; + continue; + } + + if(!modes[mode_idx].flags) + { + continue; + } + + cmrgb->ReadModeConfig(modes[mode_idx].value); + LoadConfigFromDeviceController(mode_idx); + } + + /*---------------------------------------------------------*\ + | Do the active mode last so the device controller state | + | is left with the active mode's config | + \*---------------------------------------------------------*/ + if(active_mode != -1) + { + cmrgb->ReadModeConfig(modes[active_mode].value); + LoadConfigFromDeviceController(active_mode); + } +} + +void RGBController_CMRGBController::LoadConfigFromDeviceController(int mode_idx) +{ + for(std::size_t color_idx = 0; color_idx < modes[mode_idx].colors.size(); color_idx++) + { + modes[mode_idx].colors[0] = cmrgb->GetModeColor(color_idx); + } + + if(modes[mode_idx].flags & MODE_FLAG_HAS_PER_LED_COLOR) + { + for (std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + SetLED(led_idx, cmrgb->GetPortColor(led_idx)); + } + } + + if(modes[mode_idx].flags & MODE_FLAG_HAS_SPEED) + { + modes[mode_idx].speed = cmrgb->GetSpeed(); + } + + if(modes[mode_idx].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + modes[active_mode].brightness = cmrgb->GetBrightness(); + } +} + + +void RGBController_CMRGBController::SetupZones() +{ + leds.clear(); + zones.clear(); + colors.clear(); + + /*-----------------------------------------------------*\ + | One zone, 4 leds. This might not actually work with | + | the Multilayer mode, but we'll deal with that later | + \*-----------------------------------------------------*/ + zone* new_zone = new zone(); + new_zone->name = "Controller"; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->leds_min = 1; + new_zone->leds_max = 4; + new_zone->leds_count = 4; + new_zone->matrix_map = NULL; + + for(int i = 1; i <= CM_RGBC_NUM_LEDS; i++) + { + led* new_led = new led(); + new_led->name = "LED " + std::to_string(i); + leds.push_back(*new_led); + } + + zones.push_back(*new_zone); + SetupColors(); +} + +void RGBController_CMRGBController::ResizeZone(int /*zone*/, int /*new_size*/) +{ +} + +void RGBController_CMRGBController::DeviceUpdateLEDs() +{ + for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + UpdateZoneLEDs(zone_idx); + } +} + +void RGBController_CMRGBController::UpdateZoneLEDs(int zone) +{ + cmrgb->SetLedsDirect(zones[zone].colors[0], zones[zone].colors[1], zones[zone].colors[2], zones[zone].colors[3]); +} + +void RGBController_CMRGBController::UpdateSingleLED(int /*led*/) +{ +} + +void RGBController_CMRGBController::SetCustomMode() +{ + for(std::size_t mode_idx = 0; mode_idx < modes.size() ; mode_idx++) + { + if (modes[mode_idx].value == CM_RGBC_MODE_MULTIPLE) + { + active_mode = mode_idx; + break; + } + } +} + +void RGBController_CMRGBController::DeviceUpdateMode() +{ + RGBColor color_1 = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) ? modes[active_mode].colors[0] : 0; + RGBColor color_2 = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && modes[active_mode].colors.size() > 1) ? modes[active_mode].colors[1] : 0; + + cmrgb->SetMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, color_1, color_2); +} diff --git a/Controllers/CoolerMasterController/RGBController_CMRGBController.h b/Controllers/CoolerMasterController/RGBController_CMRGBController.h new file mode 100644 index 00000000..e7c368d3 --- /dev/null +++ b/Controllers/CoolerMasterController/RGBController_CMRGBController.h @@ -0,0 +1,35 @@ +/*-------------------------------------------------------------------*\ +| RGBController_CMRGBController.h | +| | +| Driver for Coolermaster RGB USB Controller | +| | +| Nic W (midgetspy) 13th Apr 2021 | +| | +\*-------------------------------------------------------------------*/ + +#pragma once +#include "RGBController.h" +#include "CMRGBController.h" +#include + +class RGBController_CMRGBController : public RGBController +{ +public: + RGBController_CMRGBController(CMRGBController* cmrgb_ptr); + ~RGBController_CMRGBController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void DeviceUpdateMode(); + +private: + CMRGBController* cmrgb; + void LoadConfigFromDeviceController(int device_mode); + void ReadAllModeConfigsFromDevice(); +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 02ee59a8..11c52c2b 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -208,11 +208,13 @@ HEADERS += Controllers/CoolerMasterController/CMMP750Controller.h \ Controllers/CoolerMasterController/CMSmallARGBController.h \ Controllers/CoolerMasterController/CMR6000Controller.h \ + Controllers/CoolerMasterController/CMRGBController.h \ Controllers/CoolerMasterController/CMMKController.h \ Controllers/CoolerMasterController/RGBController_CMARGBController.h \ Controllers/CoolerMasterController/RGBController_CMMP750Controller.h \ Controllers/CoolerMasterController/RGBController_CMSmallARGBController.h \ Controllers/CoolerMasterController/RGBController_CMR6000Controller.h \ + Controllers/CoolerMasterController/RGBController_CMRGBController.h \ Controllers/CoolerMasterController/RGBController_CMMKController.h \ Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h \ Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h \ @@ -511,12 +513,14 @@ SOURCES += Controllers/CoolerMasterController/CMMP750Controller.cpp \ Controllers/CoolerMasterController/CMSmallARGBController.cpp \ Controllers/CoolerMasterController/CMR6000Controller.cpp \ + Controllers/CoolerMasterController/CMRGBController.cpp \ Controllers/CoolerMasterController/CMMKController.cpp \ Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp \ Controllers/CoolerMasterController/RGBController_CMARGBController.cpp \ Controllers/CoolerMasterController/RGBController_CMMP750Controller.cpp \ Controllers/CoolerMasterController/RGBController_CMSmallARGBController.cpp \ Controllers/CoolerMasterController/RGBController_CMR6000Controller.cpp \ + Controllers/CoolerMasterController/RGBController_CMRGBController.cpp \ Controllers/CoolerMasterController/RGBController_CMMKController.cpp \ Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp \ Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp \