mirror of
https://github.com/CalcProgrammer1/OpenRGB.git
synced 2025-12-26 08:47:50 -05:00
Commits squashed and amended for code style/brightness control by Adam Honse <calcprogrammer1@gmail.com>
368 lines
13 KiB
C++
368 lines
13 KiB
C++
/*-------------------------------------------------------------------*\
|
|
| CMRGBController.cpp |
|
|
| |
|
|
| Driver for Coolermaster RGB USB Controller |
|
|
| |
|
|
| Nic W (midgetspy) 13th Apr 2021 |
|
|
| |
|
|
\*-------------------------------------------------------------------*/
|
|
|
|
#include "RGBController_CMRGBController.h"
|
|
#include "CMRGBController.h"
|
|
#include <cstring>
|
|
|
|
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);
|
|
}
|
|
}
|