Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f15c3c1420 | ||
|
|
aa67045330 | ||
|
|
736640f38d | ||
|
|
e9caf663bc | ||
|
|
8afbea53de | ||
|
|
c3d496ad5b | ||
|
|
06501f528d | ||
|
|
f6a678c1a4 | ||
|
|
30690d0ebd | ||
|
|
7a830cddf9 |
@@ -471,6 +471,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC WHITE",
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING_WHITE, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_2, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC BTF", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_BTF, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_WHITE, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL LC GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_LC_RTX_5090_O32G_GAMING, 0x67);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@
|
||||
#include <map>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define GB_FUSION2_ZONES_MAX 8
|
||||
#define GB_FUSION2_ZONES_MAX 12
|
||||
|
||||
/*--------------------------------------------------------*\
|
||||
| Base LED mappings found on all controllers. |
|
||||
@@ -89,6 +89,23 @@ const FwdLedHeaders LedLookup =
|
||||
\*-------------------------------------------------*/
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------*\
|
||||
| The layout_id masks for supported effects. |
|
||||
\*--------------------------------------------------------*/
|
||||
enum GB_LID_EFFECTS_MASKS : uint32_t
|
||||
{
|
||||
GB_EFF_BREATH = 0x001,
|
||||
GB_EFF_BEAT = 0x002,
|
||||
GB_EFF_CYCLE = 0x004,
|
||||
GB_EFF_FLASH = 0x008,
|
||||
GB_EFF_RANDOM = 0x010,
|
||||
GB_EFF_WAVE = 0x020,
|
||||
GB_EFF_DFLASH = 0x040,
|
||||
GB_EFF_WAVE1 = 0x080,
|
||||
GB_EFF_WAVE2 = 0x100,
|
||||
GB_EFF_CORE_MASK = 0x1FF
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GB_FUSION2_LED_IDX idx;
|
||||
|
||||
@@ -95,10 +95,9 @@ bool RGBFusion2USBController::RefreshHardwareInfo()
|
||||
return false;
|
||||
}
|
||||
|
||||
IT8297Report report;
|
||||
std::memcpy(&report, buffer, sizeof(IT8297Report));
|
||||
report_loaded = true;
|
||||
|
||||
device_num = report.device_num;
|
||||
description = std::string(report.str_product, 28);
|
||||
if(std::string::iterator nul = std::find(description.begin(), description.end(), '\0');
|
||||
nul != description.end())
|
||||
@@ -318,7 +317,7 @@ bool RGBFusion2USBController::SetCalibration(const EncodedCalibration& cal, bool
|
||||
cal_data.mainboard = desired.c.rgb_cali;
|
||||
cal_data.spare[0] = desired.c.c_spare0;
|
||||
cal_data.spare[1] = desired.c.c_spare1;
|
||||
|
||||
|
||||
if(product_id == 0x5711)
|
||||
{
|
||||
cal_data.dled[2] = desired.c.d_strip_c2;
|
||||
@@ -362,7 +361,6 @@ void RGBFusion2USBController::SetLedCount(unsigned int c0, unsigned int c1, unsi
|
||||
\*---------------------------------------------------------*/
|
||||
bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
|
||||
{
|
||||
static bool first_call = true;
|
||||
int bitmask = 0;
|
||||
|
||||
if(hdr == -1)
|
||||
@@ -392,16 +390,16 @@ bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
int new_effect_disabled = enable
|
||||
? (effect_disabled & ~bitmask)
|
||||
: (effect_disabled | bitmask);
|
||||
int base_mask = (effect_disabled < 0) ? 0 : effect_disabled;
|
||||
int new_effect_disabled = enable
|
||||
? (base_mask & ~bitmask)
|
||||
: (base_mask | bitmask);
|
||||
|
||||
if(!first_call && new_effect_disabled == effect_disabled)
|
||||
// Skip redundant writes only after we have synchronized at least once
|
||||
if(effect_disabled >= 0 && new_effect_disabled == effect_disabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
first_call = false;
|
||||
effect_disabled = new_effect_disabled;
|
||||
int res = SendCCReport(0x32, effect_disabled);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
@@ -439,7 +437,7 @@ bool RGBFusion2USBController::EnableLampArray(bool enable)
|
||||
{
|
||||
return SendCCReport(0x48, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
std::string RGBFusion2USBController::GetDeviceName()
|
||||
{
|
||||
return(name);
|
||||
@@ -703,3 +701,115 @@ void RGBFusion2USBController::ResetController()
|
||||
}
|
||||
ApplyEffect(true);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Check controller for gen2 ARGB support |
|
||||
| Checks for supported device number |
|
||||
| Then checks for supported controllers |
|
||||
| Then checks for supported feature bit (SaveLEDState) |
|
||||
| Finally checks for strip detection value. |
|
||||
\*---------------------------------------------------------*/
|
||||
bool RGBFusion2USBController::SupportsGen2() const
|
||||
{
|
||||
bool supports_gen2 = false;
|
||||
|
||||
supports_gen2 = (device_num == 0x00)
|
||||
&& (product_id == 0x5702 || product_id==0x5711 || product_id==0x8950)
|
||||
&& (report.support_cmd_flag & 0x01)
|
||||
&& (report.strip_detect == 0x01);
|
||||
|
||||
return supports_gen2;
|
||||
}
|
||||
|
||||
std::vector<Gen2StripInfo> RGBFusion2USBController::ExportGen2Strips() const
|
||||
{
|
||||
size_t count = (product_id == 0x5711) ? 4u : 2u;
|
||||
std::vector<Gen2StripInfo> out;
|
||||
out.reserve(count);
|
||||
for(size_t i = 0; i < count; ++i)
|
||||
{
|
||||
out.push_back(g2_strip_info[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Scan Headers for Gen2 Devices |
|
||||
\*---------------------------------------------------------*/
|
||||
bool RGBFusion2USBController::ScanGen2Strips()
|
||||
{
|
||||
for(unsigned i = 0; i < 4; ++i)
|
||||
{
|
||||
if(g2_strip_info[i].LedsOfStrip.capacity() < 15)
|
||||
{
|
||||
g2_strip_info[i].LedsOfStrip.reserve(15);
|
||||
}
|
||||
g2_strip_info[i].numStrip = 0;
|
||||
g2_strip_info[i].totalLeds = 0;
|
||||
g2_strip_info[i].LedsOfStrip.resize(0);
|
||||
}
|
||||
|
||||
const unsigned int hdr_lim = (product_id == 0x5711) ? 4u : 2u;
|
||||
|
||||
for(unsigned int slot = 0; slot < hdr_lim; ++slot)
|
||||
{
|
||||
static constexpr uint8_t delta[4] = {4, 5, 0, 1};
|
||||
uint8_t scan_cmd = static_cast<uint8_t>(GEN2_LED_BASE_SCAN + delta[slot]);
|
||||
uint8_t info_cmd = static_cast<uint8_t>(scan_cmd + 2);
|
||||
|
||||
if(!SendCCReport(scan_cmd, 0x00, 0x00))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(700));
|
||||
|
||||
if(!SendCCReport(info_cmd, 0x00, 0x00))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char feature_buf[64] = {0};
|
||||
feature_buf[0] = report_id;
|
||||
int recv_len = hid_get_feature_report(dev, feature_buf, sizeof(feature_buf));
|
||||
if(recv_len < 64)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int seg_count = static_cast<int>(feature_buf[1]);
|
||||
if(seg_count < 0)
|
||||
{
|
||||
seg_count = 0;
|
||||
}
|
||||
if(seg_count > 15)
|
||||
{
|
||||
seg_count = 15;
|
||||
}
|
||||
Gen2StripInfo& dst = g2_strip_info[slot];
|
||||
dst.numStrip = static_cast<uint8_t>(seg_count);
|
||||
dst.LedsOfStrip.resize(static_cast<size_t>(seg_count));
|
||||
|
||||
uint32_t total_leds = 0;
|
||||
const int counts_base = 2;
|
||||
|
||||
for(int k = 0; k < seg_count; ++k)
|
||||
{
|
||||
const int off = counts_base + (k * 2);
|
||||
uint16_t lo = static_cast<uint16_t>(feature_buf[off + 0]);
|
||||
uint16_t hi = static_cast<uint16_t>(feature_buf[off + 1]);
|
||||
uint16_t cnt = static_cast<uint16_t>(lo | (hi << 8));
|
||||
|
||||
dst.LedsOfStrip[static_cast<size_t>(k)] = cnt;
|
||||
total_leds += cnt;
|
||||
}
|
||||
|
||||
dst.totalLeds = total_leds;
|
||||
|
||||
SetLedCount(0, 0, 0, 0);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
SaveLEDState(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
|
||||
#define FUSION2_USB_BUFFER_SIZE 64
|
||||
|
||||
/*--------------------------------------------------------*\
|
||||
| Gen2 scan/info opcode base |
|
||||
\*--------------------------------------------------------*/
|
||||
#define GEN2_LED_BASE_SCAN 0x38
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Effects mode list |
|
||||
\*---------------------------------------------------------*/
|
||||
@@ -83,6 +88,16 @@ struct EncodedCalibration
|
||||
std::string mainboard;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| High level struct to contain Gen2 Header Data |
|
||||
\*---------------------------------------------------------*/
|
||||
struct Gen2StripInfo
|
||||
{
|
||||
uint8_t numStrip = 0;
|
||||
std::vector<uint16_t> LedsOfStrip;
|
||||
uint32_t totalLeds = 0;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
@@ -321,6 +336,8 @@ public:
|
||||
void SetLEDEffect(int led, int mode, unsigned int speed, unsigned char brightness, bool random, uint32_t* color);
|
||||
bool SetStripBuiltinEffectState(int hdr, bool enable);
|
||||
void SetStripColors(unsigned int hdr, RGBColor * colors, unsigned int num_colors, int single_led = -1);
|
||||
bool SupportsGen2() const;
|
||||
bool ScanGen2Strips();
|
||||
|
||||
EncodedCalibration GetCalibration(bool refresh_from_hw = false);
|
||||
std::string GetDeviceName();
|
||||
@@ -330,6 +347,8 @@ public:
|
||||
std::string GetFWVersion();
|
||||
uint16_t GetProductID();
|
||||
std::string GetSerial();
|
||||
std::vector<Gen2StripInfo> ExportGen2Strips() const;
|
||||
Gen2StripInfo g2_strip_info[4];
|
||||
|
||||
private:
|
||||
std::string DecodeCalibrationBuffer(uint32_t value) const;
|
||||
@@ -345,7 +364,7 @@ private:
|
||||
int SendPacket(unsigned char* packet);
|
||||
|
||||
hid_device* dev;
|
||||
int device_num;
|
||||
uint8_t device_num;
|
||||
uint16_t product_id;
|
||||
uint32_t effect_zone_mask = 0;
|
||||
int mode;
|
||||
@@ -356,7 +375,7 @@ private:
|
||||
std::string location;
|
||||
std::string version;
|
||||
std::string chip_id;
|
||||
int effect_disabled = 0;
|
||||
int effect_disabled = -1;
|
||||
int report_id = 0xCC;
|
||||
bool report_loaded = false;
|
||||
bool cali_loaded = false;
|
||||
|
||||
+197
-59
@@ -25,7 +25,7 @@
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectGigabyteRGBFusion2USBControllers
|
||||
@comment The Fusion 2 USB controller applies to most AMD and
|
||||
Intel mainboards from the x570 and z390 chipsets onwards.
|
||||
Intel mainboards from the X570 and z390 chipsets onwards.
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController* controller_ptr, std::string detector)
|
||||
@@ -39,8 +39,10 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
version = controller->GetFWVersion();
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerial();
|
||||
product_id = controller->GetProductID();
|
||||
device_num = controller->GetDeviceNum();
|
||||
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0xFFFF;
|
||||
@@ -206,6 +208,13 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
|
||||
RGBController_RGBFusion2USB::~RGBController_RGBFusion2USB()
|
||||
{
|
||||
// Free any zones we allocated for the per-instance layout
|
||||
for(gb_fusion2_zone* z : allocated_zones)
|
||||
{
|
||||
delete z;
|
||||
}
|
||||
allocated_zones.clear();
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
@@ -214,94 +223,125 @@ RGBController_RGBFusion2USB::~RGBController_RGBFusion2USB()
|
||||
\*---------------------------------------------------------*/
|
||||
void RGBController_RGBFusion2USB::Init_Controller()
|
||||
{
|
||||
const std::string SectionCustom = "CustomLayout";
|
||||
|
||||
const gb_fusion2_device* src_layout = gb_fusion2_device_list[device_index];
|
||||
const std::string SectionGen2 = "Gigabyte-Gen2-ARGB";
|
||||
const std::string SectionCustomBase = "CustomLayout";
|
||||
const std::string SectionCustom = SectionCustomBase + std::to_string(device_num);
|
||||
const std::string SectionCalibration = "Calibration";
|
||||
RvrseLedHeaders ReverseLedLookup = reverse_map(LedLookup);
|
||||
SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager();
|
||||
nlohmann::json device_settings = settings_manager->GetSettings(detector_name);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create the custom layout from the generic_device |
|
||||
| Checks for Gen2 support and adds flag to json. |
|
||||
\*---------------------------------------------------------*/
|
||||
gb_fusion2_device* layout = const_cast<gb_fusion2_device*>(gb_fusion2_device_list[device_index]);
|
||||
if(controller->SupportsGen2())
|
||||
{
|
||||
if(!device_settings.contains(SectionGen2))
|
||||
{
|
||||
device_settings[SectionGen2]["Enabled"] = false;
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
|
||||
supports_gen2 = device_settings[SectionGen2]["Enabled"];
|
||||
|
||||
if(supports_gen2)
|
||||
{
|
||||
controller->ScanGen2Strips();
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create the custom layout from the generic layout |
|
||||
\*---------------------------------------------------------*/
|
||||
switch(product_id)
|
||||
{
|
||||
case 0x8950:
|
||||
src_layout = gb_fusion2_device_list[device_index + 1];
|
||||
break;
|
||||
case 0x5711:
|
||||
src_layout = gb_fusion2_device_list[device_index + 2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!device_settings.contains(SectionCustom))
|
||||
{
|
||||
device_settings[SectionCustom]["Enabled"] = false;
|
||||
device_settings[SectionCustom]["Data"] = BuildCustomLayoutJson(layout, ReverseLedLookup);
|
||||
device_settings[SectionCustom]["Data"] = BuildCustomLayoutJson(src_layout, ReverseLedLookup);
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
|
||||
bool custom_layout = device_settings[SectionCustom]["Enabled"];
|
||||
|
||||
if(custom_layout)
|
||||
{
|
||||
LoadCustomLayoutFromJson(device_settings[SectionCustom]["Data"], LedLookup, layout);
|
||||
}
|
||||
|
||||
EncodedCalibration hw_cal = controller->GetCalibration(false);
|
||||
|
||||
if(!device_settings.contains(SectionCalibration))
|
||||
if(device_num == 0)
|
||||
{
|
||||
device_settings[SectionCalibration]["Enabled"] = false;
|
||||
device_settings[SectionCalibration]["Data"] = WriteCalJsonFrom(hw_cal);
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
nlohmann::json& cal_sec = device_settings[SectionCalibration];
|
||||
bool cal_enable = cal_sec.value("Enabled", false);
|
||||
|
||||
if(!cal_sec.contains("Data") || !cal_sec["Data"].is_object())
|
||||
if(!device_settings.contains(SectionCalibration))
|
||||
{
|
||||
cal_sec["Data"] = WriteCalJsonFrom(hw_cal);
|
||||
device_settings[SectionCalibration]["Enabled"] = false;
|
||||
device_settings[SectionCalibration]["Data"] = WriteCalJsonFrom(hw_cal);
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
nlohmann::json& cdata = cal_sec["Data"];
|
||||
FillMissingWith(cdata, hw_cal);
|
||||
nlohmann::json& cal_sec = device_settings[SectionCalibration];
|
||||
bool cal_enable = cal_sec.value("Enabled", false);
|
||||
|
||||
if(!cal_enable)
|
||||
if(!cal_sec.contains("Data") || !cal_sec["Data"].is_object())
|
||||
{
|
||||
cal_sec["Data"] = WriteCalJsonFrom(hw_cal);
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
if(cal_enable)
|
||||
{
|
||||
const nlohmann::json& cdata = cal_sec["Data"];
|
||||
|
||||
EncodedCalibration desired;
|
||||
desired.dled[0] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED1");
|
||||
desired.dled[1] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED2");
|
||||
desired.mainboard = GET_JSON_VAL_ELSE_OFF(cdata, "Mainboard");
|
||||
desired.spare[0] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare0");
|
||||
desired.spare[1] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare1");
|
||||
|
||||
if(controller->GetProductID() == 0x5711)
|
||||
{
|
||||
desired.dled[2] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED3");
|
||||
desired.dled[3] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED4");
|
||||
desired.spare[2] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare2");
|
||||
desired.spare[3] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare3");
|
||||
}
|
||||
else
|
||||
{
|
||||
desired.dled[2] = "OFF";
|
||||
desired.dled[3] = "OFF";
|
||||
desired.spare[2] = "OFF";
|
||||
desired.spare[3] = "OFF";
|
||||
nlohmann::json& cdata = cal_sec["Data"];
|
||||
FillMissingWith(cdata, hw_cal);
|
||||
|
||||
if(!cal_enable)
|
||||
{
|
||||
cal_sec["Data"] = WriteCalJsonFrom(hw_cal);
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
if(cal_enable)
|
||||
{
|
||||
const nlohmann::json& cdata = cal_sec["Data"];
|
||||
|
||||
EncodedCalibration desired;
|
||||
desired.dled[0] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED1");
|
||||
desired.dled[1] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED2");
|
||||
desired.mainboard = GET_JSON_VAL_ELSE_OFF(cdata, "Mainboard");
|
||||
desired.spare[0] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare0");
|
||||
desired.spare[1] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare1");
|
||||
|
||||
if(controller->GetProductID() == 0x5711)
|
||||
{
|
||||
desired.dled[2] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED3");
|
||||
desired.dled[3] = GET_JSON_VAL_ELSE_OFF(cdata, "HDR_D_LED4");
|
||||
desired.spare[2] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare2");
|
||||
desired.spare[3] = GET_JSON_VAL_ELSE_OFF(cdata, "Spare3");
|
||||
}
|
||||
else
|
||||
{
|
||||
desired.dled[2] = "OFF";
|
||||
desired.dled[3] = "OFF";
|
||||
desired.spare[2] = "OFF";
|
||||
desired.spare[3] = "OFF";
|
||||
}
|
||||
controller->SetCalibration(desired, false);
|
||||
}
|
||||
controller->SetCalibration(desired, false);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| When no match found the first entry (generic_device) will be used |
|
||||
| otherwise look up channel map based on device name |
|
||||
@@ -315,35 +355,81 @@ void RGBController_RGBFusion2USB::Init_Controller()
|
||||
\*-----------------------------------------------------------------*/
|
||||
for(unsigned int i = 0; i < GB_FUSION2_DEVICE_COUNT; i++)
|
||||
{
|
||||
if(gb_fusion2_device_list[i]->name == name)
|
||||
if(gb_fusion2_device_list[i]->name == name &&
|
||||
gb_fusion2_device_list[i]->device_num == device_num)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Set device ID |
|
||||
\*---------------------------------------------------------*/
|
||||
device_index = i;
|
||||
layout = const_cast<gb_fusion2_device*>(gb_fusion2_device_list[i]);
|
||||
src_layout = gb_fusion2_device_list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Creates per instance copy of layouts. |
|
||||
\*---------------------------------------------------------------------*/
|
||||
instance_layout.zones = &instance_zones;
|
||||
instance_layout.layout_id = src_layout->layout_id;
|
||||
instance_layout.device_num = src_layout->device_num;
|
||||
instance_layout.name = src_layout->name;
|
||||
|
||||
for(uint8_t zi = 0; zi < GB_FUSION2_ZONES_MAX; ++zi)
|
||||
{
|
||||
(*instance_layout.zones)[zi] = (*src_layout->zones)[zi];
|
||||
}
|
||||
|
||||
if(custom_layout)
|
||||
{
|
||||
LoadCustomLayoutFromJson(device_settings[SectionCustom]["Data"], LedLookup, &instance_layout);
|
||||
}
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Culls the mode support based on layout_id. |
|
||||
\*---------------------------------------------------------------------*/
|
||||
const uint32_t effect_mask = instance_layout.layout_id & GB_EFF_CORE_MASK;
|
||||
modes.erase(std::remove_if(modes.begin(), modes.end(),
|
||||
[effect_mask](const mode& m)
|
||||
{
|
||||
if(m.value == 0xFFFF /* Direct */) { return false; }
|
||||
if(m.value == EFFECT_STATIC) { return false; }
|
||||
|
||||
uint32_t bit = 0u;
|
||||
switch(m.value)
|
||||
{
|
||||
case EFFECT_PULSE: bit = GB_EFF_BREATH; break;
|
||||
case EFFECT_COLORCYCLE: bit = GB_EFF_CYCLE; break;
|
||||
case EFFECT_BLINKING: bit = GB_EFF_FLASH; break;
|
||||
case EFFECT_RANDOM: bit = GB_EFF_RANDOM; break;
|
||||
case EFFECT_WAVE: bit = GB_EFF_WAVE; break;
|
||||
case EFFECT_DFLASH: bit = GB_EFF_DFLASH; break;
|
||||
case EFFECT_WAVE1: bit = GB_EFF_WAVE1; break;
|
||||
case EFFECT_WAVE2: bit = GB_EFF_WAVE2; break;
|
||||
case EFFECT_WAVE3: bit = GB_EFF_WAVE1; break;
|
||||
case EFFECT_WAVE4: bit = GB_EFF_WAVE2; break;
|
||||
default: bit = 0u; break;
|
||||
}
|
||||
return (bit == 0u) || ((effect_mask & bit) == 0u);
|
||||
}),
|
||||
modes.end());
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Iterate through layout and process each zone |
|
||||
\*---------------------------------------------------------*/
|
||||
for(uint8_t zone_idx = 0; zone_idx < GB_FUSION2_ZONES_MAX; zone_idx++)
|
||||
{
|
||||
if(!layout->zones[0][zone_idx])
|
||||
if(!(*instance_layout.zones)[zone_idx])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const gb_fusion2_zone* zone_at_idx = layout->zones[0][zone_idx];
|
||||
const gb_fusion2_zone* zone_at_idx = (*instance_layout.zones)[zone_idx];
|
||||
|
||||
zone new_zone;
|
||||
new_zone.name = zone_at_idx->name;
|
||||
new_zone.leds_min = zone_at_idx->leds_min;
|
||||
new_zone.leds_max = zone_at_idx->leds_max;
|
||||
new_zone.leds_count = new_zone.leds_min;
|
||||
new_zone.type = (new_zone.leds_min == new_zone.leds_max) ? ZONE_TYPE_SINGLE : ZONE_TYPE_LINEAR;
|
||||
new_zone.type = ((new_zone.leds_min == 1) && (new_zone.leds_max == 1)) ? ZONE_TYPE_SINGLE : ZONE_TYPE_LINEAR;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.emplace_back(new_zone);
|
||||
}
|
||||
@@ -363,17 +449,68 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
| Set up zones (Fixed so as to not spam the controller) |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
std::vector<Gen2StripInfo> strips = controller->ExportGen2Strips();
|
||||
|
||||
for(uint8_t zone_idx = 0; zone_idx < GB_FUSION2_ZONES_MAX; zone_idx++)
|
||||
{
|
||||
const gb_fusion2_zone* zone_at_idx = gb_fusion2_device_list[device_index]->zones[0][zone_idx];
|
||||
const gb_fusion2_zone* zone_at_idx = (*instance_layout.zones)[zone_idx];
|
||||
if(!zone_at_idx)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool single_zone = (zone_at_idx->leds_min == zone_at_idx->leds_max);
|
||||
bool single_zone = ((zone_at_idx->leds_min == 1) && (zone_at_idx->leds_max == 1));
|
||||
|
||||
if(!single_zone)
|
||||
{
|
||||
if(supports_gen2)
|
||||
{
|
||||
int slot = 0;
|
||||
switch(zone_at_idx->idx)
|
||||
{
|
||||
case LED4:
|
||||
case HDR_D_LED2:
|
||||
slot = 1;
|
||||
break;
|
||||
case HDR_D_LED3:
|
||||
slot = 2;
|
||||
break;
|
||||
case HDR_D_LED4:
|
||||
slot = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(slot >= 0 && static_cast<size_t>(slot) < strips.size())
|
||||
{
|
||||
const Gen2StripInfo& info = strips[static_cast<size_t>(slot)];
|
||||
if(info.totalLeds > 0u)
|
||||
{
|
||||
zones[zone_idx].leds_count = static_cast<unsigned int>(info.totalLeds);
|
||||
zones[zone_idx].leds_min = static_cast<unsigned int>(info.totalLeds);
|
||||
zones[zone_idx].leds_max = static_cast<unsigned int>(info.totalLeds);
|
||||
zones[zone_idx].segments.clear();
|
||||
|
||||
zones[zone_idx].segments.reserve(info.LedsOfStrip.size());
|
||||
unsigned int offset = 0;
|
||||
for(size_t si = 0; si < info.LedsOfStrip.size(); ++si)
|
||||
{
|
||||
const uint16_t cnt = info.LedsOfStrip[si];
|
||||
if(cnt == 0) continue;
|
||||
|
||||
segment seg;
|
||||
seg.name = std::string("Segment ") + std::to_string(si);
|
||||
seg.type = ZONE_TYPE_LINEAR;
|
||||
seg.start_idx = offset;
|
||||
seg.leds_count = static_cast<unsigned int>(cnt);
|
||||
|
||||
zones[zone_idx].segments.push_back(seg);
|
||||
offset += static_cast<unsigned int>(cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(zone_at_idx->idx)
|
||||
{
|
||||
case LED4:
|
||||
@@ -826,6 +963,7 @@ void RGBController_RGBFusion2USB::LoadCustomLayoutFromJson(
|
||||
&& new_zone->idx <= GB_FUSION2_LED_IDX::LED11)
|
||||
{
|
||||
layout->zones[0][zone_idx] = new_zone;
|
||||
allocated_zones.push_back(new_zone);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -62,17 +62,26 @@ private:
|
||||
std::string detector_name;
|
||||
|
||||
RGBFusion2USBController* controller;
|
||||
int device_num;
|
||||
uint8_t device_num;
|
||||
RGBColor null_color = 0;
|
||||
bool supports_gen2 = 0;
|
||||
/*---------------------------------------------------------*\
|
||||
| The intial value of device_index should point to the |
|
||||
| layout for the generic_device |
|
||||
\*---------------------------------------------------------*/
|
||||
uint32_t device_index = 0;
|
||||
|
||||
uint16_t product_id = 0;
|
||||
uint32_t effects_mask = 0;
|
||||
void Init_Controller();
|
||||
int GetLED_Zone(int led_idx);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Per instance layout lookup tables. |
|
||||
\*---------------------------------------------------------*/
|
||||
gb_fusion2_device instance_layout{};
|
||||
gb_fusion2_layout instance_zones{};
|
||||
std::vector<gb_fusion2_zone*> allocated_zones;
|
||||
|
||||
nlohmann::json WriteCalJsonFrom(
|
||||
const EncodedCalibration& src);
|
||||
void FillMissingWith(
|
||||
|
||||
@@ -20,6 +20,8 @@ static std::map<std::string, unsigned int> govee_led_counts
|
||||
{
|
||||
{ "H619A", 20 },
|
||||
{ "H70B1", 20 },
|
||||
{ "H612F", 12 },
|
||||
{ "H607C", 174 },
|
||||
};
|
||||
|
||||
RGBController_Govee::RGBController_Govee(GoveeController* controller_ptr)
|
||||
|
||||
@@ -70,6 +70,12 @@ void MSILaptopController::SetLEDs(std::vector<led> leds, std::vector<RGBColor> c
|
||||
buf[0x01] = MSI_LAPTOP_COMMAND;
|
||||
buf[0x03] = (type == MSI_LAPTOP_KLC) ? MSI_LAPTOP_KLC_PACKET_ID : MSI_LAPTOP_ALC_PACKET_ID;
|
||||
|
||||
// Fill unused LED IDs with 0xFF so they are ignored by the controller
|
||||
for(int i = 0; i < (MSI_LAPTOP_PACKET_SIZE - MSI_LAPTOP_PAYLOAD_OFFSET) / 4; i++)
|
||||
{
|
||||
buf[MSI_LAPTOP_PAYLOAD_OFFSET + (i * 4)] = 0xFF;
|
||||
}
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
|
||||
{
|
||||
unsigned int offset = MSI_LAPTOP_PAYLOAD_OFFSET + (led_idx * 4);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define NA 0xFFFFFFFF
|
||||
#define MSI_LAPTOP_KLC_MATRIX_HEIGHT 6
|
||||
#define MSI_LAPTOP_KLC_MATRIX_WIDTH 23
|
||||
#define MSI_LAPTOP_ALC_LIGHTBAR_LEDS 5
|
||||
#define MSI_LAPTOP_ALC_LIGHTBAR_LEDS 3
|
||||
|
||||
static const msi_laptop_led msi_raider_a18_klc_leds[] =
|
||||
{
|
||||
@@ -140,14 +140,24 @@ static unsigned int msi_raider_a18_klc_matrix_map[MSI_LAPTOP_KLC_MATRIX_HEIGHT][
|
||||
{ 90, 93, 92, NA, NA, NA, 38, NA, NA, NA,101, 94, 95, NA, 69, 70, 68, NA, 87, NA, 88, NA, NA },
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Note on Raider A18 HX ALC (Lightbar) LED mappings: |
|
||||
| Initial reverse engineering packet captures showed 6 zones|
|
||||
| being updated (indexes 0x00 to 0x05). |
|
||||
| However, indexes 0x04 (L4) and 0x05 (L5) are "dummy" zones|
|
||||
| on this specific model and do not correspond to physical |
|
||||
| LEDs. To avoid user confusion, they are omitted from the |
|
||||
| UI profile here. |
|
||||
| The SetLEDs function handles zero-padding the unused |
|
||||
| payload slots with 0xFF so that omitting these zones |
|
||||
| doesn't accidentally overwrite the 0x00 index (L1). |
|
||||
\*---------------------------------------------------------*/
|
||||
static const msi_laptop_led msi_raider_a18_alc_leds[] =
|
||||
{
|
||||
{ "Lightbar 1", 0x00 },
|
||||
{ "Lightbar 2", 0x01 },
|
||||
{ "Lightbar 3", 0x02 },
|
||||
{ "Lightbar 4", 0x03 },
|
||||
{ "Lightbar 5", 0x04 },
|
||||
{ "Logo", 0x05 },
|
||||
{ "Logo", 0x03 },
|
||||
};
|
||||
|
||||
static const MSILaptopModel msi_laptop_models[] =
|
||||
@@ -220,6 +230,6 @@ void DetectMSILaptop(hid_device_info* info, const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_I("MSI Laptop Keyboard", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_KLC_PID, 0);
|
||||
REGISTER_HID_DETECTOR("MSI Laptop Keyboard", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_KLC_PID);
|
||||
REGISTER_HID_DETECTOR_I("MSI Laptop Lightbar", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_ALC_PID, 0);
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| |
|
||||
| Andy Herbert 2026 June 4 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
#include "MSIMonitorController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
MSIMonitorController::MSIMonitorController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
MSIMonitorController::~MSIMonitorController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string MSIMonitorController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string MSIMonitorController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string MSIMonitorController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void MSIMonitorController::Set(uint8_t mode_value, const std::vector<RGBColor> colors, uint8_t last_bit)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Prepare color data |
|
||||
\*---------------------------------------------------------*/
|
||||
uint8_t data[MSI_MONITOR_PACKET_SIZE];
|
||||
memset(data, 0x00, MSI_MONITOR_PACKET_SIZE);
|
||||
|
||||
unsigned int offset = 0;
|
||||
|
||||
data[offset++] = 0x71;
|
||||
data[offset++] = 0x01;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
data[offset++] = 0x00;
|
||||
}
|
||||
|
||||
data[offset++] = 0x01;
|
||||
data[offset++] = 0x64;
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
data[offset++] = 0x00;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| put mode_value |
|
||||
\*---------------------------------------------------------*/
|
||||
data[offset++] = mode_value;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
data[offset++] = 0x00;
|
||||
}
|
||||
data[offset++] = 0x01;
|
||||
data[offset++] = 0x64;
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
data[offset++] = 0x00;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*\
|
||||
| this data looks like placeholder for additional LEDs in other monitors |
|
||||
\*-----------------------------------------------------------------------*/
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
data[offset++] = 0xff;
|
||||
data[offset++] = 0x00;
|
||||
data[offset++] = 0x00;
|
||||
}
|
||||
|
||||
//RGB values begin
|
||||
for(const RGBColor color: colors)
|
||||
{
|
||||
data[offset++] = RGBGetRValue(color);
|
||||
data[offset++] = RGBGetGValue(color);
|
||||
data[offset++] = RGBGetBValue(color);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------*\
|
||||
| last bit is probably a write to device bit- 0x01 saves to device, 0x00 doesn't. |
|
||||
| For direct mode, bit is set to 0x00, otherwise lights will flicker |
|
||||
\*-------------------------------------------------------------------------------*/
|
||||
|
||||
data[offset++] = last_bit;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Send the data (1 packet) |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
hid_send_feature_report(dev, data, MSI_MONITOR_PACKET_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| |
|
||||
| Andy Herbert 2026 June 1 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define MSI_MONITOR_LEDS 9
|
||||
#define MSI_MONITOR_PACKET_SIZE 78
|
||||
|
||||
enum
|
||||
{
|
||||
MSI_MONITOR_OFF_MODE_VALUE = 0x00,
|
||||
MSI_MONITOR_STATIC_MODE_VALUE = 0x01,
|
||||
MSI_MONITOR_BREATHING_MODE_VALUE = 0x02,
|
||||
MSI_MONITOR_FLASHING_MODE_VALUE = 0x03,
|
||||
MSI_MONITOR_LIGHTNING_MODE_VALUE = 0x05,
|
||||
MSI_MONITOR_MARQUEE_MODE_VALUE = 0x06,
|
||||
MSI_MONITOR_METEOR_MODE_VALUE = 0x08,
|
||||
MSI_MONITOR_RAINBOW_MODE_VALUE = 0x1A,
|
||||
MSI_MONITOR_RANDOM_MODE_VALUE = 0x1F
|
||||
};
|
||||
|
||||
class MSIMonitorController
|
||||
{
|
||||
public:
|
||||
MSIMonitorController(hid_device *dev_handle, const hid_device_info &info, std::string dev_name);
|
||||
~MSIMonitorController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetFirmwareVersion();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void Set(uint8_t mode_value, const std::vector<RGBColor> colors, uint8_t last_bit);
|
||||
|
||||
private:
|
||||
hid_device *dev;
|
||||
std::string description;
|
||||
std::string location;
|
||||
std::string name;
|
||||
std::string version;
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MSIKeyboardControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for MSI monitor (MSI Gaming Controller) |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "Detector.h"
|
||||
#include "MSIMonitorController.h"
|
||||
#include "RGBController_MSIMonitor.h"
|
||||
|
||||
#define MSI_USB_VID 0x1462
|
||||
#define MSI_USB_PID 0x3FA4
|
||||
|
||||
/*----------------------------------------------------------*\
|
||||
| |
|
||||
| DetectMSIMonitorController |
|
||||
| |
|
||||
| Detect MSI monitor and maybe others |
|
||||
| |
|
||||
\*----------------------------------------------------------*/
|
||||
|
||||
static void DetectMSIMonitorController(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
MSIMonitorController* controller = new MSIMonitorController(dev, *info, name);
|
||||
RGBController_MSIMonitor* rgb_controller = new RGBController_MSIMonitor(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("MSI Monitor (Gaming Controller)", DetectMSIMonitorController, MSI_USB_VID, MSI_USB_PID, 0, 0x01, 0);
|
||||
@@ -0,0 +1,171 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| |
|
||||
| Andy Herbert 2026 June 1 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "RGBController_MSIMonitor.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name MSIMonitor
|
||||
@category Accessory
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectMSIMonitorController
|
||||
@comment Developed with MSI MAG272CQR
|
||||
\*-------------------------------------------------------------------*/
|
||||
RGBController_MSIMonitor::RGBController_MSIMonitor(MSIMonitorController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "MSI";
|
||||
type = DEVICE_TYPE_MONITOR;
|
||||
description = "MSI Monitor (Gaming Controller)";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = MSI_MONITOR_STATIC_MODE_VALUE;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = MSI_MONITOR_STATIC_MODE_VALUE;
|
||||
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Static.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Static);
|
||||
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = MSI_MONITOR_BREATHING_MODE_VALUE;
|
||||
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Breathing.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Flashing;
|
||||
Flashing.name = "Flashing";
|
||||
Flashing.value = MSI_MONITOR_FLASHING_MODE_VALUE;
|
||||
Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Flashing.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Flashing);
|
||||
|
||||
mode Lightning;
|
||||
Lightning.name = "Lightning";
|
||||
Lightning.value = MSI_MONITOR_LIGHTNING_MODE_VALUE;
|
||||
Lightning.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Lightning.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Lightning);
|
||||
|
||||
mode Marquee;
|
||||
Marquee.name = "Marquee";
|
||||
Marquee.value = MSI_MONITOR_MARQUEE_MODE_VALUE;
|
||||
Marquee.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Marquee.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Marquee);
|
||||
|
||||
mode Meteor;
|
||||
Meteor.name = "Meteor";
|
||||
Meteor.value = MSI_MONITOR_METEOR_MODE_VALUE;
|
||||
Meteor.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Meteor.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Meteor);
|
||||
|
||||
mode Rainbow;
|
||||
Rainbow.name = "Rainbow";
|
||||
Rainbow.value = MSI_MONITOR_RAINBOW_MODE_VALUE;
|
||||
Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Rainbow.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Rainbow);
|
||||
|
||||
mode Random;
|
||||
Random.name = "Random";
|
||||
Random.value = MSI_MONITOR_RANDOM_MODE_VALUE;
|
||||
Random.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Random.color_mode = MODE_COLORS_RANDOM;
|
||||
modes.push_back(Random);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = MSI_MONITOR_OFF_MODE_VALUE;
|
||||
Off.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_MSIMonitor::~RGBController_MSIMonitor()
|
||||
{
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
|
||||
new_zone.name = "Rear";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = 9;
|
||||
new_zone.leds_max = 9;
|
||||
new_zone.leds_count = 9;
|
||||
new_zone.matrix_map = nullptr;
|
||||
|
||||
zones.emplace_back(new_zone);
|
||||
|
||||
for(unsigned int i = 0 ; i < 9; i ++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "LED " + std::to_string(i + 1);
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor::DeviceUpdateLEDs()
|
||||
{
|
||||
last_update_time = std::chrono::steady_clock::now();
|
||||
controller->Set(modes[active_mode].value, colors, active_mode == 0 ? 0x00 : 0x01);
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor::DeviceUpdateMode()
|
||||
{
|
||||
controller->Set(modes[active_mode].value, colors, 0x01);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| |
|
||||
| Andy Herbert 2026 May 16 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "RGBController.h"
|
||||
#include "MSIMonitorController.h"
|
||||
|
||||
class RGBController_MSIMonitor : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_MSIMonitor(MSIMonitorController* controller_ptr);
|
||||
~RGBController_MSIMonitor();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
MSIMonitorController* controller;
|
||||
std::thread* keepalive_thread;
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
|
||||
|
||||
void KeepaliveThread();
|
||||
};
|
||||
@@ -0,0 +1,523 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RealtekARGB.cpp |
|
||||
| |
|
||||
| RGBController for Realtek USB ARGB ICs |
|
||||
| |
|
||||
| Jerry Fan (JerryFan0612) 13 Mar 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RealtekARGB.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Realtek ARGB Device
|
||||
@category LEDStrip
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :rotating_light:
|
||||
@effects :white_check_mark:
|
||||
@detectors RealtekARGBControllerDetect
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RealtekARGB::RGBController_RealtekARGB(RealtekARGBController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
name = controller_ptr->get_dev_name();
|
||||
vendor = controller_ptr->get_manu_name();
|
||||
location = controller_ptr->get_dev_loc();
|
||||
serial = controller_ptr->get_sn();
|
||||
version = controller_ptr->get_fw_ver();
|
||||
description = vendor + "ARGB Device";
|
||||
type = DEVICE_TYPE_LEDSTRIP;
|
||||
std::fill(std::begin(ready_to_reboot), std::end(ready_to_reboot), false);
|
||||
|
||||
SetupModes();
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::SetupModes()
|
||||
{
|
||||
int brightness = controller->get_argb_brightness(0) >> 8;
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = REALTEK_ARGB_EFF_NULL;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
Direct.brightness_min = 0;
|
||||
Direct.brightness_max = 255;
|
||||
Direct.brightness = brightness;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = REALTEK_ARGB_EFF_ALWAYS_ON;
|
||||
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Static.colors_min = 1;
|
||||
Static.colors_max = 1;
|
||||
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Static.colors.resize(1);
|
||||
Static.brightness_min = 0;
|
||||
Static.brightness_max = 255;
|
||||
Static.brightness = brightness;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Blink;
|
||||
Blink.name = "Blink";
|
||||
Blink.value = REALTEK_ARGB_EFF_BLINK;
|
||||
Blink.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Blink.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
Blink.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
Blink.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
Blink.colors_min = 1;
|
||||
Blink.colors_max = 2;
|
||||
Blink.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Blink.colors.resize(2);
|
||||
Blink.brightness_min = 0;
|
||||
Blink.brightness_max = 255;
|
||||
Blink.brightness = brightness;
|
||||
modes.push_back(Blink);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = REALTEK_ARGB_EFF_BREATH;
|
||||
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Breathing.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
Breathing.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
Breathing.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
Breathing.colors_min = 1;
|
||||
Breathing.colors_max = 2;
|
||||
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Breathing.colors.resize(2);
|
||||
Breathing.brightness_min = 0;
|
||||
Breathing.brightness_max = 255;
|
||||
Breathing.brightness = brightness;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Spectrum;
|
||||
Spectrum.name = "Spectrum";
|
||||
Spectrum.value = REALTEK_ARGB_EFF_SPECTRUM;
|
||||
Spectrum.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Spectrum.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
Spectrum.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
Spectrum.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
Spectrum.color_mode = MODE_COLORS_NONE;
|
||||
Spectrum.brightness_min = 0;
|
||||
Spectrum.brightness_max = 255;
|
||||
Spectrum.brightness = brightness;
|
||||
modes.push_back(Spectrum);
|
||||
|
||||
mode Scroll;
|
||||
Scroll.name = "Scroll";
|
||||
Scroll.value = REALTEK_ARGB_EFF_SCROLL;
|
||||
Scroll.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Scroll.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
Scroll.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
Scroll.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
Scroll.colors_min = 1;
|
||||
Scroll.colors_max = 2;
|
||||
Scroll.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Scroll.colors.resize(2);
|
||||
Scroll.brightness_min = 0;
|
||||
Scroll.brightness_max = 255;
|
||||
Scroll.brightness = brightness;
|
||||
modes.push_back(Scroll);
|
||||
|
||||
mode RainbowScroll;
|
||||
RainbowScroll.name = "Rainbow Scroll";
|
||||
RainbowScroll.value = REALTEK_ARGB_EFF_RAINBOW_SCROLL;
|
||||
RainbowScroll.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
RainbowScroll.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
RainbowScroll.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
RainbowScroll.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
RainbowScroll.color_mode = MODE_COLORS_NONE;
|
||||
RainbowScroll.brightness_min = 0;
|
||||
RainbowScroll.brightness_max = 255;
|
||||
RainbowScroll.brightness = brightness;
|
||||
modes.push_back(RainbowScroll);
|
||||
|
||||
mode RunningWater;
|
||||
RunningWater.name = "Running Water";
|
||||
RunningWater.value = REALTEK_ARGB_EFF_RUNNING_WATER;
|
||||
RunningWater.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
RunningWater.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
RunningWater.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
RunningWater.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
RunningWater.colors_min = 1;
|
||||
RunningWater.colors_max = 2;
|
||||
RunningWater.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
RunningWater.colors.resize(2);
|
||||
RunningWater.brightness_min = 0;
|
||||
RunningWater.brightness_max = 255;
|
||||
RunningWater.brightness = brightness;
|
||||
modes.push_back(RunningWater);
|
||||
|
||||
mode Sliding;
|
||||
Sliding.name = "Sliding";
|
||||
Sliding.value = REALTEK_ARGB_EFF_SLIDING;
|
||||
Sliding.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
|
||||
Sliding.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
Sliding.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
Sliding.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
Sliding.colors_min = 1;
|
||||
Sliding.colors_max = 2;
|
||||
Sliding.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Sliding.colors.resize(2);
|
||||
Sliding.brightness_min = 0;
|
||||
Sliding.brightness_max = 255;
|
||||
Sliding.brightness = brightness;
|
||||
modes.push_back(Sliding);
|
||||
|
||||
mode WideSliding;
|
||||
WideSliding.name = "Wide Sliding";
|
||||
WideSliding.value = REALTEK_ARGB_EFF_WIDE_SLIDING;
|
||||
WideSliding.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
|
||||
WideSliding.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
WideSliding.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
WideSliding.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
WideSliding.colors_min = 1;
|
||||
WideSliding.colors_max = 2;
|
||||
WideSliding.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
WideSliding.colors.resize(2);
|
||||
WideSliding.brightness_min = 0;
|
||||
WideSliding.brightness_max = 255;
|
||||
WideSliding.brightness = brightness;
|
||||
modes.push_back(WideSliding);
|
||||
|
||||
mode RainbowSliding;
|
||||
RainbowSliding.name = "Rainbow Sliding";
|
||||
RainbowSliding.value = REALTEK_ARGB_EFF_RAINBOW_SLIDING;
|
||||
RainbowSliding.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
|
||||
RainbowSliding.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
RainbowSliding.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
RainbowSliding.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
RainbowSliding.color_mode = MODE_COLORS_NONE;
|
||||
RainbowSliding.brightness_min = 0;
|
||||
RainbowSliding.brightness_max = 255;
|
||||
RainbowSliding.brightness = brightness;
|
||||
modes.push_back(RainbowSliding);
|
||||
|
||||
mode RainbowFadeSliding;
|
||||
RainbowFadeSliding.name = "Rainbow Fade Sliding";
|
||||
RainbowFadeSliding.value = REALTEK_ARGB_EFF_RAINBOW_FADE_SLIDING;
|
||||
RainbowFadeSliding.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
RainbowFadeSliding.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
RainbowFadeSliding.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
RainbowFadeSliding.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
RainbowFadeSliding.color_mode = MODE_COLORS_NONE;
|
||||
RainbowFadeSliding.brightness_min = 0;
|
||||
RainbowFadeSliding.brightness_max = 255;
|
||||
RainbowFadeSliding.brightness = brightness;
|
||||
modes.push_back(RainbowFadeSliding);
|
||||
|
||||
mode NewtonCradle;
|
||||
NewtonCradle.name = "Newton Cradle";
|
||||
NewtonCradle.value = REALTEK_ARGB_EFF_NEWTON_CRADLE;
|
||||
NewtonCradle.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
NewtonCradle.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
NewtonCradle.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
NewtonCradle.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
NewtonCradle.colors_min = 1;
|
||||
NewtonCradle.colors_max = 2;
|
||||
NewtonCradle.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
NewtonCradle.colors.resize(2);
|
||||
NewtonCradle.brightness_min = 0;
|
||||
NewtonCradle.brightness_max = 255;
|
||||
NewtonCradle.brightness = brightness;
|
||||
modes.push_back(NewtonCradle);
|
||||
|
||||
mode Meteor;
|
||||
Meteor.name = "Meteor";
|
||||
Meteor.value = REALTEK_ARGB_EFF_METEOR;
|
||||
Meteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Meteor.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
Meteor.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
Meteor.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
Meteor.colors_min = 1;
|
||||
Meteor.colors_max = 2;
|
||||
Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Meteor.colors.resize(2);
|
||||
Meteor.brightness_min = 0;
|
||||
Meteor.brightness_max = 255;
|
||||
Meteor.brightness = brightness;
|
||||
modes.push_back(Meteor);
|
||||
|
||||
mode ZigZag;
|
||||
ZigZag.name = "ZigZag";
|
||||
ZigZag.value = REALTEK_ARGB_EFF_ZIGZAG;
|
||||
ZigZag.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_RANDOM_COLOR;
|
||||
ZigZag.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
ZigZag.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
ZigZag.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
ZigZag.colors_min = 1;
|
||||
ZigZag.colors_max = 2;
|
||||
ZigZag.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
ZigZag.colors.resize(2);
|
||||
ZigZag.brightness_min = 0;
|
||||
ZigZag.brightness_max = 255;
|
||||
ZigZag.brightness = brightness;
|
||||
modes.push_back(ZigZag);
|
||||
|
||||
mode StarryNight;
|
||||
StarryNight.name = "Starry Night";
|
||||
StarryNight.value = REALTEK_ARGB_EFF_STARRY_NIGHT;
|
||||
StarryNight.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_RANDOM_COLOR;
|
||||
StarryNight.speed_min = REALTEK_ARGB_SPEED_MIN;
|
||||
StarryNight.speed_max = REALTEK_ARGB_SPEED_MAX;
|
||||
StarryNight.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
StarryNight.colors_min = 1;
|
||||
StarryNight.colors_max = 1;
|
||||
StarryNight.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
StarryNight.colors.resize(1);
|
||||
StarryNight.brightness_min = 0;
|
||||
StarryNight.brightness_max = 255;
|
||||
StarryNight.brightness = brightness;
|
||||
modes.push_back(StarryNight);
|
||||
|
||||
mode Stack;
|
||||
Stack.name = "Stack";
|
||||
Stack.value = REALTEK_ARGB_EFF_STACK;
|
||||
Stack.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Stack.colors_min = 1;
|
||||
Stack.colors_max = 2;
|
||||
Stack.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Stack.colors.resize(2);
|
||||
Stack.brightness_min = 0;
|
||||
Stack.brightness_max = 255;
|
||||
Stack.brightness = brightness;
|
||||
modes.push_back(Stack);
|
||||
}
|
||||
|
||||
RGBController_RealtekARGB::~RGBController_RealtekARGB()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::SetupZones()
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Only set LED count on the first run |
|
||||
\*-------------------------------------------------*/
|
||||
bool first_run = false;
|
||||
int idx = 0;
|
||||
int argb_num = 0;
|
||||
int fix_grps = 0;
|
||||
int num_fixgrp = 0;
|
||||
int argb_num_fixgrp = 0;
|
||||
|
||||
if(zones.size() == 0)
|
||||
{
|
||||
first_run = true;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Clear any existing color/LED configuration |
|
||||
\*-------------------------------------------------*/
|
||||
leds.clear();
|
||||
colors.clear();
|
||||
valid_grp.clear();
|
||||
fix_grps = controller->get_fix_grps();
|
||||
|
||||
for(int grp_num = 0; grp_num < REALTEK_ARGB_NUM_ARGB_GRP; grp_num++)
|
||||
{
|
||||
if(controller->get_zone_enable(grp_num))
|
||||
{
|
||||
valid_grp.push_back(grp_num);
|
||||
if(fix_grps & (0x1 << grp_num))
|
||||
{
|
||||
num_fixgrp++;
|
||||
argb_num_fixgrp += controller->get_argb_num(grp_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Set zones and leds |
|
||||
\*-------------------------------------------------*/
|
||||
zones.resize(valid_grp.size());
|
||||
for(int grp_num : valid_grp)
|
||||
{
|
||||
argb_num = controller->get_argb_num(grp_num);
|
||||
zones[idx].name = "strip " + std::to_string(idx + 1);
|
||||
zones[idx].type = ZONE_TYPE_LINEAR;
|
||||
if(fix_grps & (0x1 << grp_num))
|
||||
{
|
||||
zones[idx].leds_count = argb_num;
|
||||
zones[idx].leds_min = argb_num;
|
||||
zones[idx].leds_max = argb_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(first_run)
|
||||
{
|
||||
zones[idx].leds_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
zones[idx].leds_count = argb_num;
|
||||
}
|
||||
|
||||
zones[idx].leds_min = 0;
|
||||
zones[idx].leds_max = (REALTEK_ARGB_MAX - argb_num_fixgrp) / ((int)valid_grp.size() - num_fixgrp);
|
||||
}
|
||||
zones[idx].matrix_map = NULL;
|
||||
for(unsigned int led_idx = 0; led_idx < zones[idx].leds_count; led_idx++)
|
||||
{
|
||||
led myled;
|
||||
myled.name = zones[idx].name + " led_";
|
||||
myled.name.append(std::to_string(led_idx + 1));
|
||||
leds.push_back(myled);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::ResizeZone(int zone, int new_size)
|
||||
{
|
||||
int fix_grps = controller->get_fix_grps();
|
||||
int orig_num = controller->get_argb_num(valid_grp[zone]);
|
||||
bool need_reboot = true;
|
||||
|
||||
if((size_t) zone >= zones.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if((new_size == orig_num) && zones[zone].leds_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(((unsigned int)new_size >= zones[zone].leds_min) && ((unsigned int)new_size <= zones[zone].leds_max))
|
||||
{
|
||||
int total_argb_num = 0;
|
||||
std::vector<RGBColor> rtk_colors(orig_num, 0);
|
||||
for(int grp_num = 0; grp_num < REALTEK_ARGB_NUM_ARGB_GRP; grp_num++)
|
||||
{
|
||||
if(grp_num == valid_grp[zone])
|
||||
{
|
||||
total_argb_num += new_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
total_argb_num += controller->get_argb_num(grp_num);
|
||||
}
|
||||
}
|
||||
if(total_argb_num > REALTEK_ARGB_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
controller->set_argb_direct(valid_grp[zone], rtk_colors, 0xFF);
|
||||
controller->set_argb_num(valid_grp[zone], new_size);
|
||||
ready_to_reboot[valid_grp[zone]] = true;
|
||||
|
||||
for(int grp_num = 0; grp_num < REALTEK_ARGB_NUM_ARGB_GRP; grp_num++)
|
||||
{
|
||||
if(!ready_to_reboot[grp_num] && !(fix_grps & (0x1 << grp_num)))
|
||||
{
|
||||
need_reboot = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(need_reboot)
|
||||
{
|
||||
controller->device_reboot();
|
||||
controller->device_rescan_trigger();
|
||||
}
|
||||
SetupZones();
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::DeviceUpdateLEDs()
|
||||
{
|
||||
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
if(zones[zone_idx].leds_count > 0)
|
||||
{
|
||||
UpdateZoneLEDs((int)zone_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::UpdateZoneLEDs(int zone)
|
||||
{
|
||||
unsigned short brightness = 0xFF;
|
||||
mode& curr_mode = modes[active_mode];
|
||||
std::vector<RGBColor> color_buf;
|
||||
|
||||
if(curr_mode.color_mode == MODE_COLORS_PER_LED &&
|
||||
curr_mode.value == REALTEK_ARGB_EFF_NULL) //direct mode
|
||||
{
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_BRIGHTNESS)
|
||||
{
|
||||
brightness = curr_mode.brightness;
|
||||
}
|
||||
|
||||
color_buf.resize(zones[zone].leds_count);
|
||||
for(unsigned int i = 0; i < zones[zone].leds_count; i++)
|
||||
color_buf[i] = zones[zone].colors[i];
|
||||
controller->set_argb_direct(valid_grp[zone], color_buf, brightness);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSingleLED(zone);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::UpdateSingleLED(int zone)
|
||||
{
|
||||
mode& curr_mode = modes[active_mode];
|
||||
std::vector<RGBColor> rtk_colors = curr_mode.colors;
|
||||
struct RealtekARGBControllerSetEffParam param;
|
||||
|
||||
param.speed = REALTEK_ARGB_SPEED_NORMAL;
|
||||
param.brightness = 0xFF;
|
||||
param.dir = 0;
|
||||
param.random_color = 0;
|
||||
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_SPEED)
|
||||
{
|
||||
param.speed = curr_mode.speed;
|
||||
}
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_BRIGHTNESS)
|
||||
{
|
||||
param.brightness = curr_mode.brightness;
|
||||
}
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_DIRECTION_LR)
|
||||
{
|
||||
if(curr_mode.direction == MODE_DIRECTION_RIGHT)
|
||||
{
|
||||
param.dir = 1;
|
||||
}
|
||||
}
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_RANDOM_COLOR)
|
||||
{
|
||||
if(curr_mode.color_mode == MODE_COLORS_RANDOM)
|
||||
{
|
||||
param.random_color = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(curr_mode.color_mode == MODE_COLORS_PER_LED)
|
||||
{
|
||||
rtk_colors = colors;
|
||||
}
|
||||
else if(curr_mode.color_mode == MODE_COLORS_NONE)
|
||||
{
|
||||
rtk_colors.clear();
|
||||
}
|
||||
|
||||
controller->set_argb_effect(valid_grp[zone], curr_mode.value, rtk_colors, ¶m);
|
||||
}
|
||||
|
||||
void RGBController_RealtekARGB::DeviceUpdateMode()
|
||||
{
|
||||
if(modes[active_mode].value != REALTEK_ARGB_EFF_NULL)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RealtekARGB.h |
|
||||
| |
|
||||
| RGBController for Realtek USB ARGB ICs |
|
||||
| |
|
||||
| Jerry Fan (JerryFan0612) 13 Mar 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RealtekARGBController.h"
|
||||
|
||||
class RGBController_RealtekARGB : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RealtekARGB(RealtekARGBController* controller_ptr);
|
||||
~RGBController_RealtekARGB();
|
||||
|
||||
void SetupModes();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int zone);
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RealtekARGBController* controller;
|
||||
std::vector<int> valid_grp;
|
||||
bool ready_to_reboot[REALTEK_ARGB_NUM_ARGB_GRP] = {false};
|
||||
};
|
||||
@@ -0,0 +1,715 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RealtekARGBController.cpp |
|
||||
| |
|
||||
| Controller for Realtek USB ARGB ICs |
|
||||
| |
|
||||
| Jerry Fan (JerryFan0612) 13 Mar 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RealtekARGBController.h"
|
||||
#include "MathUtils.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static const unsigned char hid_set_packet[] =
|
||||
{
|
||||
0x56, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE3,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
static const unsigned char hid_get_packet[] =
|
||||
{
|
||||
0x56, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0xE2,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
static const unsigned char hid_end_packet[] =
|
||||
{
|
||||
0x58, 0x53, 0x42, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
RealtekARGBController::RealtekARGBController(hid_device* dev, hid_device_info* info)
|
||||
{
|
||||
hdev = dev;
|
||||
hidinfo = info;
|
||||
for(int i = 0; i < REALTEK_ARGB_NUM_ARGB_GRP; i++)
|
||||
{
|
||||
argbctl_data[i] = (unsigned char*)calloc(REALTEK_ARGB_CTL_DATA_SIZE, 1);
|
||||
memset(argbctl_data[i], 0, REALTEK_ARGB_CTL_DATA_SIZE);
|
||||
prev_bright[i] = 0xFFFF;
|
||||
}
|
||||
device_init();
|
||||
|
||||
keepalive_thread_run = false;
|
||||
keepalive_thread = NULL;
|
||||
}
|
||||
|
||||
RealtekARGBController::~RealtekARGBController()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Close keepalive thread |
|
||||
\*-----------------------------------------------------*/
|
||||
if(keepalive_thread != NULL)
|
||||
{
|
||||
keepalive_thread_run = false;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
}
|
||||
|
||||
if(hdev)
|
||||
{
|
||||
for(int i = 0; i < REALTEK_ARGB_NUM_ARGB_GRP; i++)
|
||||
{
|
||||
int ret = set_appctl(i, REALTEK_ARGB_LED_CTL_FW);
|
||||
if(!ret)
|
||||
{
|
||||
appctl[i] = REALTEK_ARGB_LED_CTL_FW;
|
||||
}
|
||||
}
|
||||
hid_close(hdev);
|
||||
hdev = NULL;
|
||||
}
|
||||
memset(argbctl_hdr, 0, REALTEK_ARGB_CTL_HDR_SIZE);
|
||||
for(int i = 0; i < REALTEK_ARGB_NUM_ARGB_GRP; i++)
|
||||
free(argbctl_data[i]);
|
||||
}
|
||||
|
||||
void RealtekARGBController::KeepaliveThreadFunction()
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| One shot thread to rescan device |
|
||||
\*-----------------------------------------------------------------*/
|
||||
while(keepalive_thread_run.load())
|
||||
{
|
||||
std::this_thread::sleep_for(2s);
|
||||
device_rescan();
|
||||
keepalive_thread_run = false;
|
||||
}
|
||||
}
|
||||
|
||||
int RealtekARGBController::usb_hid_ioctl(unsigned char* usb_buf, unsigned char* data, int data_len,
|
||||
unsigned int offset, unsigned char is_in)
|
||||
{
|
||||
int id;
|
||||
int ret = 0;
|
||||
int buf_len = usb_hid_get_report(data_len, &id);
|
||||
|
||||
if(hdev == NULL)
|
||||
{
|
||||
free(usb_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!is_in && data_len)
|
||||
{
|
||||
usb_buf[0x04] = data[0];
|
||||
}
|
||||
memcpy(&usb_buf[0x08], &data_len, sizeof(data_len));
|
||||
memcpy(&usb_buf[0x1B], &data_len, sizeof(data_len));
|
||||
ret = hid_send_feature_report(hdev, usb_buf, sizeof(hid_get_packet));
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, data, data_len);
|
||||
usb_buf[0x00] = id;
|
||||
if(is_in)
|
||||
{
|
||||
ret = hid_get_feature_report(hdev, usb_buf, buf_len);
|
||||
memcpy(data, usb_buf + offset, data_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = hid_send_feature_report(hdev, usb_buf, buf_len);
|
||||
}
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_end_packet, sizeof(hid_end_packet));
|
||||
ret = hid_get_feature_report(hdev, usb_buf, sizeof(hid_end_packet));
|
||||
free(usb_buf);
|
||||
return (ret > 0) ? 0 : ret;
|
||||
}
|
||||
|
||||
int RealtekARGBController::usb_hid_get_report(int data_len, int* id)
|
||||
{
|
||||
int retlen = 0;
|
||||
|
||||
if(data_len <= REALTEK_ARGB_HID_DATALEN_CH2)
|
||||
{
|
||||
*id = REALTEK_ARGB_HID_ID_DATA_CH2;
|
||||
retlen = REALTEK_ARGB_HID_DATALEN_CH2;
|
||||
}
|
||||
else if(data_len <= REALTEK_ARGB_HID_DATALEN_CH3)
|
||||
{
|
||||
*id = REALTEK_ARGB_HID_ID_DATA_CH3;
|
||||
retlen = REALTEK_ARGB_HID_DATALEN_CH3;
|
||||
}
|
||||
else if(data_len <= REALTEK_ARGB_HID_DATALEN_CH4)
|
||||
{
|
||||
*id = REALTEK_ARGB_HID_ID_DATA_CH4;
|
||||
retlen = REALTEK_ARGB_HID_DATALEN_CH4;
|
||||
}
|
||||
else if(data_len <= REALTEK_ARGB_HID_DATALEN_CH5)
|
||||
{
|
||||
*id = REALTEK_ARGB_HID_ID_DATA_CH5;
|
||||
retlen = REALTEK_ARGB_HID_DATALEN_CH5;
|
||||
}
|
||||
else
|
||||
{
|
||||
*id = REALTEK_ARGB_HID_ID_DATA_CH1;
|
||||
retlen = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
void RealtekARGBController::device_init()
|
||||
{
|
||||
set_write_unlock();
|
||||
get_argbctl_hdr();
|
||||
get_argbctl_data();
|
||||
for(int i = 0; i < REALTEK_ARGB_NUM_ARGB_GRP; i++)
|
||||
{
|
||||
int ret = set_appctl(i, REALTEK_ARGB_LED_CTL_FW);
|
||||
if(!ret)
|
||||
{
|
||||
appctl[i] = REALTEK_ARGB_LED_CTL_FW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_write_unlock()
|
||||
{
|
||||
int ret = 0;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
int data_len = 96;
|
||||
unsigned int addr = 0xAC004000;
|
||||
unsigned char* data = (unsigned char*)calloc(data_len, 1);
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0x92;
|
||||
memcpy(&usb_buf[0x17], &addr, sizeof(addr));
|
||||
ret = usb_hid_ioctl(usb_buf, data, data_len, 0, true);
|
||||
free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char RealtekARGBController::get_support_openrgb()
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned char is_support = 0;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0xCC;
|
||||
usb_buf[0x14] = 0x04;
|
||||
usb_buf[0x15] = REALTEK_ARGB_SYNC_METHOD_OPENRGB;
|
||||
if(usb_hid_ioctl(usb_buf, &is_support, sizeof(is_support), 0, true))
|
||||
{
|
||||
is_support = 0;
|
||||
}
|
||||
return is_support;
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_manu_name()
|
||||
{
|
||||
return StringUtils::wchar_to_char(hidinfo->manufacturer_string);
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_product_name()
|
||||
{
|
||||
return StringUtils::wchar_to_char(hidinfo->product_string);
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_sn()
|
||||
{
|
||||
return StringUtils::wchar_to_char(hidinfo->serial_number);
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_dev_loc()
|
||||
{
|
||||
return hidinfo->path;
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_fw_ver()
|
||||
{
|
||||
std::string ver = "";
|
||||
struct RealtekARGBControllerFWVersion fw_ver;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0xA5;
|
||||
if(!usb_hid_ioctl(usb_buf, (unsigned char*)&fw_ver, sizeof(fw_ver), 0, true))
|
||||
{
|
||||
ver += std::to_string(fw_ver.fw_major_ver) + "." +
|
||||
std::to_string(fw_ver.fw_minor_ver) + "." +
|
||||
std::to_string(fw_ver.fw_extra_ver) + "." +
|
||||
std::to_string(fw_ver.fw_build_date);
|
||||
}
|
||||
return ver;
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_ic_uuid()
|
||||
{
|
||||
unsigned int uuid = 0;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0xC3;
|
||||
usb_hid_ioctl(usb_buf, (unsigned char*)&uuid, sizeof(uuid), 0, true);
|
||||
|
||||
return StringUtils::u32int_to_hexString(uuid);
|
||||
}
|
||||
|
||||
std::string RealtekARGBController::get_dev_name()
|
||||
{
|
||||
bool got_custled = false;
|
||||
std::string devname = get_product_name();
|
||||
|
||||
if(custled[0])
|
||||
{
|
||||
got_custled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!get_custled(custled, sizeof(custled)))
|
||||
{
|
||||
got_custled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(got_custled)
|
||||
{
|
||||
if(custled[5] == REALTEK_ARGB_CUST_DEVNAME_MANU_UUID)
|
||||
{
|
||||
devname = get_manu_name() + get_ic_uuid();
|
||||
}
|
||||
}
|
||||
return devname;
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_fix_grps()
|
||||
{
|
||||
bool got_custled = false;
|
||||
static int fix_grps = 0;
|
||||
|
||||
if(custled[0])
|
||||
{
|
||||
got_custled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!get_custled(custled, sizeof(custled)))
|
||||
{
|
||||
got_custled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(got_custled)
|
||||
{
|
||||
fix_grps = custled[4];
|
||||
}
|
||||
return fix_grps;
|
||||
}
|
||||
|
||||
bool RealtekARGBController::get_zone_enable(int grp_num)
|
||||
{
|
||||
bool got_custled = false;
|
||||
bool en = false;
|
||||
|
||||
if(custled[0])
|
||||
{
|
||||
got_custled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!get_custled(custled, sizeof(custled)))
|
||||
{
|
||||
got_custled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(got_custled)
|
||||
{
|
||||
en = (custled[5] & (0x1 << grp_num)) ? true : false;
|
||||
}
|
||||
return en;
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_argb_num(int grp_num)
|
||||
{
|
||||
int num_rgb = 0;
|
||||
memcpy(&num_rgb, &argbctl_hdr[32 + grp_num * 2], 2);
|
||||
|
||||
return num_rgb;
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_argb_brightness(int grp_num)
|
||||
{
|
||||
int bright = 0;
|
||||
memcpy(&bright, &argbctl_hdr[42 + grp_num * 2], 2);
|
||||
|
||||
return bright;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_argb_brightness(int grp_num, unsigned short bright)
|
||||
{
|
||||
memcpy(&argbctl_hdr[42 + grp_num * sizeof(bright)], &bright, sizeof(bright));
|
||||
set_argbctl_hdr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_appctl(unsigned char grp_num, unsigned char ctl_sts)
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x4C;
|
||||
usb_buf[0x14] = 0x01;
|
||||
usb_buf[0x15] = ctl_sts;
|
||||
usb_buf[0x16] = grp_num;
|
||||
return usb_hid_ioctl(usb_buf, &ctl_sts, sizeof(ctl_sts), 0, false);
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_custled(unsigned char* cust, unsigned int cust_len)
|
||||
{
|
||||
int ret = 0;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned int addr = 0xAC004000;
|
||||
unsigned int offset = 0x800;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len + offset, 1);// will release in usb_hid_ioctl function
|
||||
unsigned char* data = (unsigned char*)calloc(buf_len, 1);
|
||||
|
||||
memset(data, 0x00, buf_len);
|
||||
memset(usb_buf, 0x00, buf_len + offset);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0x92;
|
||||
memcpy(&usb_buf[0x17], &addr, sizeof(addr));
|
||||
ret = usb_hid_ioctl(usb_buf, data, buf_len, offset, true);
|
||||
if(!ret)
|
||||
{
|
||||
memcpy(cust, &data[70], cust_len);
|
||||
}
|
||||
free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_argbctl_hdr()
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0xCC;
|
||||
usb_buf[0x14] = 0x02;
|
||||
return usb_hid_ioctl(usb_buf, argbctl_hdr, REALTEK_ARGB_CTL_HDR_SIZE, 0, true);
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_argbctl_hdr()
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x4C;
|
||||
usb_buf[0x14] = 0x02;
|
||||
return usb_hid_ioctl(usb_buf, argbctl_hdr, REALTEK_ARGB_CTL_HDR_SIZE, 0, false);
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_argbctl_data()
|
||||
{
|
||||
int ret = 0;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
int offset = REALTEK_ARGB_CTL_HDR_SIZE;
|
||||
unsigned char* usb_buf;
|
||||
|
||||
for(int i = 0; i < REALTEK_ARGB_NUM_ARGB_GRP; i++)
|
||||
{
|
||||
usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0xCC;
|
||||
usb_buf[0x14] = 0x02;
|
||||
memcpy(&usb_buf[0x17], &offset, sizeof(offset));
|
||||
ret = usb_hid_ioctl(usb_buf, argbctl_data[i], REALTEK_ARGB_CTL_DATA_SIZE, 0, true);
|
||||
offset += REALTEK_ARGB_CTL_DATA_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_argbctl_data(unsigned char grp_num)
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
int offset = REALTEK_ARGB_CTL_HDR_SIZE + REALTEK_ARGB_CTL_DATA_SIZE * grp_num;
|
||||
unsigned char* usb_buf;
|
||||
|
||||
usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x4C;
|
||||
usb_buf[0x14] = 0x02;
|
||||
memcpy(&usb_buf[0x17], &offset, sizeof(offset));
|
||||
return usb_hid_ioctl(usb_buf, argbctl_data[grp_num], REALTEK_ARGB_CTL_DATA_SIZE, 0, false);
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_eff_id(unsigned char grp_num, unsigned short effid)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num], &effid, sizeof(effid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_p_color(unsigned char grp_num, RGBColor color)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num] + 8, &color, sizeof(color));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_s_color(unsigned char grp_num, RGBColor color)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num] + 12, &color, sizeof(color));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_cycle(unsigned char grp_num, unsigned short cycle)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num] + 2, &cycle, sizeof(cycle));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_ramp(unsigned char grp_num, unsigned short ramp)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num] + 4, &ramp, sizeof(ramp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_stable(unsigned char grp_num, unsigned short stable)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num] + 6, &stable, sizeof(stable));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_subcmd(unsigned char grp_num, int subcmd)
|
||||
{
|
||||
memcpy(argbctl_data[grp_num] + 16, &subcmd, sizeof(subcmd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_direct(unsigned char* color, int color_num, unsigned char grp_num)
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
int data_len = color_num * REALTEK_ARGB_COLOR_DEPTH;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_ioctl function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x4C;
|
||||
usb_buf[0x14] = 0x03;
|
||||
usb_buf[0x15] = REALTEK_ARGB_SYNC_METHOD_OPENRGB;
|
||||
usb_buf[0x16] = grp_num;
|
||||
memcpy(&usb_buf[0x17], &color_num, sizeof(color_num));
|
||||
return usb_hid_ioctl(usb_buf, color, data_len, 0, false);
|
||||
}
|
||||
|
||||
int RealtekARGBController::get_flash_argbctl_hdr(unsigned char* data)
|
||||
{
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned int addr = 0xAC000000;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_get_packet, sizeof(hid_get_packet));
|
||||
usb_buf[0x13] = 0x92;
|
||||
memcpy(&usb_buf[0x17], &addr, sizeof(addr));
|
||||
return usb_hid_ioctl(usb_buf, data, buf_len, 0, true);
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_flash_argbctl_hdr(unsigned int offset, unsigned int data_len)
|
||||
{
|
||||
int ret = 0;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
unsigned int addr = 0xAC000000;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
unsigned char* data = (unsigned char*)calloc(buf_len, 1);
|
||||
memset(data, 0, buf_len);
|
||||
|
||||
ret = get_flash_argbctl_hdr(data);
|
||||
if(!ret)
|
||||
{
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x10;
|
||||
memcpy(&usb_buf[0x17], &addr, sizeof(addr));
|
||||
ret = usb_hid_ioctl(usb_buf, (unsigned char*)&addr, sizeof(addr), 0, false);
|
||||
|
||||
usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x11;
|
||||
memcpy(data + offset, argbctl_hdr + offset, data_len);
|
||||
ret = usb_hid_ioctl(usb_buf, data, buf_len, 0, false);
|
||||
}
|
||||
free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_argb_direct(int grp_num, std::vector<RGBColor> color_buf, unsigned short brightness)
|
||||
{
|
||||
int ret = -1;
|
||||
size_t color_num = color_buf.size();
|
||||
size_t buf_len = color_num * REALTEK_ARGB_COLOR_DEPTH;
|
||||
unsigned char* buf;
|
||||
std::lock_guard<std::mutex> lock(my_mutex);
|
||||
|
||||
if(color_num == 0)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(appctl[grp_num] != REALTEK_ARGB_LED_CTL_APP)
|
||||
{
|
||||
ret = set_appctl(grp_num, REALTEK_ARGB_LED_CTL_APP);
|
||||
if(ret)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
appctl[grp_num] = REALTEK_ARGB_LED_CTL_APP;
|
||||
}
|
||||
}
|
||||
|
||||
if(prev_bright[grp_num] != brightness)
|
||||
{
|
||||
prev_bright[grp_num] = brightness;
|
||||
ret = set_argb_brightness(grp_num, brightness << 8);
|
||||
if(ret)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
buf = (uint8_t*)malloc(buf_len);
|
||||
memset(buf, 0, buf_len);
|
||||
for(size_t i = 0; i < color_num; i++)
|
||||
{
|
||||
buf[i * REALTEK_ARGB_COLOR_DEPTH + 0] = RGBGetRValue(color_buf[i]);
|
||||
buf[i * REALTEK_ARGB_COLOR_DEPTH + 1] = RGBGetGValue(color_buf[i]);
|
||||
buf[i * REALTEK_ARGB_COLOR_DEPTH + 2] = RGBGetBValue(color_buf[i]);
|
||||
}
|
||||
ret = set_direct(buf, (int)color_num, grp_num);
|
||||
free(buf);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_argb_effect(int grp_num, uint8_t mode, std::vector<RGBColor> color_buf, struct RealtekARGBControllerSetEffParam* param)
|
||||
{
|
||||
int ret = -1;
|
||||
int cycle = MathUtils::IntInterpolate(REALTEK_ARGB_CYCLE_MAX, REALTEK_ARGB_CYCLE_MIN, 0, REALTEK_ARGB_SPEED_MAX, param->speed);
|
||||
std::lock_guard<std::mutex> lock(my_mutex);
|
||||
|
||||
if(mode == REALTEK_ARGB_EFF_ALWAYS_ON || mode == REALTEK_ARGB_EFF_STACK)
|
||||
{
|
||||
cycle = 0;
|
||||
}
|
||||
|
||||
if(color_buf.size() >= 1)
|
||||
{
|
||||
set_p_color(grp_num, color_buf[0]);
|
||||
}
|
||||
if(color_buf.size() >= 2)
|
||||
{
|
||||
set_s_color(grp_num, color_buf[1]);
|
||||
}
|
||||
|
||||
set_eff_id(grp_num, mode);
|
||||
set_cycle(grp_num, cycle);
|
||||
set_ramp(grp_num, 0);
|
||||
set_stable(grp_num, 0);
|
||||
set_subcmd(grp_num, (param->dir || param->random_color) ? 0x1 : 0x0);
|
||||
set_argb_brightness(grp_num, param->brightness << 8);
|
||||
set_argbctl_data(grp_num);
|
||||
|
||||
ret = set_appctl(grp_num, REALTEK_ARGB_LED_CTL_FW);
|
||||
if(!ret)
|
||||
{
|
||||
appctl[grp_num] = REALTEK_ARGB_LED_CTL_FW;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RealtekARGBController::set_argb_num(int grp_num, unsigned short new_num)
|
||||
{
|
||||
memcpy(&argbctl_hdr[32 + grp_num * sizeof(new_num)], &new_num, sizeof(new_num));
|
||||
set_flash_argbctl_hdr(32 + grp_num * sizeof(new_num), sizeof(new_num));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekARGBController::device_reboot()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(my_mutex);
|
||||
int ret = 0;
|
||||
int buf_len = REALTEK_ARGB_HID_DATALEN_CH1;
|
||||
int reboot_type = 1;
|
||||
unsigned char* usb_buf = (unsigned char*)calloc(buf_len, 1);// will release in usb_hid_send/usb_hid_get function
|
||||
|
||||
memset(usb_buf, 0x00, buf_len);
|
||||
memcpy(usb_buf, hid_set_packet, sizeof(hid_set_packet));
|
||||
usb_buf[0x13] = 0x30;
|
||||
usb_buf[0x14] = reboot_type;
|
||||
ret = usb_hid_ioctl(usb_buf, (unsigned char*)&reboot_type, sizeof(reboot_type), 0, false);
|
||||
|
||||
hid_close(hdev);
|
||||
hdev = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RealtekARGBController::device_rescan_trigger()
|
||||
{
|
||||
keepalive_thread_run = true;
|
||||
keepalive_thread = new std::thread(&RealtekARGBController::KeepaliveThreadFunction, this);
|
||||
}
|
||||
|
||||
void RealtekARGBController::device_rescan()
|
||||
{
|
||||
hid_device_info* info_full = hid_enumerate(REALTEK_ARGB_VID, REALTEK_ARGB_PID);
|
||||
hid_device_info* info_temp = info_full;
|
||||
|
||||
while(info_temp)
|
||||
{
|
||||
if(info_temp->vendor_id == REALTEK_ARGB_VID &&
|
||||
info_temp->product_id == REALTEK_ARGB_PID &&
|
||||
info_temp->usage == REALTEK_ARGB_HID2SCSI_USAGE &&
|
||||
info_temp->usage_page == REALTEK_ARGB_HID2SCSI_PG)
|
||||
{
|
||||
hid_device* dev_temp = hid_open_path(info_temp->path);
|
||||
if(dev_temp)
|
||||
{
|
||||
hdev = dev_temp;
|
||||
if(get_support_openrgb())
|
||||
{
|
||||
device_init();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
hid_close(hdev);
|
||||
hdev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
info_temp = info_temp->next;
|
||||
}
|
||||
hid_free_enumeration(info_full);
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RealtekARGBController.h |
|
||||
| |
|
||||
| Controller for Realtek USB ARGB ICs |
|
||||
| |
|
||||
| Jerry Fan (JerryFan0612) 13 Mar 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <hidapi.h>
|
||||
|
||||
#include "RGBController.h"
|
||||
|
||||
#define REALTEK_ARGB_VID 0x0BDA
|
||||
#define REALTEK_ARGB_PID 0x9209
|
||||
#define REALTEK_ARGB_HID2SCSI_PG 0xFF00
|
||||
#define REALTEK_ARGB_HID2SCSI_USAGE 0x0001
|
||||
|
||||
#define REALTEK_ARGB_NUM_ARGB_GRP 5
|
||||
#define REALTEK_ARGB_BRINTF_TYPE_HID 1
|
||||
#define REALTEK_ARGB_SYNC_METHOD_OPENRGB 6
|
||||
#define REALTEK_ARGB_COLOR_DEPTH 3
|
||||
#define REALTEK_ARGB_MAX 400
|
||||
|
||||
#define REALTEK_ARGB_CTL_HDR_SIZE 80
|
||||
#define REALTEK_ARGB_CTL_DATA_SIZE 96
|
||||
|
||||
#define REALTEK_ARGB_HID_DATALEN_CH1 4096
|
||||
#define REALTEK_ARGB_HID_DATALEN_CH2 64
|
||||
#define REALTEK_ARGB_HID_DATALEN_CH3 512
|
||||
#define REALTEK_ARGB_HID_DATALEN_CH4 1200
|
||||
#define REALTEK_ARGB_HID_DATALEN_CH5 2048
|
||||
|
||||
#define REALTEK_ARGB_HID_ID_DATA_CH1 0x57
|
||||
#define REALTEK_ARGB_HID_ID_DATA_CH2 0x59
|
||||
#define REALTEK_ARGB_HID_ID_DATA_CH3 0x5A
|
||||
#define REALTEK_ARGB_HID_ID_DATA_CH4 0x5B
|
||||
#define REALTEK_ARGB_HID_ID_DATA_CH5 0x5C
|
||||
|
||||
enum REALTEK_ARGB_LED_CTL
|
||||
{
|
||||
REALTEK_ARGB_LED_CTL_FW,
|
||||
REALTEK_ARGB_LED_CTL_APP,
|
||||
REALTEK_ARGB_LED_CTL_LAMP,
|
||||
};
|
||||
|
||||
enum REALTEK_ARGB_EFFECT_ID
|
||||
{
|
||||
REALTEK_ARGB_EFF_NULL,
|
||||
REALTEK_ARGB_EFF_ALWAYS_ON,
|
||||
REALTEK_ARGB_EFF_BLINK,
|
||||
REALTEK_ARGB_EFF_BREATH,
|
||||
REALTEK_ARGB_EFF_SPECTRUM,
|
||||
REALTEK_ARGB_EFF_SCROLL,
|
||||
REALTEK_ARGB_EFF_RAINBOW_SCROLL,
|
||||
REALTEK_ARGB_EFF_RUNNING_WATER,
|
||||
REALTEK_ARGB_EFF_SLIDING,
|
||||
REALTEK_ARGB_EFF_NEWTON_CRADLE,
|
||||
REALTEK_ARGB_EFF_METEOR,
|
||||
REALTEK_ARGB_EFF_RAINBOW_SLIDING,
|
||||
REALTEK_ARGB_EFF_RAINBOW_FADE_SLIDING,
|
||||
REALTEK_ARGB_EFF_WIDE_SLIDING,
|
||||
REALTEK_ARGB_EFF_DOT_MATRIX, // reserved: Not supported by OpenRGB
|
||||
REALTEK_ARGB_EFF_DOT_MATRIX_BREATH, // reserved: Not supported by OpenRGB
|
||||
REALTEK_ARGB_EFF_ZIGZAG,
|
||||
REALTEK_ARGB_EFF_STARRY_NIGHT,
|
||||
REALTEK_ARGB_EFF_STACK,
|
||||
};
|
||||
|
||||
enum REALTEK_ARGB_SPEED
|
||||
{
|
||||
REALTEK_ARGB_SPEED_MIN = 1,
|
||||
REALTEK_ARGB_SPEED_NORMAL = 50,
|
||||
REALTEK_ARGB_SPEED_MAX = 100,
|
||||
};
|
||||
|
||||
enum REALTEK_ARGB_CYCLE_MS
|
||||
{
|
||||
REALTEK_ARGB_CYCLE_MIN = 200,
|
||||
REALTEK_ARGB_CYCLE_NORMAL = 2000,
|
||||
REALTEK_ARGB_CYCLE_MAX = 10000,
|
||||
};
|
||||
|
||||
enum REALTEK_ARGB_CUST_DEVNAME
|
||||
{
|
||||
REALTEK_ARGB_CUST_DEVNAME_NULL = 0x0,
|
||||
REALTEK_ARGB_CUST_DEVNAME_MANU_UUID = 0x1,
|
||||
};
|
||||
|
||||
struct RealtekARGBControllerSetEffParam
|
||||
{
|
||||
unsigned int speed;
|
||||
unsigned short brightness;
|
||||
unsigned char dir;
|
||||
unsigned char random_color;
|
||||
};
|
||||
|
||||
struct RealtekARGBControllerFWVersion
|
||||
{
|
||||
unsigned int fw_major_ver;
|
||||
unsigned int fw_minor_ver;
|
||||
unsigned int fw_extra_ver;
|
||||
unsigned int fw_build_ver;
|
||||
unsigned int fw_build_date;
|
||||
};
|
||||
|
||||
class RealtekARGBController
|
||||
{
|
||||
public:
|
||||
RealtekARGBController(hid_device* dev, hid_device_info* info);
|
||||
~RealtekARGBController();
|
||||
|
||||
unsigned char get_support_openrgb();
|
||||
std::string get_manu_name();
|
||||
std::string get_product_name();
|
||||
std::string get_sn();
|
||||
std::string get_dev_loc();
|
||||
std::string get_fw_ver();
|
||||
std::string get_ic_uuid();
|
||||
std::string get_dev_name();
|
||||
int get_fix_grps();
|
||||
bool get_zone_enable(int grp_num);
|
||||
int get_argb_num(int grp_num);
|
||||
int get_argb_brightness(int grp_num);
|
||||
int set_argb_brightness(int grp_num, unsigned short bright);
|
||||
|
||||
int set_argb_direct(int grp_num, std::vector<RGBColor> color_buf, unsigned short brightness);
|
||||
int set_argb_effect(int grp_num, uint8_t mode, std::vector<RGBColor> color_buf, struct RealtekARGBControllerSetEffParam* param);
|
||||
int set_argb_num(int grp_num, unsigned short new_num);
|
||||
int device_reboot();
|
||||
void device_rescan_trigger();
|
||||
private:
|
||||
hid_device* hdev;
|
||||
std::mutex my_mutex;
|
||||
unsigned char argbctl_hdr[REALTEK_ARGB_CTL_HDR_SIZE] = {0};
|
||||
unsigned char* argbctl_data[REALTEK_ARGB_NUM_ARGB_GRP] = {0};
|
||||
hid_device_info* hidinfo = NULL;
|
||||
int appctl[REALTEK_ARGB_NUM_ARGB_GRP] = {REALTEK_ARGB_LED_CTL_FW};
|
||||
unsigned short prev_bright[REALTEK_ARGB_NUM_ARGB_GRP] = {0};
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::thread* keepalive_thread;
|
||||
unsigned char custled[16] = {0};
|
||||
|
||||
void KeepaliveThreadFunction();
|
||||
|
||||
int usb_hid_ioctl(unsigned char* usb_buf, unsigned char* data, int data_len,
|
||||
unsigned int offset, unsigned char is_in);
|
||||
int usb_hid_get_report(int data_len, int* id);
|
||||
|
||||
void device_init();
|
||||
int set_write_unlock();
|
||||
int set_appctl(unsigned char grp_num, unsigned char ctl_sts);
|
||||
int set_argbctl_data(unsigned char* data, int data_len, int offset);
|
||||
int get_custled(unsigned char* cust, unsigned int cust_len);
|
||||
int get_argbctl_hdr();
|
||||
int set_argbctl_hdr();
|
||||
int get_argbctl_data();
|
||||
int set_argbctl_data(unsigned char grp_num);
|
||||
int set_eff_id(unsigned char grp_num, unsigned short effid);
|
||||
int set_p_color(unsigned char grp_num, RGBColor color);
|
||||
int set_s_color(unsigned char grp_num, RGBColor color);
|
||||
int set_cycle(unsigned char grp_num, unsigned short cycle);
|
||||
int set_ramp(unsigned char grp_num, unsigned short ramp);
|
||||
int set_stable(unsigned char grp_num, unsigned short stable);
|
||||
int set_subcmd(unsigned char grp_num, int subcmd);
|
||||
int set_direct(unsigned char* color, int color_num, unsigned char grp_num);
|
||||
|
||||
int get_flash_argbctl_hdr(unsigned char* data);
|
||||
int set_flash_argbctl_hdr(unsigned int offset, unsigned int data_len);
|
||||
|
||||
void device_rescan();
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RealtekARGBControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Realtek USB ARGB ICs |
|
||||
| |
|
||||
| Jerry Fan (JerryFan0612) 13 Mar 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "Detector.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_RealtekARGB.h"
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectRealtekARGBControllers *
|
||||
* *
|
||||
* Tests the USB address to see if an Realtek ARGB controller exists there *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
void DetectRealtekARGBControllers(hid_device_info* info, const std::string& /*name*/)
|
||||
{
|
||||
RealtekARGBController* controller = NULL;
|
||||
RGBController_RealtekARGB* rgb_controller = NULL;
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
controller = new RealtekARGBController(dev, info);
|
||||
if(controller->get_support_openrgb())
|
||||
{
|
||||
rgb_controller = new RGBController_RealtekARGB(controller);
|
||||
if(rgb_controller->type != DEVICE_TYPE_UNKNOWN)
|
||||
{
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete rgb_controller;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_PU("RTL9209", DetectRealtekARGBControllers, REALTEK_ARGB_VID, REALTEK_ARGB_PID, REALTEK_ARGB_HID2SCSI_PG, REALTEK_ARGB_HID2SCSI_USAGE);
|
||||
@@ -28,6 +28,7 @@
|
||||
#define REDRAGON_M801_PID 0xFC58
|
||||
#define REDRAGON_M810_PID 0xFA7E
|
||||
#define REDRAGON_M987_PID 0xFC69
|
||||
#define REDRAGON_M921_PID 0xFC40
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
@@ -62,3 +63,4 @@ REGISTER_HID_DETECTOR_IP("Redragon M808 Storm", DetectRedragonMice, RE
|
||||
REGISTER_HID_DETECTOR_IP("Redragon M801 Sniper", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M801_PID, 2, REDRAGON_MOUSE_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("Redragon M810 Taipan", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M810_PID, 2, REDRAGON_MOUSE_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("Redragon M987 Reaping", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M987_PID, 2, REDRAGON_MOUSE_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("Redragon M921 Azzinoth", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M921_PID, 2, REDRAGON_MOUSE_USAGE_PAGE);
|
||||
|
||||
@@ -120,13 +120,13 @@
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_PID 0x1628
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1 0x1630
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2 0x1632
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_PID 0x1642
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1 0x1644
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2 0x1646
|
||||
#define STEELSERIES_APEX_M750_PID 0x0616
|
||||
#define STEELSERIES_APEX_OG_PID 0x1202
|
||||
#define STEELSERIES_APEX_350_PID 0x1206
|
||||
#define STEELSERIES_APEX_PRO3_PID 0x1640
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_PID 0x1642
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1 0x1644
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2 0x1646
|
||||
|
||||
void DetectSteelSeriesAerox3(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
@@ -516,10 +516,10 @@ REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL", Dete
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL 2023 Wired", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL 2023 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1, 3, 0xFFC0, 1);
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL 2023 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2, 3, 0xFFC0, 1);
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL Gen 3 Wired", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL Gen 3 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1, 3, 0xFFC0, 1);
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL Gen 3 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2, 3, 0xFFC0, 1);
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex M750", DetectSteelSeriesApexM, STEELSERIES_VID, STEELSERIES_APEX_M750_PID, 2 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex (OG)/Apex Fnatic", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_OG_PID, 0 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 350", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_350_PID, 0 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro 3", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO3_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL Gen 3", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL Gen 3 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1, 3, 0xFFC0, 1);
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL Gen 3 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2, 3, 0xFFC0, 1);
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_ZotacBlackwellGPU.h"
|
||||
#include "LogManager.h"
|
||||
#include "pci_ids.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name ZOTAC RTX 50 series GPU
|
||||
@@ -20,21 +22,60 @@
|
||||
@effects :tools:
|
||||
@detectors DetectZotacBlackwellGPUControllersPCI
|
||||
@comment
|
||||
Supports ZOTAC Blackwell (RTX 50 series) GPUs with 3 zones:
|
||||
Logo, Side Bar, and Infinity Mirror.
|
||||
Supports ZOTAC Blackwell (RTX 50 series) GPUs. The zone layout
|
||||
varies per card and is resolved from a static table keyed on
|
||||
PCI device and sub-device IDs.
|
||||
|
||||
The controller uses individual SMBus byte writes (registers
|
||||
0x20-0x2F) with a 3ms delay between each transaction.
|
||||
|
||||
To add new cards, add PCI ID entries in `pci_ids/pci_ids.h`
|
||||
and detection entries in
|
||||
To add new cards, add PCI ID entries in `pci_ids/pci_ids.h`,
|
||||
a zone config entry in `device_zone_configs` below, and a
|
||||
`REGISTER_I2C_PCI_DETECTOR` line in
|
||||
`Controllers/ZotacBlackwellGPUController/ZotacBlackwellGPUControllerDetect.cpp`.
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_ZotacBlackwellGPU::RGBController_ZotacBlackwellGPU(ZotacBlackwellGPUController* controller_ptr)
|
||||
const RGBController_ZotacBlackwellGPU::DeviceZoneConfig RGBController_ZotacBlackwellGPU::device_zone_configs[] =
|
||||
{
|
||||
{ NVIDIA_RTX5080_DEV, ZOTAC_RTX5080_AMP_EXTREME_SUB_DEV, { "Logo", "Side Bar", "Infinity Mirror" }, 3 },
|
||||
{ NVIDIA_RTX5090_DEV, ZOTAC_RTX5090_SOLID_OC_SUB_DEV, { "ZOTAC Gaming", "Logo" }, 2 },
|
||||
{ 0, 0, { nullptr }, 0 }
|
||||
};
|
||||
|
||||
const RGBController_ZotacBlackwellGPU::DeviceZoneConfig* RGBController_ZotacBlackwellGPU::FindZoneConfig(uint16_t device, uint16_t subdevice)
|
||||
{
|
||||
for(const DeviceZoneConfig* cfg = device_zone_configs; cfg->zone_count != 0; cfg++)
|
||||
{
|
||||
if(cfg->device == device && cfg->subdevice == subdevice)
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RGBController_ZotacBlackwellGPU::RGBController_ZotacBlackwellGPU(ZotacBlackwellGPUController* controller_ptr,
|
||||
uint16_t device, uint16_t subdevice)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
const DeviceZoneConfig* cfg = FindZoneConfig(device, subdevice);
|
||||
if(cfg == nullptr)
|
||||
{
|
||||
LOG_ERROR("[%s] Unrecognized PCI device/subdevice: %04X/%04X. Falling back to three generic zones.",
|
||||
controller->GetName().c_str(), device, subdevice);
|
||||
zone_names.push_back("Zone 0");
|
||||
zone_names.push_back("Zone 1");
|
||||
zone_names.push_back("Zone 2");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint8_t z = 0; z < cfg->zone_count; z++)
|
||||
{
|
||||
zone_names.push_back(cfg->zones[z]);
|
||||
}
|
||||
}
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "ZOTAC";
|
||||
description = "ZOTAC RTX 50 series RGB GPU Device (" + controller->GetVersion() + ")";
|
||||
@@ -252,52 +293,25 @@ RGBController_ZotacBlackwellGPU::~RGBController_ZotacBlackwellGPU()
|
||||
void RGBController_ZotacBlackwellGPU::SetupZones()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Zone 0: Logo |
|
||||
| One single-LED zone per name from the device_zone_configs |
|
||||
| table. The zone's index is its position here, which is |
|
||||
| written verbatim to the zone register (0x21) on update. |
|
||||
\*---------------------------------------------------------*/
|
||||
zone logo_zone;
|
||||
logo_zone.name = "Logo";
|
||||
logo_zone.type = ZONE_TYPE_SINGLE;
|
||||
logo_zone.leds_min = 1;
|
||||
logo_zone.leds_max = 1;
|
||||
logo_zone.leds_count = 1;
|
||||
logo_zone.matrix_map = NULL;
|
||||
zones.push_back(logo_zone);
|
||||
for(const std::string& zone_name : zone_names)
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = zone_name;
|
||||
new_zone.type = ZONE_TYPE_SINGLE;
|
||||
new_zone.leds_min = 1;
|
||||
new_zone.leds_max = 1;
|
||||
new_zone.leds_count = 1;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
led logo_led;
|
||||
logo_led.name = "Logo LED";
|
||||
leds.push_back(logo_led);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Zone 1: Side Bar |
|
||||
\*---------------------------------------------------------*/
|
||||
zone sidebar_zone;
|
||||
sidebar_zone.name = "Side Bar";
|
||||
sidebar_zone.type = ZONE_TYPE_SINGLE;
|
||||
sidebar_zone.leds_min = 1;
|
||||
sidebar_zone.leds_max = 1;
|
||||
sidebar_zone.leds_count = 1;
|
||||
sidebar_zone.matrix_map = NULL;
|
||||
zones.push_back(sidebar_zone);
|
||||
|
||||
led sidebar_led;
|
||||
sidebar_led.name = "Side Bar LED";
|
||||
leds.push_back(sidebar_led);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Zone 2: Infinity Mirror |
|
||||
\*---------------------------------------------------------*/
|
||||
zone infinity_zone;
|
||||
infinity_zone.name = "Infinity Mirror";
|
||||
infinity_zone.type = ZONE_TYPE_SINGLE;
|
||||
infinity_zone.leds_min = 1;
|
||||
infinity_zone.leds_max = 1;
|
||||
infinity_zone.leds_count = 1;
|
||||
infinity_zone.matrix_map = NULL;
|
||||
zones.push_back(infinity_zone);
|
||||
|
||||
led infinity_led;
|
||||
infinity_led.name = "Infinity Mirror LED";
|
||||
leds.push_back(infinity_led);
|
||||
led new_led;
|
||||
new_led.name = zone_name + " LED";
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
@@ -362,7 +376,7 @@ void RGBController_ZotacBlackwellGPU::DeviceUpdateZone(int zone)
|
||||
|
||||
void RGBController_ZotacBlackwellGPU::DeviceUpdateMode()
|
||||
{
|
||||
for(unsigned int zone_idx = 0; zone_idx < ZOTAC_BLACKWELL_GPU_NUM_ZONES; zone_idx++)
|
||||
for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
DeviceUpdateZone(zone_idx);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "RGBController.h"
|
||||
#include "ZotacBlackwellGPUController.h"
|
||||
|
||||
class RGBController_ZotacBlackwellGPU : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_ZotacBlackwellGPU(ZotacBlackwellGPUController* controller_ptr);
|
||||
RGBController_ZotacBlackwellGPU(ZotacBlackwellGPUController* controller_ptr,
|
||||
uint16_t device, uint16_t subdevice);
|
||||
~RGBController_ZotacBlackwellGPU();
|
||||
|
||||
void SetupZones();
|
||||
@@ -33,4 +37,17 @@ public:
|
||||
|
||||
private:
|
||||
ZotacBlackwellGPUController* controller;
|
||||
std::vector<std::string> zone_names;
|
||||
|
||||
struct DeviceZoneConfig
|
||||
{
|
||||
uint16_t device;
|
||||
uint16_t subdevice;
|
||||
const char* zones[4];
|
||||
uint8_t zone_count;
|
||||
};
|
||||
|
||||
static const DeviceZoneConfig device_zone_configs[];
|
||||
|
||||
static const DeviceZoneConfig* FindZoneConfig(uint16_t device, uint16_t subdevice);
|
||||
};
|
||||
|
||||
@@ -46,14 +46,6 @@
|
||||
#define ZOTAC_BLACKWELL_GPU_REG_RELOAD 0x11
|
||||
#define ZOTAC_BLACKWELL_GPU_REG_COMMIT 0x17
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Zone indices |
|
||||
\*---------------------------------------------------------*/
|
||||
#define ZOTAC_BLACKWELL_GPU_ZONE_LOGO 0x00
|
||||
#define ZOTAC_BLACKWELL_GPU_ZONE_SIDEBAR 0x01
|
||||
#define ZOTAC_BLACKWELL_GPU_ZONE_INFINITY 0x02
|
||||
#define ZOTAC_BLACKWELL_GPU_NUM_ZONES 3
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Mode values (from Firestorm V5.0.0.012E reverse eng.) |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
* DetectZotacBlackwellGPUControllersPCI *
|
||||
* *
|
||||
* Detect ZOTAC Blackwell (RTX 50 series) RGB controllers on the enumerated *
|
||||
* I2C busses at address 0x4B. *
|
||||
* I2C busses at address 0x4B. Zone configuration is resolved inside the *
|
||||
* RGBController by looking up the PCI device/sub-device IDs in a static table. *
|
||||
* *
|
||||
* bus - pointer to i2c_smbus_interface where RGB device is connected *
|
||||
* dev - I2C address of RGB device *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
void DetectZotacBlackwellGPUControllersPCI(i2c_smbus_interface* bus, u8 i2c_addr, const std::string& name)
|
||||
{
|
||||
s32 result = bus->i2c_smbus_read_byte_data(i2c_addr, 0x10);
|
||||
@@ -34,10 +34,13 @@ void DetectZotacBlackwellGPUControllersPCI(i2c_smbus_interface* bus, u8 i2c_addr
|
||||
if(result >= 0)
|
||||
{
|
||||
ZotacBlackwellGPUController* controller = new ZotacBlackwellGPUController(bus, i2c_addr, name);
|
||||
RGBController_ZotacBlackwellGPU* rgb_controller = new RGBController_ZotacBlackwellGPU(controller);
|
||||
RGBController_ZotacBlackwellGPU* rgb_controller = new RGBController_ZotacBlackwellGPU(controller,
|
||||
bus->pci_device,
|
||||
bus->pci_subsystem_device);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 5080 AMP Extreme INFINITY", DetectZotacBlackwellGPUControllersPCI, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX5080_AMP_EXTREME_SUB_DEV, 0x4B);
|
||||
REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 5090 SOLID OC", DetectZotacBlackwellGPUControllersPCI, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX5090_SOLID_OC_SUB_DEV, 0x4B);
|
||||
|
||||
@@ -366,6 +366,7 @@
|
||||
#define ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING 0x89DF
|
||||
#define ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING_WHITE 0x8A2C
|
||||
#define ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING 0x89E3
|
||||
#define ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_2 0x89E4
|
||||
#define ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_BTF 0x8A3C
|
||||
#define ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_WHITE 0x8A2E
|
||||
#define ASUS_ROG_ASTRAL_LC_RTX_5090_O32G_GAMING 0x89EC
|
||||
@@ -999,6 +1000,7 @@
|
||||
#define ZOTAC_RTX4090_TRINITY_SUB_DEV 0x3675
|
||||
#define ZOTAC_RTX4090_AMP_SUB_DEV 0x4675
|
||||
#define ZOTAC_RTX5080_AMP_EXTREME_SUB_DEV 0x1762
|
||||
#define ZOTAC_RTX5090_SOLID_OC_SUB_DEV 0x1761
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Manli Sub-Device IDs |
|
||||
|
||||
Reference in New Issue
Block a user