Publish curated LumaOps source from c85ee9ef8f1454f5c305398902afbb9e6738de40
Managed validation / full (push) Failing after 8s

This commit is contained in:
Public Source Publisher committed 2026-09-30 00:26:45 +00:00
1 parent 91f8b3e3c1
commit def7920856
2271 files changed
+501225 -501178

No files matched your search

@@ -1,197 +1,197 @@
/*---------------------------------------------------------*\
| CMKeyboardAbstractController.cpp |
| |
| Driver for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "CMKeyboardAbstractController.h"
#include "StringUtils.h"
CMKeyboardAbstractController::CMKeyboardAbstractController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name)
{
wchar_t tmp[HID_MAX_STR];
m_pDev = dev_handle;
m_productId = dev_info->product_id;
m_sLocation = dev_info->path;
m_deviceName = dev_name;
hid_get_manufacturer_string(m_pDev, tmp, HID_MAX_STR);
m_vendorName = StringUtils::wstring_to_string(tmp);
hid_get_product_string(m_pDev, tmp, HID_MAX_STR);
m_serialNumber = StringUtils::wstring_to_string(tmp);
bool bNotFound = true;
for(uint16_t i = 0; i < COOLERMASTER_KEYBOARD_DEVICE_COUNT; i++)
{
if(cm_kb_device_list[i]->product_id == m_productId)
{
bNotFound = false;
m_deviceIndex = i;
break;
}
}
if(bNotFound)
{
LOG_ERROR("[%s] device capabilities not found. Please creata a new device request.", m_deviceName.c_str());
}
};
CMKeyboardAbstractController::~CMKeyboardAbstractController()
{
hid_close(m_pDev);
};
std::string CMKeyboardAbstractController::GetDeviceName()
{
return(m_deviceName);
}
std::string CMKeyboardAbstractController::GetDeviceVendor()
{
return(m_vendorName);
}
std::string CMKeyboardAbstractController::GetDeviceSerial()
{
return(m_serialNumber);
}
const cm_kb_device* CMKeyboardAbstractController::GetDeviceData()
{
return(cm_kb_device_list[m_deviceIndex]);
}
std::string CMKeyboardAbstractController::GetLocation()
{
return(m_sLocation);
}
std::string CMKeyboardAbstractController::GetFirmwareVersion()
{
return(m_sFirmwareVersion);
}
int CMKeyboardAbstractController::GetProductID()
{
return(m_productId);
}
std::vector<uint8_t> CMKeyboardAbstractController::SendCommand(std::vector<uint8_t> buf, uint8_t fill)
{
int status;
std::vector<uint8_t> read;
uint8_t data[CM_KEYBOARD_WRITE_SIZE];
memset(data, fill, CM_KEYBOARD_WRITE_SIZE);
size_t i = 1;
for(uint8_t b : buf)
{
data[i++] = b;
}
std::lock_guard<std::mutex> guard(m_mutexSendCommand);
status = hid_write(m_pDev, data, CM_KEYBOARD_WRITE_SIZE);
if(status < 0)
{
LOG_ERROR("[%s] SendCommand() failed code %d.", m_deviceName.c_str(), status);
return(read);
}
memset(data, 0, CM_KEYBOARD_WRITE_SIZE);
status = hid_read(m_pDev, data, CM_KEYBOARD_WRITE_SIZE);
if(status < 0)
{
LOG_ERROR("[%s] SendCommand() failed code %d.", m_deviceName.c_str(), status);
return(read);
}
for(i = 0; i < (size_t)status; i++)
{
read.push_back(data[i]);
}
return(read);
}
/*---------------------------------------------------------*\
| Enter/leave direct control mode |
\*---------------------------------------------------------*/
void CMKeyboardAbstractController::SetControlMode(uint8_t modeId)
{
SendCommand({0x41, (uint8_t)modeId});
};
/*---------------------------------------------------------*\
| Sets the currently active profile. |
| byte[0] = 0x51 0x00 0x00 0x00 |
| byte[4] = profileId |
| - corresponds to saved keyboard profile i.e. [1-4] |
| - 0x05 - Used on MK and CK style keyboards? |
\*---------------------------------------------------------*/
void CMKeyboardAbstractController::SetActiveProfile(uint8_t profileId)
{
SendCommand({0x51, 0x00, 0x00, 0x00, profileId});
};
uint8_t CMKeyboardAbstractController::GetActiveProfile()
{
std::vector<uint8_t> data = SendCommand({0x52, 0x00});
if(data.size() > 4)
{
return((int)data[4]);
}
return(0xFF); // error
}
/*---------------------------------------------------------*\
| Saves changes in currently used profile. |
| byte[1] = 0x52 |
\*---------------------------------------------------------*/
void CMKeyboardAbstractController::SaveActiveProfile()
{
SendCommand({0x50, 0x55});
}
void CMKeyboardAbstractController::SetActiveEffect(uint8_t effectId)
{
SendCommand({0x51, 0x28, 0x00, 0x00, effectId});
};
void CMKeyboardAbstractController::SaveProfile()
{
SendCommand({0x50, 0x55});
}
uint8_t CMKeyboardAbstractController::GetModeStatus()
{
std::vector<uint8_t> data = SendCommand({0x52, 0x28});
return(data[4]);
};
std::string CMKeyboardAbstractController::GetHexString(std::vector<uint8_t> buf)
{
std::stringstream hexss;
for(uint8_t b : buf)
{
hexss << std::hex << b << " ";
}
return(hexss.str());
}
/*---------------------------------------------------------*\
| CMKeyboardAbstractController.cpp |
| |
| Driver for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "CMKeyboardAbstractController.h"
#include "StringUtils.h"
CMKeyboardAbstractController::CMKeyboardAbstractController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name)
{
wchar_t tmp[HID_MAX_STR];
m_pDev = dev_handle;
m_productId = dev_info->product_id;
m_sLocation = dev_info->path;
m_deviceName = dev_name;
hid_get_manufacturer_string(m_pDev, tmp, HID_MAX_STR);
m_vendorName = StringUtils::wstring_to_string(tmp);
hid_get_product_string(m_pDev, tmp, HID_MAX_STR);
m_serialNumber = StringUtils::wstring_to_string(tmp);
bool bNotFound = true;
for(uint16_t i = 0; i < COOLERMASTER_KEYBOARD_DEVICE_COUNT; i++)
{
if(cm_kb_device_list[i]->product_id == m_productId)
{
bNotFound = false;
m_deviceIndex = i;
break;
}
}
if(bNotFound)
{
LOG_ERROR("[%s] device capabilities not found. Please creata a new device request.", m_deviceName.c_str());
}
};
CMKeyboardAbstractController::~CMKeyboardAbstractController()
{
hid_close(m_pDev);
};
std::string CMKeyboardAbstractController::GetDeviceName()
{
return(m_deviceName);
}
std::string CMKeyboardAbstractController::GetDeviceVendor()
{
return(m_vendorName);
}
std::string CMKeyboardAbstractController::GetDeviceSerial()
{
return(m_serialNumber);
}
const cm_kb_device* CMKeyboardAbstractController::GetDeviceData()
{
return(cm_kb_device_list[m_deviceIndex]);
}
std::string CMKeyboardAbstractController::GetLocation()
{
return(m_sLocation);
}
std::string CMKeyboardAbstractController::GetFirmwareVersion()
{
return(m_sFirmwareVersion);
}
int CMKeyboardAbstractController::GetProductID()
{
return(m_productId);
}
std::vector<uint8_t> CMKeyboardAbstractController::SendCommand(std::vector<uint8_t> buf, uint8_t fill)
{
int status;
std::vector<uint8_t> read;
uint8_t data[CM_KEYBOARD_WRITE_SIZE];
memset(data, fill, CM_KEYBOARD_WRITE_SIZE);
size_t i = 1;
for(uint8_t b : buf)
{
data[i++] = b;
}
std::lock_guard<std::mutex> guard(m_mutexSendCommand);
status = hid_write(m_pDev, data, CM_KEYBOARD_WRITE_SIZE);
if(status < 0)
{
LOG_ERROR("[%s] SendCommand() failed code %d.", m_deviceName.c_str(), status);
return(read);
}
memset(data, 0, CM_KEYBOARD_WRITE_SIZE);
status = hid_read(m_pDev, data, CM_KEYBOARD_WRITE_SIZE);
if(status < 0)
{
LOG_ERROR("[%s] SendCommand() failed code %d.", m_deviceName.c_str(), status);
return(read);
}
for(i = 0; i < (size_t)status; i++)
{
read.push_back(data[i]);
}
return(read);
}
/*---------------------------------------------------------*\
| Enter/leave direct control mode |
\*---------------------------------------------------------*/
void CMKeyboardAbstractController::SetControlMode(uint8_t modeId)
{
SendCommand({0x41, (uint8_t)modeId});
};
/*---------------------------------------------------------*\
| Sets the currently active profile. |
| byte[0] = 0x51 0x00 0x00 0x00 |
| byte[4] = profileId |
| - corresponds to saved keyboard profile i.e. [1-4] |
| - 0x05 - Used on MK and CK style keyboards? |
\*---------------------------------------------------------*/
void CMKeyboardAbstractController::SetActiveProfile(uint8_t profileId)
{
SendCommand({0x51, 0x00, 0x00, 0x00, profileId});
};
uint8_t CMKeyboardAbstractController::GetActiveProfile()
{
std::vector<uint8_t> data = SendCommand({0x52, 0x00});
if(data.size() > 4)
{
return((int)data[4]);
}
return(0xFF); // error
}
/*---------------------------------------------------------*\
| Saves changes in currently used profile. |
| byte[1] = 0x52 |
\*---------------------------------------------------------*/
void CMKeyboardAbstractController::SaveActiveProfile()
{
SendCommand({0x50, 0x55});
}
void CMKeyboardAbstractController::SetActiveEffect(uint8_t effectId)
{
SendCommand({0x51, 0x28, 0x00, 0x00, effectId});
};
void CMKeyboardAbstractController::SaveProfile()
{
SendCommand({0x50, 0x55});
}
uint8_t CMKeyboardAbstractController::GetModeStatus()
{
std::vector<uint8_t> data = SendCommand({0x52, 0x28});
return(data[4]);
};
std::string CMKeyboardAbstractController::GetHexString(std::vector<uint8_t> buf)
{
std::stringstream hexss;
for(uint8_t b : buf)
{
hexss << std::hex << b << " ";
}
return(hexss.str());
}
@@ -1,120 +1,120 @@
/*---------------------------------------------------------*\
| CMKeyboardAbstractController.h |
| |
| Driver for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <stdint.h>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <hidapi.h>
#include "CMKeyboardDevices.h"
#include "KeyboardLayoutManager.h"
#include "RGBController.h"
#include "LogManager.h"
#define HID_MAX_STR 255
#define CM_KEYBOARD_WRITE_SIZE 65
#define CM_MAX_LEDS 255
#define CM_KEYBOARD_TIMEOUT 50
#define CM_KEYBOARD_TIMEOUT_SHORT 3
struct cm_keyboard_effect
{
uint8_t effectId;
uint8_t p1;
uint8_t p2;
uint8_t p3;
RGBColor color1;
RGBColor color2;
};
/*---------------------------------------------------------*\
| byte[0] = 0x41 |
| byte[1] = modeId |
\*---------------------------------------------------------*/
enum cm_keyboard_control_mode
{
MODE_FIRMWARE = 0x00,
MODE_EFFECT = 0x01,
MODE_MANUAL_V2 = 0x02,
MODE_CUSTOM_PROFILE = 0x03,
MODE_CUSTOM_PROFILE_V2 = 0x05,
MODE_DIRECT = 0x80
};
class CMKeyboardAbstractController
{
public:
CMKeyboardAbstractController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
virtual ~CMKeyboardAbstractController();
/*---------------------------------------------------------*\
| Common USB controller fuctions |
\*---------------------------------------------------------*/
int GetProductID();
std::string GetDeviceName();
std::string GetDeviceVendor();
std::string GetDeviceSerial();
std::string GetLocation();
std::string GetFirmwareVersion();
const cm_kb_device* GetDeviceData();
/*---------------------------------------------------------*\
| Keyboard Layout Manager support funtions |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| Common keyboard driver functions |
\*---------------------------------------------------------*/
virtual void SetControlMode(uint8_t modeId);
virtual void SetActiveProfile(uint8_t profileId);
virtual uint8_t GetActiveProfile();
virtual void SaveActiveProfile();
virtual void SaveProfile();
virtual void SetActiveEffect(uint8_t effectId);
virtual uint8_t GetModeStatus();
virtual void InitializeModes(std::vector<mode> &modes) = 0;
virtual KEYBOARD_LAYOUT GetKeyboardLayout() = 0;
/*---------------------------------------------------------*\
| Protocol specific funtions to be implmented |
\*---------------------------------------------------------*/
virtual void SetLeds(std::vector<led> leds, std::vector<RGBColor> colors) = 0;
virtual void SetSingleLED(uint8_t in_led, RGBColor in_color) = 0;
virtual void Initialize() = 0;
virtual void Shutdown() = 0;
virtual void SetLEDControl(bool bManual) = 0; // FW or SW control
virtual void SetCustomMode() = 0;
virtual void SetMode(mode selectedMode) = 0;
protected:
/*---------------------------------------------------------*\
| Utility functions. |
\*---------------------------------------------------------*/
std::vector<std::uint8_t> SendCommand(std::vector<uint8_t> buf, uint8_t fill=0x00);
std::string GetHexString(std::vector<uint8_t> buf);
std::string m_sFirmwareVersion;
std::string m_deviceName;
hid_device* m_pDev;
uint16_t m_productId;
uint16_t m_deviceIndex;
std::string m_vendorName;
std::string m_sLocation;
std::string m_serialNumber;
KEYBOARD_LAYOUT m_keyboardLayout;
std::map<int, int> mapModeValueEffect;
std::mutex m_mutex;
std::mutex m_mutexSendCommand;
};
/*---------------------------------------------------------*\
| CMKeyboardAbstractController.h |
| |
| Driver for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <stdint.h>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <hidapi.h>
#include "CMKeyboardDevices.h"
#include "KeyboardLayoutManager.h"
#include "RGBController.h"
#include "LogManager.h"
#define HID_MAX_STR 255
#define CM_KEYBOARD_WRITE_SIZE 65
#define CM_MAX_LEDS 255
#define CM_KEYBOARD_TIMEOUT 50
#define CM_KEYBOARD_TIMEOUT_SHORT 3
struct cm_keyboard_effect
{
uint8_t effectId;
uint8_t p1;
uint8_t p2;
uint8_t p3;
RGBColor color1;
RGBColor color2;
};
/*---------------------------------------------------------*\
| byte[0] = 0x41 |
| byte[1] = modeId |
\*---------------------------------------------------------*/
enum cm_keyboard_control_mode
{
MODE_FIRMWARE = 0x00,
MODE_EFFECT = 0x01,
MODE_MANUAL_V2 = 0x02,
MODE_CUSTOM_PROFILE = 0x03,
MODE_CUSTOM_PROFILE_V2 = 0x05,
MODE_DIRECT = 0x80
};
class CMKeyboardAbstractController
{
public:
CMKeyboardAbstractController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
virtual ~CMKeyboardAbstractController();
/*---------------------------------------------------------*\
| Common USB controller fuctions |
\*---------------------------------------------------------*/
int GetProductID();
std::string GetDeviceName();
std::string GetDeviceVendor();
std::string GetDeviceSerial();
std::string GetLocation();
std::string GetFirmwareVersion();
const cm_kb_device* GetDeviceData();
/*---------------------------------------------------------*\
| Keyboard Layout Manager support funtions |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| Common keyboard driver functions |
\*---------------------------------------------------------*/
virtual void SetControlMode(uint8_t modeId);
virtual void SetActiveProfile(uint8_t profileId);
virtual uint8_t GetActiveProfile();
virtual void SaveActiveProfile();
virtual void SaveProfile();
virtual void SetActiveEffect(uint8_t effectId);
virtual uint8_t GetModeStatus();
virtual void InitializeModes(std::vector<mode> &modes) = 0;
virtual KEYBOARD_LAYOUT GetKeyboardLayout() = 0;
/*---------------------------------------------------------*\
| Protocol specific funtions to be implmented |
\*---------------------------------------------------------*/
virtual void SetLeds(std::vector<led> leds, std::vector<RGBColor> colors) = 0;
virtual void SetSingleLED(uint8_t in_led, RGBColor in_color) = 0;
virtual void Initialize() = 0;
virtual void Shutdown() = 0;
virtual void SetLEDControl(bool bManual) = 0; // FW or SW control
virtual void SetCustomMode() = 0;
virtual void SetMode(mode selectedMode) = 0;
protected:
/*---------------------------------------------------------*\
| Utility functions. |
\*---------------------------------------------------------*/
std::vector<std::uint8_t> SendCommand(std::vector<uint8_t> buf, uint8_t fill=0x00);
std::string GetHexString(std::vector<uint8_t> buf);
std::string m_sFirmwareVersion;
std::string m_deviceName;
hid_device* m_pDev;
uint16_t m_productId;
uint16_t m_deviceIndex;
std::string m_vendorName;
std::string m_sLocation;
std::string m_serialNumber;
KEYBOARD_LAYOUT m_keyboardLayout;
std::map<int, int> mapModeValueEffect;
std::mutex m_mutex;
std::mutex m_mutexSendCommand;
};
File diff suppressed because it is too large. Load diff
@@ -1,123 +1,123 @@
/*---------------------------------------------------------*\
| CMKeyboardDevices.h |
| |
| Device list for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "KeyboardLayoutManager.h"
/*-----------------------------------------------------*\
| List of all supported effects by this controller. |
| All of these effects are firmware controlled, and |
| they types of effects supported will depend on the |
| Keyboard. |
| |
| To enable a command, the SetEffect(effectId) needs |
| to be called. The specific effectId->Effect mapping |
| depends on the keyboard. |
\*-----------------------------------------------------*/
enum cm_keyboard_effect_type
{
NONE = 0,
DIRECT,
SINGLE,
FULLY_LIT,
STATIC,
BREATHE,
CYCLE,
WAVE,
RIPPLE,
CROSS,
RAINDROPS,
STARS,
SNAKE,
CUSTOMIZED,
INDICATOR,
MULTILAYER,
REACTIVE_FADE,
REACTIVE_PUNCH,
REACTIVE_TORNADO,
HEARTBEAT,
FIREBALL,
SNOW,
CIRCLE_SPECTRUM,
WATER_RIPPLE,
OFF
};
#define CM_KB_ZONES_MAX 1
typedef struct
{
std::string name;
zone_type type;
} cm_kb_zone;
typedef struct
{
uint16_t product_id;
const cm_kb_zone * zones[CM_KB_ZONES_MAX];
keyboard_keymap_overlay_values* layout_new;
} cm_kb_device;
#define COOLERMASTER_VID 0x2516
#define CMKB_MAXKEYS 256
/*-----------------------------------------------------------------*\
| keyboard support status is indicated to the right of |
| the PID definition. Attribution to products is also |
| indicated. |
| |
| libcmmk |
| signal https://gitlab.com/signalrgb/signal-plugins |
| openrgb |
| ck550-macos https://github.com/vookimedlo/ck550-macos/tree/master |
| reversed |
| |
| issue tickets, open merge requests etc are provided |
| for developer references. |
| # denotes issue ticket |
| ! denotes merge/pull request |
\*-----------------------------------------------------------------*/
#define COOLERMASTER_KEYBOARD_CK351_PID 0x014F // unsupported
#define COOLERMASTER_KEYBOARD_CK530_PID 0x009F // [ck550-macos]
#define COOLERMASTER_KEYBOARD_CK530_V2_PID 0x0147 // [signal]
#define COOLERMASTER_KEYBOARD_CK550_V2_PID 0x0145 // [openrgb #800, #2863, signal]
#define COOLERMASTER_KEYBOARD_CK552_V2_PID 0x007F // [ck550-macos, signal]
#define COOLERMASTER_KEYBOARD_CK570_V2_PID 0x01E8 // unsupported
#define COOLERMASTER_KEYBOARD_CK720_PID 0x016B // unsupported
#define COOLERMASTER_KEYBOARD_CK721_PID 0x016D // unsupported
#define COOLERMASTER_KEYBOARD_CK721LINE_PID 0x01EE // unsupported
#define COOLERMASTER_KEYBOARD_PRO_L_PID 0x003B // [libcmmk !16]
#define COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID 0x0047 // [libcmmk]
#define COOLERMASTER_KEYBOARD_PRO_S_PID 0x003C // [libcmmk #30 !31 !36, !37, !7, #5(closed), #3(closed)]
// MASTERKEYS PRO M [libcmmk #17]
#define COOLERMASTER_KEYBOARD_MK721_PID 0x016F // unsupported
#define COOLERMASTER_KEYBOARD_MK730_PID 0x008F // [openrgb #1630, libcmmk]
#define COOLERMASTER_KEYBOARD_MK750_PID 0x0067 // fw1.2 [libcmmk #25 !9, !14, signal]
#define COOLERMASTER_KEYBOARD_MK770_PID 0x01D5 // unsupported
#define COOLERMASTER_KEYBOARD_MK850_PID 0x0069 // [signal]
#define COOLERMASTER_KEYBOARD_SK620B_PID 0x0157 // [openrgb #4292]
#define COOLERMASTER_KEYBOARD_SK620W_PID 0x0159 // [openrgb #4292, signal]
#define COOLERMASTER_KEYBOARD_SK622B_PID 0x0149 // [openrgb #3110, signal #217(closed)]
#define COOLERMASTER_KEYBOARD_SK622W_PID 0x014B // [signal]
#define COOLERMASTER_KEYBOARD_SK630_PID 0x0089 // [openrgb #967, libcmmk !21]
#define COOLERMASTER_KEYBOARD_SK631B_PID 0x008B // unsupported
#define COOLERMASTER_KEYBOARD_SK631W_PID 0x0125 // [libcmmk]
#define COOLERMASTER_KEYBOARD_SK650_PID 0x008D // [openrgb #613, libcmmk #23 !37 !27 !28, signal]
#define COOLERMASTER_KEYBOARD_SK651B_PID 0x0091 // unsupported
#define COOLERMASTER_KEYBOARD_SK651W_PID 0x0127 // [signal]
#define COOLERMASTER_KEYBOARD_SK652_PID 0x015D // [signal]
#define COOLERMASTER_KEYBOARD_SK653_PID 0x01AB // [openrgb #3571, signal]
extern const unsigned int COOLERMASTER_KEYBOARD_DEVICE_COUNT;
extern const cm_kb_device** cm_kb_device_list;
/*---------------------------------------------------------*\
| CMKeyboardDevices.h |
| |
| Device list for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "KeyboardLayoutManager.h"
/*-----------------------------------------------------*\
| List of all supported effects by this controller. |
| All of these effects are firmware controlled, and |
| they types of effects supported will depend on the |
| Keyboard. |
| |
| To enable a command, the SetEffect(effectId) needs |
| to be called. The specific effectId->Effect mapping |
| depends on the keyboard. |
\*-----------------------------------------------------*/
enum cm_keyboard_effect_type
{
NONE = 0,
DIRECT,
SINGLE,
FULLY_LIT,
STATIC,
BREATHE,
CYCLE,
WAVE,
RIPPLE,
CROSS,
RAINDROPS,
STARS,
SNAKE,
CUSTOMIZED,
INDICATOR,
MULTILAYER,
REACTIVE_FADE,
REACTIVE_PUNCH,
REACTIVE_TORNADO,
HEARTBEAT,
FIREBALL,
SNOW,
CIRCLE_SPECTRUM,
WATER_RIPPLE,
OFF
};
#define CM_KB_ZONES_MAX 1
typedef struct
{
std::string name;
zone_type type;
} cm_kb_zone;
typedef struct
{
uint16_t product_id;
const cm_kb_zone * zones[CM_KB_ZONES_MAX];
keyboard_keymap_overlay_values* layout_new;
} cm_kb_device;
#define COOLERMASTER_VID 0x2516
#define CMKB_MAXKEYS 256
/*-----------------------------------------------------------------*\
| keyboard support status is indicated to the right of |
| the PID definition. Attribution to products is also |
| indicated. |
| |
| libcmmk |
| signal https://gitlab.com/signalrgb/signal-plugins |
| openrgb |
| ck550-macos https://github.com/vookimedlo/ck550-macos/tree/master |
| reversed |
| |
| issue tickets, open merge requests etc are provided |
| for developer references. |
| # denotes issue ticket |
| ! denotes merge/pull request |
\*-----------------------------------------------------------------*/
#define COOLERMASTER_KEYBOARD_CK351_PID 0x014F // unsupported
#define COOLERMASTER_KEYBOARD_CK530_PID 0x009F // [ck550-macos]
#define COOLERMASTER_KEYBOARD_CK530_V2_PID 0x0147 // [signal]
#define COOLERMASTER_KEYBOARD_CK550_V2_PID 0x0145 // [openrgb #800, #2863, signal]
#define COOLERMASTER_KEYBOARD_CK552_V2_PID 0x007F // [ck550-macos, signal]
#define COOLERMASTER_KEYBOARD_CK570_V2_PID 0x01E8 // unsupported
#define COOLERMASTER_KEYBOARD_CK720_PID 0x016B // unsupported
#define COOLERMASTER_KEYBOARD_CK721_PID 0x016D // unsupported
#define COOLERMASTER_KEYBOARD_CK721LINE_PID 0x01EE // unsupported
#define COOLERMASTER_KEYBOARD_PRO_L_PID 0x003B // [libcmmk !16]
#define COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID 0x0047 // [libcmmk]
#define COOLERMASTER_KEYBOARD_PRO_S_PID 0x003C // [libcmmk #30 !31 !36, !37, !7, #5(closed), #3(closed)]
// MASTERKEYS PRO M [libcmmk #17]
#define COOLERMASTER_KEYBOARD_MK721_PID 0x016F // unsupported
#define COOLERMASTER_KEYBOARD_MK730_PID 0x008F // [openrgb #1630, libcmmk]
#define COOLERMASTER_KEYBOARD_MK750_PID 0x0067 // fw1.2 [libcmmk #25 !9, !14, signal]
#define COOLERMASTER_KEYBOARD_MK770_PID 0x01D5 // unsupported
#define COOLERMASTER_KEYBOARD_MK850_PID 0x0069 // [signal]
#define COOLERMASTER_KEYBOARD_SK620B_PID 0x0157 // [openrgb #4292]
#define COOLERMASTER_KEYBOARD_SK620W_PID 0x0159 // [openrgb #4292, signal]
#define COOLERMASTER_KEYBOARD_SK622B_PID 0x0149 // [openrgb #3110, signal #217(closed)]
#define COOLERMASTER_KEYBOARD_SK622W_PID 0x014B // [signal]
#define COOLERMASTER_KEYBOARD_SK630_PID 0x0089 // [openrgb #967, libcmmk !21]
#define COOLERMASTER_KEYBOARD_SK631B_PID 0x008B // unsupported
#define COOLERMASTER_KEYBOARD_SK631W_PID 0x0125 // [libcmmk]
#define COOLERMASTER_KEYBOARD_SK650_PID 0x008D // [openrgb #613, libcmmk #23 !37 !27 !28, signal]
#define COOLERMASTER_KEYBOARD_SK651B_PID 0x0091 // unsupported
#define COOLERMASTER_KEYBOARD_SK651W_PID 0x0127 // [signal]
#define COOLERMASTER_KEYBOARD_SK652_PID 0x015D // [signal]
#define COOLERMASTER_KEYBOARD_SK653_PID 0x01AB // [openrgb #3571, signal]
extern const unsigned int COOLERMASTER_KEYBOARD_DEVICE_COUNT;
extern const cm_kb_device** cm_kb_device_list;
@@ -1,500 +1,500 @@
/*---------------------------------------------------------*\
| CMKeyboardV1Controller.cpp |
| |
| Driver for Cooler Master MasterKeys (V1) keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cmath>
#include "CMKeyboardV1Controller.h"
#include "LogManager.h"
CMKeyboardV1Controller::CMKeyboardV1Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) : CMKeyboardAbstractController(dev_handle, dev_info, dev_name)
{
m_sFirmwareVersion = _GetFirmwareVersion();
}
CMKeyboardV1Controller::~CMKeyboardV1Controller()
{
}
void CMKeyboardV1Controller::Initialize()
{
SetLEDControl(true);
}
void CMKeyboardV1Controller::SetActiveEffect(uint8_t effectId)
{
SendCommand({0x51, 0x28, 0x00, 0x00, effectId});
}
uint8_t CMKeyboardV1Controller::GetActiveEffect()
{
std::vector<uint8_t> data = SendCommand({0x52, 0x28});
return data[4];
}
void CMKeyboardV1Controller::SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2)
{
std::vector<uint8_t> data;
data.push_back(0x51);
data.push_back(0x2C);
data.push_back(0x00); // multilayer_mode - NOT SUPPORTED
data.push_back(0x00);
data.push_back(effectId);
data.push_back(p1);
data.push_back(p2);
data.push_back(p3);
data.push_back(0xFF);
data.push_back(0xFF);
data.push_back(RGBGetRValue(color1));
data.push_back(RGBGetGValue(color1));
data.push_back(RGBGetBValue(color1));
data.push_back(RGBGetRValue(color2));
data.push_back(RGBGetGValue(color2));
data.push_back(RGBGetBValue(color2));
/*-------------------------------------------*\
| Likely a bit mask for each LEDs. |
| 3 bits per LED x 127 possible LEDs ~48 bytes|
\*-------------------------------------------*/
for(size_t i = 0; i < 48; i++)
{
data.push_back(0xFF);
}
SetCustomMode();
SetActiveEffect(effectId);
SendCommand(data);
}
void CMKeyboardV1Controller::SetCustomMode()
{
SetControlMode(0x01);
}
void CMKeyboardV1Controller::SetMode(mode selectedMode)
{
RGBColor color1 = 0;
RGBColor color2 = 0;
uint8_t cSpeed = 0;
uint8_t cDirection = 0;
uint8_t effectId = selectedMode.value;
bool bModeRandom = false;
if(selectedMode.colors.size() >= 1)
{
color1 = selectedMode.colors[0];
}
if(selectedMode.colors.size() >= 2)
{
color2 = selectedMode.colors[1];
}
if(selectedMode.color_mode == MODE_COLORS_RANDOM)
{
bModeRandom = true;
}
int selectedEffect = mapModeValueEffect[effectId];
cSpeed = selectedMode.speed;
switch(selectedMode.direction)
{
case MODE_DIRECTION_LEFT:
case MODE_DIRECTION_HORIZONTAL:
cDirection = 0x00;
break;
case MODE_DIRECTION_RIGHT:
cDirection = 0x04;
break;
case MODE_DIRECTION_UP:
case MODE_DIRECTION_VERTICAL:
cDirection = 0x06;
break;
case MODE_DIRECTION_DOWN:
cDirection = 0x02;
break;
default:
break;
}
switch(selectedEffect)
{
case DIRECT:
case STATIC:
{
SetEffect(effectId, 0, 0, 0, color1, color2);
}
break;
case CROSS:
case BREATHE:
case REACTIVE_PUNCH:
case CIRCLE_SPECTRUM:
case SNAKE:
{
SetEffect(effectId, cSpeed, 0, 0xFF, color1, color2);
}
break;
case WAVE:
{
SetEffect(effectId, cSpeed, cDirection, 0xFF, color1, color2);
}
break;
case RIPPLE:
{
SetEffect(effectId, cSpeed, bModeRandom ? 0x80 : 0x00, 0xFF, color1, color2);
}
break;
case RAINDROPS:
{
SetEffect(effectId, 0x6a, 0x00, cSpeed, color1, color2);
}
break;
case STARS:
{
SetEffect(effectId, cSpeed, 0x00, 0x10, color1, color2);
}
break;
default:
break;
}
}
void CMKeyboardV1Controller::InitializeModes(std::vector<mode> &modes)
{
mode Direct;
Direct.name = "Direct";
Direct.value = 0x02;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mapModeValueEffect[0x02] = DIRECT;
mode Static;
Static.name = "Static";
Static.value = 0x00;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(1);
modes.push_back(Static);
mapModeValueEffect[0x00] = STATIC;
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = 0x01;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.speed_min = 0x46;
Breathing.speed_max = 0x27;
Breathing.speed = 0x36;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(1);
modes.push_back(Breathing);
mapModeValueEffect[0x01] = BREATHE;
mode Cycle;
Cycle.name = "Spectrum Cycle";
Cycle.value = 0x02;
Cycle.flags = MODE_FLAG_HAS_SPEED;
Cycle.color_mode = MODE_COLORS_NONE;
Cycle.speed_min = 0x96;
Cycle.speed_max = 0x68;
Cycle.speed = 0x7F;
modes.push_back(Cycle);
mapModeValueEffect[0x02] = CIRCLE_SPECTRUM;
mode Reactive;
Reactive.name = "Reactive";
Reactive.value = 0x03;
Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC;
Reactive.speed_min = 0x3C;
Reactive.speed_max = 0x2F;
Reactive.speed = 0x35;
Reactive.colors_min = 2;
Reactive.colors_max = 2;
Reactive.colors.resize(2);
modes.push_back(Reactive);
mapModeValueEffect[0x03] = REACTIVE_PUNCH;
mode Wave;
Wave.name = "Rainbow Wave";
Wave.value = 0x04;
Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD;
Wave.color_mode = MODE_COLORS_MODE_SPECIFIC;
Wave.speed_min = 0x48;
Wave.speed_max = 0x2A;
Wave.speed = 0x29;
Wave.direction = MODE_DIRECTION_LEFT;
Wave.colors_min = 1;
Wave.colors_max = 1;
Wave.colors.resize(1);
modes.push_back(Wave);
mapModeValueEffect[0x04] = WAVE;
mode Ripple;
Ripple.name = "Ripple Effect";
Ripple.value = 0x05;
Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED;
Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC;
Ripple.speed_min = 0x96;
Ripple.speed_max = 0x62;
Ripple.speed = 0x7C;
Ripple.colors_min = 2;
Ripple.colors_max = 2;
Ripple.colors.resize(2);
modes.push_back(Ripple);
mapModeValueEffect[0x05] = RIPPLE;
mode Cross;
Cross.name = "Cross";
Cross.value = 0x06;
Cross.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Cross.color_mode = MODE_COLORS_MODE_SPECIFIC;
Cross.speed_min = 0x2A;
Cross.speed_max = 0x48;
Cross.speed = 0x39;
Cross.colors_min = 2;
Cross.colors_max = 2;
Cross.colors.resize(2);
modes.push_back(Cross);
mapModeValueEffect[0x06] = CROSS;
mode Raindrops;
Raindrops.name = "Raindrops";
Raindrops.value = 0x07;
Raindrops.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Raindrops.color_mode = MODE_COLORS_MODE_SPECIFIC;
Raindrops.speed_min = 0x40;
Raindrops.speed_max = 0x08;
Raindrops.speed = 0x24;
Raindrops.colors_min = 2;
Raindrops.colors_max = 2;
Raindrops.colors.resize(2);
modes.push_back(Raindrops);
mapModeValueEffect[0x07] = RAINDROPS;
mode Stars;
Stars.name = "Starfield";
Stars.value = 0x08;
Stars.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Stars.color_mode = MODE_COLORS_MODE_SPECIFIC;
Stars.speed_min = 0x46;
Stars.speed_max = 0x32;
Stars.speed = 0x3C;
Stars.colors_min = 2;
Stars.colors_max = 2;
Stars.colors.resize(2);
modes.push_back(Stars);
mapModeValueEffect[0x08] = STARS;
mode Snake;
Snake.name = "Snake";
Snake.value = 0x09;
Snake.flags = MODE_FLAG_HAS_SPEED;
Snake.color_mode = MODE_COLORS_NONE;
Snake.speed_min = 0x48;
Snake.speed_max = 0x2A;
Snake.speed = 0x39;
modes.push_back(Snake);
mapModeValueEffect[0x09] = SNAKE;
}
struct cm_keyboard_effect CMKeyboardV1Controller::GetEffect(uint8_t effectId)
{
std::vector<uint8_t> data;
data.push_back(0x52);
data.push_back(0x2C);
data.push_back(0x00);
data.push_back(0x00);
data.push_back(effectId);
data = SendCommand(data);
struct cm_keyboard_effect response;
response.effectId = effectId;
response.p1 = data[5];
response.p2 = data[6];
response.p3 = data[7];
response.color1 = ToRGBColor(data[10], data[11], data[12]);
response.color2 = ToRGBColor(data[13], data[14], data[15]);
return response;
}
std::vector<uint8_t> CMKeyboardV1Controller::GetEnabledEffects()
{
std::vector<uint8_t> data;
data = SendCommand({0x52, 0x29});
std::vector<uint8_t> effects;
for(size_t i = 4; data[i] != 0xFF; i++)
{
effects.push_back(data[i]);
}
return effects;
}
void CMKeyboardV1Controller::SetLEDControl(bool bManual)
{
uint8_t modeId = 0; // firmware
if(bManual)
{
modeId = 0x02; // manual
}
SetControlMode(modeId);
};
void CMKeyboardV1Controller::SetLeds(std::vector<led> leds, std::vector<RGBColor> colors)
{
SetLEDControl(true);
RGBColor rgbColorMap[CM_MAX_LEDS];
memset(rgbColorMap, 0, sizeof(RGBColor)*CM_MAX_LEDS);
for(size_t i = 0; i < leds.size(); i++)
{
rgbColorMap[leds[i].value] = colors[i];
}
RGBColor * pRGBColor = rgbColorMap;
std::lock_guard<std::mutex> guard(m_mutex);
for(size_t i = 0; i < 8; i++)
{
std::vector<uint8_t> data;
data.push_back(0xC0);
data.push_back(0x02);
data.push_back((uint8_t)(i * 2));
data.push_back(0x00);
for(size_t j = 0; j < 16; j++)
{
data.push_back(RGBGetRValue(*pRGBColor));
data.push_back(RGBGetGValue(*pRGBColor));
data.push_back(RGBGetBValue(*pRGBColor));
++pRGBColor;
}
SendCommand(data);
}
}
void CMKeyboardV1Controller::SetSingleLED(uint8_t in_led, RGBColor in_color)
{
std::vector<uint8_t> data;
data.push_back(0xC0);
data.push_back(0x01);
data.push_back(0x01);
data.push_back(0x00);
data.push_back(in_led);
data.push_back(RGBGetRValue(in_color));
data.push_back(RGBGetGValue(in_color));
data.push_back(RGBGetBValue(in_color));
SendCommand(data);
}
/*-------------------------------------------------------------------*\
| Detect the Firmware Version |
| |
| Firmware version string is in the format: |
| <layout>.<minor>.<major> |
| Where <layout> is: |
| UNK = 0, ANSI/US = 1, ISO/EU = 2, JP = 3 |
| Examples: |
| 1.2.1 = ANSI/US Keyboard (PRO S) |
| 2.2.1 = ISO/EU Keyboard (PRO L) |
\*-------------------------------------------------------------------*/
std::string CMKeyboardV1Controller::_GetFirmwareVersion()
{
std::vector<uint8_t> read;
SetControlMode(MODE_FIRMWARE);
read = SendCommand({0x01, 0x02});
char cVersionStr[CM_KEYBOARD_WRITE_SIZE];
for(size_t i = 0; i < read.size(); i++)
{
cVersionStr[i] = read[i];
}
cVersionStr[CM_KEYBOARD_WRITE_SIZE - 1] = 0;
std::string sFirmwareVersion;
sFirmwareVersion = std::string(cVersionStr+4);
LOG_VERBOSE("[%s] GetFirmwareVersion(): [%s]", m_deviceName.c_str(), sFirmwareVersion.c_str());
return sFirmwareVersion;
}
void CMKeyboardV1Controller::Shutdown()
{
}
KEYBOARD_LAYOUT CMKeyboardV1Controller::GetKeyboardLayout()
{
KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT_DEFAULT;
if(m_sFirmwareVersion.empty())
{
LOG_WARNING("[%s] GetKeyboardLayout() empty firmware string detected. Unable to detect firmware layout. Assuming defaults.", m_deviceName.c_str());
layout = KEYBOARD_LAYOUT_ANSI_QWERTY;
return layout;
}
switch(m_sFirmwareVersion.c_str()[0])
{
case '0':
default:
case '1':
layout = KEYBOARD_LAYOUT_ANSI_QWERTY;
break;
case '2':
layout = KEYBOARD_LAYOUT_ISO_QWERTY;
break;
case '3':
layout = KEYBOARD_LAYOUT_JIS;
break;
}
return layout;
}
/*---------------------------------------------------------*\
| CMKeyboardV1Controller.cpp |
| |
| Driver for Cooler Master MasterKeys (V1) keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cmath>
#include "CMKeyboardV1Controller.h"
#include "LogManager.h"
CMKeyboardV1Controller::CMKeyboardV1Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) : CMKeyboardAbstractController(dev_handle, dev_info, dev_name)
{
m_sFirmwareVersion = _GetFirmwareVersion();
}
CMKeyboardV1Controller::~CMKeyboardV1Controller()
{
}
void CMKeyboardV1Controller::Initialize()
{
SetLEDControl(true);
}
void CMKeyboardV1Controller::SetActiveEffect(uint8_t effectId)
{
SendCommand({0x51, 0x28, 0x00, 0x00, effectId});
}
uint8_t CMKeyboardV1Controller::GetActiveEffect()
{
std::vector<uint8_t> data = SendCommand({0x52, 0x28});
return data[4];
}
void CMKeyboardV1Controller::SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2)
{
std::vector<uint8_t> data;
data.push_back(0x51);
data.push_back(0x2C);
data.push_back(0x00); // multilayer_mode - NOT SUPPORTED
data.push_back(0x00);
data.push_back(effectId);
data.push_back(p1);
data.push_back(p2);
data.push_back(p3);
data.push_back(0xFF);
data.push_back(0xFF);
data.push_back(RGBGetRValue(color1));
data.push_back(RGBGetGValue(color1));
data.push_back(RGBGetBValue(color1));
data.push_back(RGBGetRValue(color2));
data.push_back(RGBGetGValue(color2));
data.push_back(RGBGetBValue(color2));
/*-------------------------------------------*\
| Likely a bit mask for each LEDs. |
| 3 bits per LED x 127 possible LEDs ~48 bytes|
\*-------------------------------------------*/
for(size_t i = 0; i < 48; i++)
{
data.push_back(0xFF);
}
SetCustomMode();
SetActiveEffect(effectId);
SendCommand(data);
}
void CMKeyboardV1Controller::SetCustomMode()
{
SetControlMode(0x01);
}
void CMKeyboardV1Controller::SetMode(mode selectedMode)
{
RGBColor color1 = 0;
RGBColor color2 = 0;
uint8_t cSpeed = 0;
uint8_t cDirection = 0;
uint8_t effectId = selectedMode.value;
bool bModeRandom = false;
if(selectedMode.colors.size() >= 1)
{
color1 = selectedMode.colors[0];
}
if(selectedMode.colors.size() >= 2)
{
color2 = selectedMode.colors[1];
}
if(selectedMode.color_mode == MODE_COLORS_RANDOM)
{
bModeRandom = true;
}
int selectedEffect = mapModeValueEffect[effectId];
cSpeed = selectedMode.speed;
switch(selectedMode.direction)
{
case MODE_DIRECTION_LEFT:
case MODE_DIRECTION_HORIZONTAL:
cDirection = 0x00;
break;
case MODE_DIRECTION_RIGHT:
cDirection = 0x04;
break;
case MODE_DIRECTION_UP:
case MODE_DIRECTION_VERTICAL:
cDirection = 0x06;
break;
case MODE_DIRECTION_DOWN:
cDirection = 0x02;
break;
default:
break;
}
switch(selectedEffect)
{
case DIRECT:
case STATIC:
{
SetEffect(effectId, 0, 0, 0, color1, color2);
}
break;
case CROSS:
case BREATHE:
case REACTIVE_PUNCH:
case CIRCLE_SPECTRUM:
case SNAKE:
{
SetEffect(effectId, cSpeed, 0, 0xFF, color1, color2);
}
break;
case WAVE:
{
SetEffect(effectId, cSpeed, cDirection, 0xFF, color1, color2);
}
break;
case RIPPLE:
{
SetEffect(effectId, cSpeed, bModeRandom ? 0x80 : 0x00, 0xFF, color1, color2);
}
break;
case RAINDROPS:
{
SetEffect(effectId, 0x6a, 0x00, cSpeed, color1, color2);
}
break;
case STARS:
{
SetEffect(effectId, cSpeed, 0x00, 0x10, color1, color2);
}
break;
default:
break;
}
}
void CMKeyboardV1Controller::InitializeModes(std::vector<mode> &modes)
{
mode Direct;
Direct.name = "Direct";
Direct.value = 0x02;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mapModeValueEffect[0x02] = DIRECT;
mode Static;
Static.name = "Static";
Static.value = 0x00;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(1);
modes.push_back(Static);
mapModeValueEffect[0x00] = STATIC;
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = 0x01;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.speed_min = 0x46;
Breathing.speed_max = 0x27;
Breathing.speed = 0x36;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(1);
modes.push_back(Breathing);
mapModeValueEffect[0x01] = BREATHE;
mode Cycle;
Cycle.name = "Spectrum Cycle";
Cycle.value = 0x02;
Cycle.flags = MODE_FLAG_HAS_SPEED;
Cycle.color_mode = MODE_COLORS_NONE;
Cycle.speed_min = 0x96;
Cycle.speed_max = 0x68;
Cycle.speed = 0x7F;
modes.push_back(Cycle);
mapModeValueEffect[0x02] = CIRCLE_SPECTRUM;
mode Reactive;
Reactive.name = "Reactive";
Reactive.value = 0x03;
Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC;
Reactive.speed_min = 0x3C;
Reactive.speed_max = 0x2F;
Reactive.speed = 0x35;
Reactive.colors_min = 2;
Reactive.colors_max = 2;
Reactive.colors.resize(2);
modes.push_back(Reactive);
mapModeValueEffect[0x03] = REACTIVE_PUNCH;
mode Wave;
Wave.name = "Rainbow Wave";
Wave.value = 0x04;
Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD;
Wave.color_mode = MODE_COLORS_MODE_SPECIFIC;
Wave.speed_min = 0x48;
Wave.speed_max = 0x2A;
Wave.speed = 0x29;
Wave.direction = MODE_DIRECTION_LEFT;
Wave.colors_min = 1;
Wave.colors_max = 1;
Wave.colors.resize(1);
modes.push_back(Wave);
mapModeValueEffect[0x04] = WAVE;
mode Ripple;
Ripple.name = "Ripple Effect";
Ripple.value = 0x05;
Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED;
Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC;
Ripple.speed_min = 0x96;
Ripple.speed_max = 0x62;
Ripple.speed = 0x7C;
Ripple.colors_min = 2;
Ripple.colors_max = 2;
Ripple.colors.resize(2);
modes.push_back(Ripple);
mapModeValueEffect[0x05] = RIPPLE;
mode Cross;
Cross.name = "Cross";
Cross.value = 0x06;
Cross.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Cross.color_mode = MODE_COLORS_MODE_SPECIFIC;
Cross.speed_min = 0x2A;
Cross.speed_max = 0x48;
Cross.speed = 0x39;
Cross.colors_min = 2;
Cross.colors_max = 2;
Cross.colors.resize(2);
modes.push_back(Cross);
mapModeValueEffect[0x06] = CROSS;
mode Raindrops;
Raindrops.name = "Raindrops";
Raindrops.value = 0x07;
Raindrops.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Raindrops.color_mode = MODE_COLORS_MODE_SPECIFIC;
Raindrops.speed_min = 0x40;
Raindrops.speed_max = 0x08;
Raindrops.speed = 0x24;
Raindrops.colors_min = 2;
Raindrops.colors_max = 2;
Raindrops.colors.resize(2);
modes.push_back(Raindrops);
mapModeValueEffect[0x07] = RAINDROPS;
mode Stars;
Stars.name = "Starfield";
Stars.value = 0x08;
Stars.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Stars.color_mode = MODE_COLORS_MODE_SPECIFIC;
Stars.speed_min = 0x46;
Stars.speed_max = 0x32;
Stars.speed = 0x3C;
Stars.colors_min = 2;
Stars.colors_max = 2;
Stars.colors.resize(2);
modes.push_back(Stars);
mapModeValueEffect[0x08] = STARS;
mode Snake;
Snake.name = "Snake";
Snake.value = 0x09;
Snake.flags = MODE_FLAG_HAS_SPEED;
Snake.color_mode = MODE_COLORS_NONE;
Snake.speed_min = 0x48;
Snake.speed_max = 0x2A;
Snake.speed = 0x39;
modes.push_back(Snake);
mapModeValueEffect[0x09] = SNAKE;
}
struct cm_keyboard_effect CMKeyboardV1Controller::GetEffect(uint8_t effectId)
{
std::vector<uint8_t> data;
data.push_back(0x52);
data.push_back(0x2C);
data.push_back(0x00);
data.push_back(0x00);
data.push_back(effectId);
data = SendCommand(data);
struct cm_keyboard_effect response;
response.effectId = effectId;
response.p1 = data[5];
response.p2 = data[6];
response.p3 = data[7];
response.color1 = ToRGBColor(data[10], data[11], data[12]);
response.color2 = ToRGBColor(data[13], data[14], data[15]);
return response;
}
std::vector<uint8_t> CMKeyboardV1Controller::GetEnabledEffects()
{
std::vector<uint8_t> data;
data = SendCommand({0x52, 0x29});
std::vector<uint8_t> effects;
for(size_t i = 4; data[i] != 0xFF; i++)
{
effects.push_back(data[i]);
}
return effects;
}
void CMKeyboardV1Controller::SetLEDControl(bool bManual)
{
uint8_t modeId = 0; // firmware
if(bManual)
{
modeId = 0x02; // manual
}
SetControlMode(modeId);
};
void CMKeyboardV1Controller::SetLeds(std::vector<led> leds, std::vector<RGBColor> colors)
{
SetLEDControl(true);
RGBColor rgbColorMap[CM_MAX_LEDS];
memset(rgbColorMap, 0, sizeof(RGBColor)*CM_MAX_LEDS);
for(size_t i = 0; i < leds.size(); i++)
{
rgbColorMap[leds[i].value] = colors[i];
}
RGBColor * pRGBColor = rgbColorMap;
std::lock_guard<std::mutex> guard(m_mutex);
for(size_t i = 0; i < 8; i++)
{
std::vector<uint8_t> data;
data.push_back(0xC0);
data.push_back(0x02);
data.push_back((uint8_t)(i * 2));
data.push_back(0x00);
for(size_t j = 0; j < 16; j++)
{
data.push_back(RGBGetRValue(*pRGBColor));
data.push_back(RGBGetGValue(*pRGBColor));
data.push_back(RGBGetBValue(*pRGBColor));
++pRGBColor;
}
SendCommand(data);
}
}
void CMKeyboardV1Controller::SetSingleLED(uint8_t in_led, RGBColor in_color)
{
std::vector<uint8_t> data;
data.push_back(0xC0);
data.push_back(0x01);
data.push_back(0x01);
data.push_back(0x00);
data.push_back(in_led);
data.push_back(RGBGetRValue(in_color));
data.push_back(RGBGetGValue(in_color));
data.push_back(RGBGetBValue(in_color));
SendCommand(data);
}
/*-------------------------------------------------------------------*\
| Detect the Firmware Version |
| |
| Firmware version string is in the format: |
| <layout>.<minor>.<major> |
| Where <layout> is: |
| UNK = 0, ANSI/US = 1, ISO/EU = 2, JP = 3 |
| Examples: |
| 1.2.1 = ANSI/US Keyboard (PRO S) |
| 2.2.1 = ISO/EU Keyboard (PRO L) |
\*-------------------------------------------------------------------*/
std::string CMKeyboardV1Controller::_GetFirmwareVersion()
{
std::vector<uint8_t> read;
SetControlMode(MODE_FIRMWARE);
read = SendCommand({0x01, 0x02});
char cVersionStr[CM_KEYBOARD_WRITE_SIZE];
for(size_t i = 0; i < read.size(); i++)
{
cVersionStr[i] = read[i];
}
cVersionStr[CM_KEYBOARD_WRITE_SIZE - 1] = 0;
std::string sFirmwareVersion;
sFirmwareVersion = std::string(cVersionStr+4);
LOG_VERBOSE("[%s] GetFirmwareVersion(): [%s]", m_deviceName.c_str(), sFirmwareVersion.c_str());
return sFirmwareVersion;
}
void CMKeyboardV1Controller::Shutdown()
{
}
KEYBOARD_LAYOUT CMKeyboardV1Controller::GetKeyboardLayout()
{
KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT_DEFAULT;
if(m_sFirmwareVersion.empty())
{
LOG_WARNING("[%s] GetKeyboardLayout() empty firmware string detected. Unable to detect firmware layout. Assuming defaults.", m_deviceName.c_str());
layout = KEYBOARD_LAYOUT_ANSI_QWERTY;
return layout;
}
switch(m_sFirmwareVersion.c_str()[0])
{
case '0':
default:
case '1':
layout = KEYBOARD_LAYOUT_ANSI_QWERTY;
break;
case '2':
layout = KEYBOARD_LAYOUT_ISO_QWERTY;
break;
case '3':
layout = KEYBOARD_LAYOUT_JIS;
break;
}
return layout;
}
@@ -1,43 +1,43 @@
/*---------------------------------------------------------*\
| CMKeyboardV1Controller.h |
| |
| Driver for Cooler Master MasterKeys (V1) keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "CMKeyboardAbstractController.h"
class CMKeyboardV1Controller : public CMKeyboardAbstractController
{
public:
CMKeyboardV1Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
~CMKeyboardV1Controller();
/*---------------------------------------------------------*\
| Protocol specific funtions to be implmented |
\*---------------------------------------------------------*/
void SetLeds(std::vector<led> leds, std::vector<RGBColor> colors);
void SetSingleLED(uint8_t in_led, RGBColor in_color);
void Initialize();
void Shutdown();
void SetLEDControl(bool bManual);
void SetActiveEffect(uint8_t effectId);
uint8_t GetActiveEffect();
void SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2);
struct cm_keyboard_effect GetEffect(uint8_t effectId);
void SetCustomMode();
void SetMode(mode selectedMode);
std::vector<uint8_t> GetEnabledEffects();
void InitializeModes(std::vector<mode> &modes);
KEYBOARD_LAYOUT GetKeyboardLayout();
private:
std::string _GetFirmwareVersion();
};
/*---------------------------------------------------------*\
| CMKeyboardV1Controller.h |
| |
| Driver for Cooler Master MasterKeys (V1) keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "CMKeyboardAbstractController.h"
class CMKeyboardV1Controller : public CMKeyboardAbstractController
{
public:
CMKeyboardV1Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
~CMKeyboardV1Controller();
/*---------------------------------------------------------*\
| Protocol specific funtions to be implmented |
\*---------------------------------------------------------*/
void SetLeds(std::vector<led> leds, std::vector<RGBColor> colors);
void SetSingleLED(uint8_t in_led, RGBColor in_color);
void Initialize();
void Shutdown();
void SetLEDControl(bool bManual);
void SetActiveEffect(uint8_t effectId);
uint8_t GetActiveEffect();
void SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2);
struct cm_keyboard_effect GetEffect(uint8_t effectId);
void SetCustomMode();
void SetMode(mode selectedMode);
std::vector<uint8_t> GetEnabledEffects();
void InitializeModes(std::vector<mode> &modes);
KEYBOARD_LAYOUT GetKeyboardLayout();
private:
std::string _GetFirmwareVersion();
};
File diff suppressed because it is too large. Load diff
@@ -1,59 +1,59 @@
/*---------------------------------------------------------*\
| CMKeyboardV2Controller.h |
| |
| Driver for Cooler Master V2 keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "CMKeyboardAbstractController.h"
struct stCMKeyboardV2_mode
{
const char *name;
unsigned int value;
unsigned int speed_min;
unsigned int speed_max;
unsigned int speed;
unsigned int brightness;
unsigned int direction;
unsigned int nColors;
unsigned int color_mode;
unsigned int flags;
};
class CMKeyboardV2Controller : public CMKeyboardAbstractController
{
public:
CMKeyboardV2Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
~CMKeyboardV2Controller();
/*---------------------------------------------------------*\
| Protocol specific funtions to be implmented |
\*---------------------------------------------------------*/
void SetLeds(std::vector<led> leds, std::vector<RGBColor> colors);
void SetSingleLED(uint8_t in_led, RGBColor in_color);
void Initialize();
void Shutdown();
void SetLEDControl(bool bManual);
void SendApplyPacket(uint8_t mode);
void MagicStartupPacket();
void MagicCommand(uint8_t profileId);
void SetCustomMode();
void SetMode(mode selectedMode);
void SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2);
void InitializeModes(std::vector<mode> &modes);
KEYBOARD_LAYOUT GetKeyboardLayout();
private:
void _SetEffectMode(uint8_t effectId);
void _UpdateSpeed(mode selectedMode, uint8_t &cSpeed1, uint8_t &cSpeed2);
std::string _GetFirmwareVersion();
bool m_bMoreFFs;
};
/*---------------------------------------------------------*\
| CMKeyboardV2Controller.h |
| |
| Driver for Cooler Master V2 keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "CMKeyboardAbstractController.h"
struct stCMKeyboardV2_mode
{
const char *name;
unsigned int value;
unsigned int speed_min;
unsigned int speed_max;
unsigned int speed;
unsigned int brightness;
unsigned int direction;
unsigned int nColors;
unsigned int color_mode;
unsigned int flags;
};
class CMKeyboardV2Controller : public CMKeyboardAbstractController
{
public:
CMKeyboardV2Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
~CMKeyboardV2Controller();
/*---------------------------------------------------------*\
| Protocol specific funtions to be implmented |
\*---------------------------------------------------------*/
void SetLeds(std::vector<led> leds, std::vector<RGBColor> colors);
void SetSingleLED(uint8_t in_led, RGBColor in_color);
void Initialize();
void Shutdown();
void SetLEDControl(bool bManual);
void SendApplyPacket(uint8_t mode);
void MagicStartupPacket();
void MagicCommand(uint8_t profileId);
void SetCustomMode();
void SetMode(mode selectedMode);
void SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2);
void InitializeModes(std::vector<mode> &modes);
KEYBOARD_LAYOUT GetKeyboardLayout();
private:
void _SetEffectMode(uint8_t effectId);
void _UpdateSpeed(mode selectedMode, uint8_t &cSpeed1, uint8_t &cSpeed2);
std::string _GetFirmwareVersion();
bool m_bMoreFFs;
};
@@ -1,197 +1,197 @@
/*---------------------------------------------------------*\
| RGBController_CMKeyboardController.cpp |
| |
| RGBController for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_CMKeyboardController.h"
#include "CMKeyboardDevices.h"
/**------------------------------------------------------------------*\
@name Coolermaster Masterkeys Keyboards
@category Keyboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectCoolerMasterV1Keyboards,DetectCoolerMasterV2Keyboards
@comment
In CMKeyboardV1Controller brightness control not supported.
Supported effects differ between CMKeyboardV1Controller and
CMKeyboardV2Controller.
\*-------------------------------------------------------------------*/
RGBController_CMKeyboardController::RGBController_CMKeyboardController(CMKeyboardAbstractController* pController)
{
m_pController = pController;
vendor = m_pController->GetDeviceVendor();
type = DEVICE_TYPE_KEYBOARD;
description = "Cooler Master Keyboard Device";
version = m_pController->GetFirmwareVersion();
/*----------------------------------------------------------------*\
| Coolermaster uses the name field to store the serial number in |
| many of their keyboards. |
\*----------------------------------------------------------------*/
serial = m_pController->GetDeviceSerial();
location = m_pController->GetLocation();
m_keyboardLayout = m_pController->GetKeyboardLayout();
name = m_pController->GetDeviceName();
m_pController->InitializeModes(modes);
SetupZones();
}
RGBController_CMKeyboardController::~RGBController_CMKeyboardController()
{
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
if(zones[zone_index].matrix_map->map != NULL)
{
delete zones[zone_index].matrix_map->map;
}
delete zones[zone_index].matrix_map;
}
}
if(m_pController)
{
delete m_pController;
}
}
#define COOLERMASTER_ZONES_MAX 1
void RGBController_CMKeyboardController::SetupZones()
{
std::string physical_size;
unsigned int max_led_value = 0;
const cm_kb_device* coolermaster = m_pController->GetDeviceData();
/*---------------------------------------------------------*\
| Fill in zones from the device data |
\*---------------------------------------------------------*/
for(size_t i = 0; i < COOLERMASTER_ZONES_MAX; i++)
{
if(coolermaster->zones[i] == NULL)
{
break;
}
else
{
zone new_zone;
new_zone.name = coolermaster->zones[i]->name;
new_zone.type = coolermaster->zones[i]->type;
if(new_zone.type == ZONE_TYPE_MATRIX)
{
KeyboardLayoutManager new_kb(m_keyboardLayout, coolermaster->layout_new->base_size, coolermaster->layout_new->key_values);
matrix_map_type * new_map = new matrix_map_type;
new_zone.matrix_map = new_map;
if(coolermaster->layout_new->base_size != KEYBOARD_SIZE_EMPTY)
{
/*---------------------------------------------------------*\
| Minor adjustments to keyboard layout |
\*---------------------------------------------------------*/
keyboard_keymap_overlay_values* temp = coolermaster->layout_new;
new_kb.ChangeKeys(*temp);
new_map->height = new_kb.GetRowCount();
new_map->width = new_kb.GetColumnCount();
new_map->map = new unsigned int[new_map->height * new_map->width];
/*---------------------------------------------------------*\
| Matrix map still uses declared zone rows and columns |
| as the packet structure depends on the matrix map |
\*---------------------------------------------------------*/
new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, new_map->height, new_map->width);
/*---------------------------------------------------------*\
| Create LEDs for the Matrix zone |
| Place keys in the layout to populate the matrix |
\*---------------------------------------------------------*/
new_zone.leds_count = new_kb.GetKeyCount();
LOG_DEBUG("[%s] Created KB matrix with %d rows and %d columns containing %d keys",
m_pController->GetDeviceName().c_str(), new_kb.GetRowCount(), new_kb.GetColumnCount(), new_zone.leds_count);
for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++)
{
led new_led;
new_led.name = new_kb.GetKeyNameAt(led_idx);
new_led.value = new_kb.GetKeyValueAt(led_idx);
max_led_value = std::max(max_led_value, new_led.value);
leds.push_back(new_led);
}
}
/*---------------------------------------------------------*\
| Add 1 the max_led_value to account for the 0th index |
\*---------------------------------------------------------*/
max_led_value++;
}
/*---------------------------------------------------------*\
| name is not set yet so description is used instead |
\*---------------------------------------------------------*/
LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", description.c_str(),
((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"),
new_zone.name.c_str(), new_zone.leds_count);
new_zone.leds_min = new_zone.leds_count;
new_zone.leds_max = new_zone.leds_count;
zones.push_back(new_zone);
}
}
SetupColors();
}
void RGBController_CMKeyboardController::ResizeZone(int /*zone*/, int /*new_size*/)
{
}
void RGBController_CMKeyboardController::DeviceUpdateLEDs()
{
m_pController->SetLeds(leds, colors);
}
void RGBController_CMKeyboardController::UpdateSingleLED(int led, RGBColor color)
{
uint8_t key_value = m_pLayoutManager->GetKeyValueAt(led);
m_pController->SetSingleLED(key_value, color);
}
void RGBController_CMKeyboardController::UpdateSingleLED(int led)
{
m_pController->SetSingleLED(led, colors[led]);
}
void RGBController_CMKeyboardController::UpdateZoneLEDs(int /*zone_idx*/)
{
DeviceUpdateLEDs();
}
void RGBController_CMKeyboardController::DeviceUpdateMode()
{
m_pController->SetMode(modes[active_mode]);
}
void RGBController_CMKeyboardController::SetCustomMode()
{
}
/*---------------------------------------------------------*\
| RGBController_CMKeyboardController.cpp |
| |
| RGBController for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_CMKeyboardController.h"
#include "CMKeyboardDevices.h"
/**------------------------------------------------------------------*\
@name Coolermaster Masterkeys Keyboards
@category Keyboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectCoolerMasterV1Keyboards,DetectCoolerMasterV2Keyboards
@comment
In CMKeyboardV1Controller brightness control not supported.
Supported effects differ between CMKeyboardV1Controller and
CMKeyboardV2Controller.
\*-------------------------------------------------------------------*/
RGBController_CMKeyboardController::RGBController_CMKeyboardController(CMKeyboardAbstractController* pController)
{
m_pController = pController;
vendor = m_pController->GetDeviceVendor();
type = DEVICE_TYPE_KEYBOARD;
description = "Cooler Master Keyboard Device";
version = m_pController->GetFirmwareVersion();
/*----------------------------------------------------------------*\
| Coolermaster uses the name field to store the serial number in |
| many of their keyboards. |
\*----------------------------------------------------------------*/
serial = m_pController->GetDeviceSerial();
location = m_pController->GetLocation();
m_keyboardLayout = m_pController->GetKeyboardLayout();
name = m_pController->GetDeviceName();
m_pController->InitializeModes(modes);
SetupZones();
}
RGBController_CMKeyboardController::~RGBController_CMKeyboardController()
{
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
if(zones[zone_index].matrix_map->map != NULL)
{
delete zones[zone_index].matrix_map->map;
}
delete zones[zone_index].matrix_map;
}
}
if(m_pController)
{
delete m_pController;
}
}
#define COOLERMASTER_ZONES_MAX 1
void RGBController_CMKeyboardController::SetupZones()
{
std::string physical_size;
unsigned int max_led_value = 0;
const cm_kb_device* coolermaster = m_pController->GetDeviceData();
/*---------------------------------------------------------*\
| Fill in zones from the device data |
\*---------------------------------------------------------*/
for(size_t i = 0; i < COOLERMASTER_ZONES_MAX; i++)
{
if(coolermaster->zones[i] == NULL)
{
break;
}
else
{
zone new_zone;
new_zone.name = coolermaster->zones[i]->name;
new_zone.type = coolermaster->zones[i]->type;
if(new_zone.type == ZONE_TYPE_MATRIX)
{
KeyboardLayoutManager new_kb(m_keyboardLayout, coolermaster->layout_new->base_size, coolermaster->layout_new->key_values);
matrix_map_type * new_map = new matrix_map_type;
new_zone.matrix_map = new_map;
if(coolermaster->layout_new->base_size != KEYBOARD_SIZE_EMPTY)
{
/*---------------------------------------------------------*\
| Minor adjustments to keyboard layout |
\*---------------------------------------------------------*/
keyboard_keymap_overlay_values* temp = coolermaster->layout_new;
new_kb.ChangeKeys(*temp);
new_map->height = new_kb.GetRowCount();
new_map->width = new_kb.GetColumnCount();
new_map->map = new unsigned int[new_map->height * new_map->width];
/*---------------------------------------------------------*\
| Matrix map still uses declared zone rows and columns |
| as the packet structure depends on the matrix map |
\*---------------------------------------------------------*/
new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, new_map->height, new_map->width);
/*---------------------------------------------------------*\
| Create LEDs for the Matrix zone |
| Place keys in the layout to populate the matrix |
\*---------------------------------------------------------*/
new_zone.leds_count = new_kb.GetKeyCount();
LOG_DEBUG("[%s] Created KB matrix with %d rows and %d columns containing %d keys",
m_pController->GetDeviceName().c_str(), new_kb.GetRowCount(), new_kb.GetColumnCount(), new_zone.leds_count);
for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++)
{
led new_led;
new_led.name = new_kb.GetKeyNameAt(led_idx);
new_led.value = new_kb.GetKeyValueAt(led_idx);
max_led_value = std::max(max_led_value, new_led.value);
leds.push_back(new_led);
}
}
/*---------------------------------------------------------*\
| Add 1 the max_led_value to account for the 0th index |
\*---------------------------------------------------------*/
max_led_value++;
}
/*---------------------------------------------------------*\
| name is not set yet so description is used instead |
\*---------------------------------------------------------*/
LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", description.c_str(),
((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"),
new_zone.name.c_str(), new_zone.leds_count);
new_zone.leds_min = new_zone.leds_count;
new_zone.leds_max = new_zone.leds_count;
zones.push_back(new_zone);
}
}
SetupColors();
}
void RGBController_CMKeyboardController::ResizeZone(int /*zone*/, int /*new_size*/)
{
}
void RGBController_CMKeyboardController::DeviceUpdateLEDs()
{
m_pController->SetLeds(leds, colors);
}
void RGBController_CMKeyboardController::UpdateSingleLED(int led, RGBColor color)
{
uint8_t key_value = m_pLayoutManager->GetKeyValueAt(led);
m_pController->SetSingleLED(key_value, color);
}
void RGBController_CMKeyboardController::UpdateSingleLED(int led)
{
m_pController->SetSingleLED(led, colors[led]);
}
void RGBController_CMKeyboardController::UpdateZoneLEDs(int /*zone_idx*/)
{
DeviceUpdateLEDs();
}
void RGBController_CMKeyboardController::DeviceUpdateMode()
{
m_pController->SetMode(modes[active_mode]);
}
void RGBController_CMKeyboardController::SetCustomMode()
{
}
@@ -1,42 +1,42 @@
/*---------------------------------------------------------*\
| RGBController_CMKeyboardController.h |
| |
| RGBController for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "CMKeyboardAbstractController.h"
#include "CMKeyboardV1Controller.h"
#include "CMKeyboardV2Controller.h"
#include "CMKeyboardDevices.h"
class RGBController_CMKeyboardController : public RGBController
{
public:
RGBController_CMKeyboardController(CMKeyboardAbstractController* pController);
~RGBController_CMKeyboardController();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateSingleLED(int led, RGBColor color);
void UpdateSingleLED(int led);
void UpdateZoneLEDs(int zone_idx);
void SetCustomMode();
void DeviceUpdateMode();
private:
CMKeyboardAbstractController* m_pController;;
KeyboardLayoutManager* m_pLayoutManager;
KEYBOARD_LAYOUT m_keyboardLayout;
layout_values m_layoutValues;
};
/*---------------------------------------------------------*\
| RGBController_CMKeyboardController.h |
| |
| RGBController for Cooler Master keyboards |
| |
| Tam D (too.manyhobbies) 30 Nov 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "CMKeyboardAbstractController.h"
#include "CMKeyboardV1Controller.h"
#include "CMKeyboardV2Controller.h"
#include "CMKeyboardDevices.h"
class RGBController_CMKeyboardController : public RGBController
{
public:
RGBController_CMKeyboardController(CMKeyboardAbstractController* pController);
~RGBController_CMKeyboardController();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateSingleLED(int led, RGBColor color);
void UpdateSingleLED(int led);
void UpdateZoneLEDs(int zone_idx);
void SetCustomMode();
void DeviceUpdateMode();
private:
CMKeyboardAbstractController* m_pController;;
KeyboardLayoutManager* m_pLayoutManager;
KEYBOARD_LAYOUT m_keyboardLayout;
layout_values m_layoutValues;
};