From b709e5ddccff628d3a9b3cffd7ec4ba75e01ec85 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 12 Oct 2020 23:41:30 +1100 Subject: [PATCH] Initial add for Coolermaster ARGB controller * Not yet functional Commit amended for code style and cherry-pick cleanup by Adam Honse --- .../CMARGBcontroller.cpp | 152 ++++++++++++++++++ .../CoolerMasterController/CMARGBcontroller.h | 119 ++++++++++++++ .../CoolerMasterControllerDetect.cpp | 27 +++- OpenRGB.pro | 2 + 4 files changed, 292 insertions(+), 8 deletions(-) create mode 100644 Controllers/CoolerMasterController/CMARGBcontroller.cpp create mode 100644 Controllers/CoolerMasterController/CMARGBcontroller.h diff --git a/Controllers/CoolerMasterController/CMARGBcontroller.cpp b/Controllers/CoolerMasterController/CMARGBcontroller.cpp new file mode 100644 index 00000000..4fa20844 --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBcontroller.cpp @@ -0,0 +1,152 @@ +/*-------------------------------------------------------------------*\ +| CMARGBController.cpp | +| | +| Driver for Coolermaster ARGB USB Controller | +| | +| Chris M (Dr_No) 10th Oct 2020 | +| | +\*-------------------------------------------------------------------*/ + +#include "CMARGBcontroller.h" + +static unsigned char argb_colour_index_data[2][2][2] = +{ //R0 R1 + { { 0x00, 0x01 }, //G0 B0 + { 0x02, 0x04 }, }, //G1 B0 + { { 0x03, 0x05 }, //G0 B1 + { 0x06, 0x07 }, } //G1 B1 +}; + +static unsigned char argb_mode_data[2][9] = +{ + { 0x05, 0x01, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x01 }, //12v RGB Mode values + { 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09 } //5v ARGB Mode values +}; + +CMARGBController::CMARGBController(hid_device* dev_handle, wchar_t *_vendor, wchar_t *_device_name, char *_path) +{ + std::size_t tmp_size = wcslen(_vendor); + dev = dev_handle; + location = _path; + + for(std::size_t i = 0; (i < tmp_size) && (i < CM_ARGB_DEVICE_NAME_SIZE); i++) + { + device_name[i] = (char)_vendor[i]; + } + for(std::size_t j = 0; (j < wcslen(_vendor)) && (tmp_size + j < CM_ARGB_DEVICE_NAME_SIZE); j++) + { + device_name[tmp_size + j] = (char)_device_name[j]; + } +} + +CMARGBController::~CMARGBController() +{ + hid_close(dev); +} + +char* CMARGBController::GetDeviceName() +{ + return device_name; +} + +char* CMARGBController::GetSerial() +{ + return serial; +} + +std::string CMARGBController::GetLocation() +{ + return location; +} + +unsigned char CMARGBController::GetMode() +{ + return current_mode; +} + +unsigned char CMARGBController::GetLedRed() +{ + return current_red; +} + +unsigned char CMARGBController::GetLedGreen() +{ + return current_green; +} + +unsigned char CMARGBController::GetLedBlue() +{ + return current_blue; +} + +unsigned char CMARGBController::GetLedSpeed() +{ + return current_speed; +} + +unsigned char CMARGBController::GetLargestColour(unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char largest; + if ( red > green ) + { + ( red > blue ) ? largest = red : largest = blue; + } + else + { + ( green > blue ) ? largest = green : largest = blue; + } + + return largest; +} + +unsigned char CMARGBController::GetColourIndex(unsigned char red, unsigned char green, unsigned char blue) +{ + //The Coolermaster ARGB controller uses a limited colour pallette referenced by an index + //Starting at 0x00 Random, 0x01 Red, 0x02 Green, 0x03 Blue, 0x04 Yellow, 0x05 Purple, 0x06 Cyan, 0x07 White + //The index can be calculated by normalising the input colour, rounding those values + //and using them as the indicies of a 3d array containing the correct index + unsigned char divisor = GetLargestColour( red, green, blue); + unsigned int r = round( red / divisor )+1; + unsigned int g = round( green / divisor )+1; + unsigned int b = round( blue / divisor )+1; + return argb_colour_index_data[r][g][b]; +} + +void CMARGBController::SetMode(unsigned char mode, unsigned char speed) +{ + current_mode = mode; + current_speed = speed; + + SendUpdate(); +} + +void CMARGBController::SetColor(unsigned char red, unsigned char green, unsigned char blue) +{ + current_red = red; + current_green = green; + current_blue = blue; + + SendUpdate(); +} + +void CMARGBController::SendUpdate(unsigned char zone) +{ + unsigned char buffer[0x40] = { 0x00 }; + int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); + bool boolARGB_header = true; + buffer[CM_ARGB_REPORT_BYTE] = 0x80; + buffer[CM_ARGB_COMMAND_BYTE] = 0x01; + buffer[CM_ARGB_MODE_BYTE] = 0x01; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT ); + + buffer[CM_ARGB_COMMAND_BYTE] = (boolARGB_header) ? 0x0b : 0x04; //ARGB sends 0x0b (1011) RGB sends 0x04 (0100) + buffer[CM_ARGB_MODE_BYTE] = current_mode; + buffer[CM_ARGB_ZONE_BYTE] = zone; + buffer[CM_ARGB_COLOUR_INDEX_BYTE] = GetColourIndex( current_red, current_green, current_blue ); + buffer[CM_ARGB_SPEED_BYTE] = current_speed; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT ); +} diff --git a/Controllers/CoolerMasterController/CMARGBcontroller.h b/Controllers/CoolerMasterController/CMARGBcontroller.h new file mode 100644 index 00000000..bfd51f53 --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBcontroller.h @@ -0,0 +1,119 @@ +/*-------------------------------------------------------------------*\ +| CMARGBController.h | +| | +| Driver for Coolermaster ARGB USB Controller | +| | +| Chris M (Dr_No) 10th Oct 2020 | +| | +| Simple RGB device with 5 modes | +| BYTE0 = Mode (0x01 thru 0x05 | +| BYTE1 = ?? Must be set to 0x04 for colour modes otherwise ignored | +| BYTE2 = Colour Modes: RED else Cycle SPEED | +| BYTE3 = Colour Modes: GREEN else ignored | +| BYTE4 = Colour Modes: BLUE else ignored | +| BYTE5 = Colour Modes: SPEED else ignored | +\*-------------------------------------------------------------------*/ + +#include +#include +#include //Needed by round() +#include + +#pragma once + +#define CM_ARGB_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) +#define CM_ARGB_INTERRUPT_TIMEOUT 250 +#define CM_ARGB_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) +#define CM_ARGB_SERIAL_SIZE (sizeof(serial) / sizeof(serial[ 0 ])) +#define HID_MAX_STR 255 + +enum +{ + CM_ARGB_REPORT_BYTE = 0, + CM_ARGB_COMMAND_BYTE = 1, + CM_ARGB_MODE_BYTE = 2, + CM_ARGB_ZONE_BYTE = 3, + CM_ARGB_COLOUR_INDEX_BYTE = 5, + CM_ARGB_SPEED_BYTE = 6 +}; + +// ARGB Modes +/* + * 01 Spectrum (random) + * 02 Reload + * 03 Recoil + * 04 Breathing + * 05 Refill + * 06 Demo Mode (random) + * 08 Fill Flow (random) + * 09 Rainbow (random) + * 0a Turn Off + */ + +// RGB Modes +/* + * 01 Colour Cycle + * 02 Flash + * 03 Breathing + * 04 Motherboard (Pass Thru) + * 05 Turn Off + */ + +enum +{ + CM_ARGB_MODE_OFF = 1, //Turn off + CM_ARGB_MODE_SPECTRUM = 2, //Spectrum Mode + CM_ARGB_MODE_RELOAD = 3, //Reload Mode + CM_ARGB_MODE_RECOIL = 4, //Recoil Mode + CM_ARGB_MODE_BREATHING = 5, //Breathing Mode + CM_ARGB_MODE_REFILL = 6, //Refill Mode + CM_ARGB_MODE_DEMO = 7, //Demo Mode + CM_ARGB_MODE_FILLFLOW = 8, //Fill Flow Mode + CM_ARGB_MODE_RAINBOW = 9 //Rainbow Mode +}; + +enum +{ + CM_ARGB_SPEED_SLOWEST = 0x00, // Slowest speed + CM_ARGB_SPEED_SLOW = 0x01, // Slower speed + CM_ARGB_SPEED_NORMAL = 0x02, // Normal speed + CM_ARGB_SPEED_FAST = 0x03, // Fast speed + CM_ARGB_SPEED_FASTEST = 0x04, // Fastest speed +}; + +class CMARGBController +{ +public: + CMARGBController(hid_device* dev_handle, wchar_t *_vendor, wchar_t *_device_name, char *_path); + ~CMARGBController(); + + char* GetDeviceName(); + char* GetSerial(); + std::string GetLocation(); + + unsigned char GetMode(); + unsigned char GetLedRed(); + unsigned char GetLedGreen(); + unsigned char GetLedBlue(); + unsigned char GetLedSpeed(); + void SetMode(unsigned char mode, unsigned char speed); + void SetColor(unsigned char red, unsigned char green, unsigned char blue); + +private: + char device_name[32]; + char serial[32]; + std::string location; + hid_device* dev; + + unsigned char current_mode; + unsigned char current_speed; + + unsigned char current_red; + unsigned char current_green; + unsigned char current_blue; + + unsigned char GetLargestColour(unsigned char red, unsigned char green, unsigned char blue); + unsigned char GetColourIndex(unsigned char red, unsigned char green, unsigned char blue); + void GetStatus(); + void SendUpdate(unsigned char zone); +}; diff --git a/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp b/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp index 936eb218..be03062f 100644 --- a/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp +++ b/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp @@ -1,5 +1,6 @@ #include "Detector.h" #include "CMMP750Controller.h" +#include "CMARGBcontroller.h" #include "RGBController.h" #include "RGBController_CMMP750Controller.h" #include @@ -8,19 +9,21 @@ #define COOLERMASTER_MP750_XL_PID 0x0109 #define COOLERMASTER_MP750_MEDIUM_PID 0x0105 +#define COOLERMASTER_ARGB_PID 0x1011 #define COOLERMASTER_NUM_DEVICES (sizeof(cm_pids) / sizeof(cm_pids[ 0 ])) enum { - CM_PID = 0, - CM_INTERFACE = 1 + CM_PID = 0, + CM_INTERFACE = 1 }; static const unsigned int cm_pids[][4] = -{ // PID, Interface - { COOLERMASTER_MP750_XL_PID, 0x00 }, //Coolermaster MP750 (Extra Large) - { COOLERMASTER_MP750_MEDIUM_PID, 0x00 } //Coolermaster MP750 (Medium) +{ // PID, Interface Type + { COOLERMASTER_MP750_XL_PID, 0x00, DEVICE_TYPE_MOUSEMAT }, //Coolermaster MP750 (Extra Large) + { COOLERMASTER_MP750_MEDIUM_PID, 0x00, DEVICE_TYPE_MOUSEMAT }, //Coolermaster MP750 (Medium) + { COOLERMASTER_ARGB_PID, 0x01, DEVICE_TYPE_LEDSTRIP } //Coolermaster ARGB Controller }; /******************************************************************************************\ @@ -57,13 +60,21 @@ void DetectCoolerMasterControllers(std::vector& rgb_controllers) if(dev) { - CMMP750Controller* controller = new CMMP750Controller(dev, info->manufacturer_string, info->product_string, info->path); - RGBController_CMMP750Controller* rgb_controller = new RGBController_CMMP750Controller(controller); - rgb_controllers.push_back(rgb_controller); + if (dev_type == DEVICE_TYPE_MOUSEMAT) + { + CMMP750Controller* controller = new CMMP750Controller(dev, info->manufacturer_string, info->product_string, info->path); + RGBController_CMMP750Controller* rgb_controller = new RGBController_CMMP750Controller(controller); + rgb_controllers.push_back(rgb_controller); + } + else if(dev_type == DEVICE_TYPE_LEDSTRIP) + { + //Add controllers here + } } info = info->next; } hid_free_enumeration(info); + } /* DetectCoolerMasterControllers() */ REGISTER_DETECTOR("Cooler Master", DetectCoolerMasterControllers); diff --git a/OpenRGB.pro b/OpenRGB.pro index 07ae9d19..a9338c83 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -149,6 +149,7 @@ HEADERS += Controllers/AuraGPUController/RGBController_AuraGPU.h \ Controllers/AuraSMBusController/AuraSMBusController.h \ Controllers/AuraSMBusController/RGBController_AuraSMBus.h \ + Controllers/CoolerMasterController/CMARGBcontroller.h \ Controllers/CoolerMasterController/CMMP750Controller.h \ Controllers/CoolerMasterController/RGBController_CMMP750Controller.h \ Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h \ @@ -317,6 +318,7 @@ SOURCES += Controllers/AuraSMBusController/AuraSMBusController.cpp \ Controllers/AuraSMBusController/AuraSMBusControllerDetect.cpp \ Controllers/AuraSMBusController/RGBController_AuraSMBus.cpp \ + Controllers/CoolerMasterController/CMARGBcontroller.cpp \ Controllers/CoolerMasterController/CMMP750Controller.cpp \ Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp \ Controllers/CoolerMasterController/RGBController_CMMP750Controller.cpp \