Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
253f74f5bd | ||
|
|
b03cd94ae8 | ||
|
|
bbf348d273 | ||
|
|
dce48eb415 | ||
|
|
decf14635d | ||
|
|
db4f49bbba | ||
|
|
26824fcb6e | ||
|
|
8afad91b33 | ||
|
|
69de0b13c4 | ||
|
|
967153bc10 | ||
|
|
971d9be1bd | ||
|
|
7a3faef886 | ||
|
|
f67030fcc7 | ||
|
|
7353e99449 | ||
|
|
91d9597c89 | ||
|
|
2eb569912b | ||
|
|
9410d9c066 | ||
|
|
29d8788e25 | ||
|
|
0304c50bc6 |
@@ -22,6 +22,7 @@
|
||||
#define AURA_ROG_GLADIUS_II_WIRELESS_1_PID 0x189E
|
||||
#define AURA_ROG_GLADIUS_II_WIRELESS_2_PID 0x18A0
|
||||
#define AURA_ROG_GLADIUS_III_PID 0x197B
|
||||
#define AURA_ROG_GLADIUS_III_CORE_PID 0x1C8D
|
||||
#define AURA_ROG_GLADIUS_III_WIRELESS_USB_PID 0x197D
|
||||
#define AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID 0x197F
|
||||
#define AURA_ROG_GLADIUS_III_WIRELESS_BT_PID 0x1981
|
||||
@@ -217,6 +218,20 @@ static std::map<int,mouse_type> aura_mouse_devices =
|
||||
{ AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY }
|
||||
}
|
||||
},
|
||||
{
|
||||
AURA_ROG_GLADIUS_III_CORE_PID, // ROG Gladius III Core
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
100,
|
||||
false,
|
||||
1,
|
||||
false,
|
||||
{ AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL },
|
||||
{ AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE }
|
||||
}
|
||||
},
|
||||
{
|
||||
AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, // ROG Gladius III Wireless USB
|
||||
{
|
||||
|
||||
@@ -394,6 +394,7 @@ REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin COD",
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_1_PID, 1, 0xFF13);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_2_PID, 2, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_PID, 0, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_CORE_PID, 0, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, 0, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, 0, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, 0, 0xFF01);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*---------------------------------------------------------*\
|
||||
/*---------------------------------------------------------*\
|
||||
| ColorfulGPUControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Colorful GPU |
|
||||
@@ -48,7 +48,7 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Advanced OC 12G L-V", Detec
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA106_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060TI_ADVANCED_OC, 0x61);
|
||||
@@ -72,6 +72,8 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", Detec
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV2, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV2, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060_ULTRAW_OC, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC_2, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV, 0x61);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV2, 0x61);
|
||||
@@ -461,6 +461,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS ROG MATRIX PLATINUM GeForce RTX 4090",
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5060_O8G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070_O12G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING_WHITE, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_5070TI_O16G_GAMING_OC, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5080_O16G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5090_O32G_GAMING, 0x67);
|
||||
@@ -468,6 +469,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming",
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING, 0x67);
|
||||
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING_WHITE, 0x67);
|
||||
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 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);
|
||||
|
||||
@@ -44,7 +44,7 @@ FnaticStreakController::~FnaticStreakController()
|
||||
|
||||
std::string FnaticStreakController::GetDeviceLocation()
|
||||
{
|
||||
return("HID " + location);
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string FnaticStreakController::GetNameString()
|
||||
@@ -230,16 +230,41 @@ void FnaticStreakController::SetLEDsDirect(std::vector<led> leds, std::vector<RG
|
||||
|
||||
void FnaticStreakController::SendRGBToDevice()
|
||||
{
|
||||
unsigned int total_leds = GetLEDCount();
|
||||
unsigned int data_size = total_leds * 3;
|
||||
if(keyboard_type == FNATIC_STREAK_TYPE_65)
|
||||
{
|
||||
unsigned char data[64];
|
||||
memset(data, 0x00, sizeof(data));
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| For direct/software control, use command 0x0f |
|
||||
| This bypasses the profile and allows immediate update |
|
||||
| The 0x03 subcommand indicates per-key color data |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned char prefix[] = { 0x0f, 0x03 };
|
||||
SendRequest(prefix, sizeof(prefix), color_buf, data_size);
|
||||
data[0] = 0x0F;
|
||||
data[1] = 0x15;
|
||||
|
||||
data[7] = 0x0F;
|
||||
data[8] = 0x03;
|
||||
|
||||
for(unsigned int i = 9; i < 25; i++)
|
||||
{
|
||||
data[i] = 0xFF;
|
||||
}
|
||||
|
||||
data[25] = color_buf[0];
|
||||
data[26] = color_buf[1];
|
||||
data[27] = color_buf[2];
|
||||
|
||||
hid_write(dev, data, sizeof(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int total_leds = GetLEDCount();
|
||||
unsigned int data_size = total_leds * 3;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| For direct/software control, use command 0x0f |
|
||||
| This bypasses the profile and allows immediate update |
|
||||
| The 0x03 subcommand indicates per-key color data |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned char prefix[] = { 0x0f, 0x03 };
|
||||
SendRequest(prefix, sizeof(prefix), color_buf, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
void FnaticStreakController::SetPulse(unsigned char color_mode, unsigned char r, unsigned char g, unsigned char b, unsigned char speed)
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
enum FnaticStreakType
|
||||
{
|
||||
FNATIC_STREAK_TYPE_FULL,
|
||||
FNATIC_STREAK_TYPE_MINI
|
||||
FNATIC_STREAK_TYPE_MINI,
|
||||
FNATIC_STREAK_TYPE_65
|
||||
};
|
||||
|
||||
class FnaticStreakController
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#define FNATIC_STREAK_PID 0x0101
|
||||
#define FNATIC_MINISTREAK_PID 0x0102
|
||||
#define FNATIC_STREAK65_PID 0x0105
|
||||
|
||||
void DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
@@ -39,6 +40,10 @@ void DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
kb_type = FNATIC_STREAK_TYPE_MINI;
|
||||
}
|
||||
else if(info->product_id == FNATIC_STREAK65_PID)
|
||||
{
|
||||
kb_type = FNATIC_STREAK_TYPE_65;
|
||||
}
|
||||
else
|
||||
{
|
||||
kb_type = FNATIC_STREAK_TYPE_FULL;
|
||||
@@ -53,3 +58,4 @@ void DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
|
||||
|
||||
REGISTER_HID_DETECTOR_I("Fnatic Streak", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_STREAK_PID, 1);
|
||||
REGISTER_HID_DETECTOR_I("Fnatic miniStreak", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_MINISTREAK_PID, 1);
|
||||
REGISTER_HID_DETECTOR_I("Fnatic Streak65", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_STREAK65_PID, 1);
|
||||
|
||||
@@ -37,19 +37,22 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
|
||||
\*-----------------------------------------------------------------*/
|
||||
case 0x32:
|
||||
res = bus->i2c_smbus_read_byte_data(address, 0x00);
|
||||
if(res == 0x27 || res == 0x26) {
|
||||
if(res == 0x27 || res == 0x26)
|
||||
{
|
||||
res = bus->i2c_smbus_read_byte_data(address, 0x01);
|
||||
if (res == 0x10 || res == 0x20)
|
||||
if(res == 0x10 || res == 0x20)
|
||||
{
|
||||
pass = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| V1 Controller - RTX 3080 |
|
||||
| V1 Controller |
|
||||
\*-----------------------------------------------------------------*/
|
||||
case 0x23:
|
||||
res = bus->i2c_smbus_read_byte_data(address, 0x00);
|
||||
if(res == 0x30)
|
||||
if(res == 0x27 || res == 0x30)
|
||||
{
|
||||
pass = true;
|
||||
}
|
||||
@@ -60,8 +63,10 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
|
||||
\*-----------------------------------------------------------------*/
|
||||
case 0x51:
|
||||
res = bus->i2c_smbus_read_byte_data(address, 0x00);
|
||||
if (res == 0x80)
|
||||
if(res == 0x80)
|
||||
{
|
||||
pass = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -199,6 +199,7 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Gaming OC",
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_16G_SUB_DEV, 0x75);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellAorusWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER ICE", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_ICE_16G_SUB_DEV, 0x75);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV, 0x75);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV1, 0x75);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV2, 0x75);
|
||||
|
||||
@@ -194,6 +194,7 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7800 XT GAMING OC",
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 GRE GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900GRE_GAMING_OC_16G_SUB_DEV, 0x62);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XT_GAMING_OC_20G_SUB_DEV, 0x62);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XTX GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XTX_GAMING_OC_24G_SUB_DEV, 0x62);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 7900 XTX ELITE 24G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX7900XTX_ELITE_24G_SUB_DEV, 0x71);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6750 XT ELITE 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX_6750_XT_ELITE_12G_SUB_DEV, 0x70);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6900 XT EXTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, GIGABYTE_SUB_VEN, GIGABYTE_RX6900XT_XTREME_WATERFORCE_WB_SUB_DEV, 0x70);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 9070 XT Elite", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX9070XT_ELITE_16G_SUB_DEV, 0x73);
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXEve1800Controller.cpp |
|
||||
| |
|
||||
| Driver for HyperX Eve 1800 keyboard |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "HyperXEve1800Controller.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
HyperXEve1800Controller::HyperXEve1800Controller(hid_device* dev_handle, const char* path, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
HyperXEve1800Controller::~HyperXEve1800Controller()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string HyperXEve1800Controller::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string HyperXEve1800Controller::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string HyperXEve1800Controller::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 HyperXEve1800Controller::SetBrightness(unsigned int brightness)
|
||||
{
|
||||
unsigned char buf[65];
|
||||
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
|
||||
buf[0x00] = 0x40;
|
||||
buf[0x01] = 0x01;
|
||||
buf[0x02] = 0x00;
|
||||
buf[0x03] = 0x00;
|
||||
buf[0x04] = brightness & 0xFF;
|
||||
|
||||
hid_write(dev, buf, 65);
|
||||
}
|
||||
|
||||
void HyperXEve1800Controller::SetLEDsDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
SendDirectInitialization();
|
||||
|
||||
if(colors.empty())
|
||||
{
|
||||
RGBColor temp = 0x00000000;
|
||||
SendDirectColorPacket(&temp, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendDirectColorPacket(&colors[0], (unsigned int)colors.size());
|
||||
}
|
||||
}
|
||||
|
||||
void HyperXEve1800Controller::SendDirectInitialization()
|
||||
{
|
||||
unsigned char buf[65];
|
||||
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
|
||||
buf[0x00] = 0x44;
|
||||
buf[0x01] = 0x01;
|
||||
buf[0x02] = 0x04;
|
||||
buf[0x03] = 0x00;
|
||||
|
||||
hid_write(dev, buf, 65);
|
||||
}
|
||||
|
||||
void HyperXEve1800Controller::SendDirectColorPacket(RGBColor* color_data, unsigned int color_count)
|
||||
{
|
||||
unsigned char buf[65];
|
||||
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
|
||||
buf[0x00] = 0x44;
|
||||
buf[0x01] = 0x02;
|
||||
buf[0x02] = 0x00;
|
||||
buf[0x03] = 0x00;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| The Eve 1800 exposes 10 lighting zones, but this |
|
||||
| report format can carry up to 20 RGB triplets. |
|
||||
\*-----------------------------------------------------*/
|
||||
if(color_count > 20)
|
||||
{
|
||||
color_count = 20;
|
||||
}
|
||||
|
||||
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
|
||||
{
|
||||
buf[4 + (color_idx * 3)] = RGBGetRValue(color_data[color_idx]);
|
||||
buf[4 + (color_idx * 3) + 1] = RGBGetGValue(color_data[color_idx]);
|
||||
buf[4 + (color_idx * 3) + 2] = RGBGetBValue(color_data[color_idx]);
|
||||
}
|
||||
|
||||
hid_write(dev, buf, 65);
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXEve1800Controller.h |
|
||||
| |
|
||||
| Driver for HyperX Eve 1800 keyboard |
|
||||
| |
|
||||
| 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"
|
||||
|
||||
class HyperXEve1800Controller
|
||||
{
|
||||
public:
|
||||
HyperXEve1800Controller(hid_device* dev_handle, const char* path, std::string dev_name);
|
||||
~HyperXEve1800Controller();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SetBrightness(unsigned int brightness);
|
||||
void SetLEDsDirect(std::vector<RGBColor> colors);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
void SendDirectInitialization();
|
||||
void SendDirectColorPacket(RGBColor* color_data, unsigned int color_count);
|
||||
};
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_HyperXEve1800.cpp |
|
||||
| |
|
||||
| RGBController for HyperX Eve 1800 keyboard |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_HyperXEve1800.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define HYPERX_EVE_1800_BRIGHTNESS_MIN 0x00
|
||||
#define HYPERX_EVE_1800_BRIGHTNESS_MAX 0xFF
|
||||
#define HYPERX_EVE_1800_ZONE_COUNT 10
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name HyperX Eve 1800
|
||||
@category Keyboard
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectHyperXEve1800
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_HyperXEve1800::RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "HyperX";
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
description = "HyperX Eve 1800 Keyboard Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0xFFFF;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Direct.brightness_min = HYPERX_EVE_1800_BRIGHTNESS_MIN;
|
||||
Direct.brightness_max = HYPERX_EVE_1800_BRIGHTNESS_MAX;
|
||||
Direct.brightness = HYPERX_EVE_1800_BRIGHTNESS_MAX;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
|
||||
keepalive_thread_run = 1;
|
||||
keepalive_thread = new std::thread(&RGBController_HyperXEve1800::KeepaliveThread, this);
|
||||
}
|
||||
|
||||
RGBController_HyperXEve1800::~RGBController_HyperXEve1800()
|
||||
{
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = "Keyboard";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = HYPERX_EVE_1800_ZONE_COUNT;
|
||||
new_zone.leds_max = HYPERX_EVE_1800_ZONE_COUNT;
|
||||
new_zone.leds_count = HYPERX_EVE_1800_ZONE_COUNT;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "Zone ";
|
||||
new_led.name.append(std::to_string(led_idx + 1));
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->SetLEDsDirect(colors);
|
||||
last_update_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::DeviceUpdateMode()
|
||||
{
|
||||
controller->SetBrightness(modes[active_mode].brightness);
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_HyperXEve1800::KeepaliveThread()
|
||||
{
|
||||
while(keepalive_thread_run.load())
|
||||
{
|
||||
if(active_mode == 0)
|
||||
{
|
||||
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
|
||||
{
|
||||
UpdateLEDs();
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_HyperXEve1800.h |
|
||||
| |
|
||||
| RGBController for HyperX Eve 1800 keyboard |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "RGBController.h"
|
||||
#include "HyperXEve1800Controller.h"
|
||||
|
||||
class RGBController_HyperXEve1800 : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr);
|
||||
~RGBController_HyperXEve1800();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
void KeepaliveThread();
|
||||
|
||||
private:
|
||||
HyperXEve1800Controller* controller;
|
||||
std::thread* keepalive_thread;
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
|
||||
};
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "HyperXAlloyOriginsController.h"
|
||||
#include "HyperXAlloyOriginsCoreController.h"
|
||||
#include "HyperXAlloyOrigins60and65Controller.h"
|
||||
#include "HyperXEve1800Controller.h"
|
||||
#include "HyperXOrigins2_65Controller.h"
|
||||
#include "RGBController_HyperXAlloyElite.h"
|
||||
#include "RGBController_HyperXAlloyElite2.h"
|
||||
@@ -22,6 +23,7 @@
|
||||
#include "RGBController_HyperXAlloyOrigins.h"
|
||||
#include "RGBController_HyperXAlloyOriginsCore.h"
|
||||
#include "RGBController_HyperXAlloyOrigins60and65.h"
|
||||
#include "RGBController_HyperXEve1800.h"
|
||||
#include "RGBController_HyperXOrigins2_65.h"
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
@@ -46,6 +48,7 @@
|
||||
#define HYPERX_ALLOY_ORIGINS_65_HP_PID 0x038F
|
||||
#define HYPERX_ALLOY_ORIGINS_CORE_HP_PID 0x098F
|
||||
#define HYPERX_ALLOY_ORIGINS_HP_PID 0x0591
|
||||
#define HYPERX_EVE_1800_HP_PID 0x08C2
|
||||
#define HYPERX_ORIGINS_2_65_HP_PID 0x0CC2
|
||||
|
||||
AlloyOrigins60and65MappingLayoutType GetAlloyOrigins60and65MappingLayoutType(int pid)
|
||||
@@ -156,6 +159,19 @@ void DetectHyperXOrigins2_65(hid_device_info* info, const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
void DetectHyperXEve1800(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXEve1800Controller* controller = new HyperXEve1800Controller(dev, info->path, name);
|
||||
RGBController_HyperXEve1800* rgb_controller = new RGBController_HyperXEve1800(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite RGB", DetectHyperXAlloyElite, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_PID, 2, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy FPS RGB", DetectHyperXAlloyFPS, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_FPS_RGB_PID, 2, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOriginsCore, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 2);
|
||||
@@ -163,6 +179,7 @@ REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOrigi
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core (HP)", DetectHyperXAlloyOriginsCore, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_HP_PID, 2);
|
||||
|
||||
REGISTER_HID_DETECTOR_I("HyperX Origins 2 65 (HP)", DetectHyperXOrigins2_65, HP_KEYBOARD_VID, HYPERX_ORIGINS_2_65_HP_PID, 3);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Eve 1800 (HP)", DetectHyperXEve1800, HP_KEYBOARD_VID, HYPERX_EVE_1800_HP_PID, 2);
|
||||
|
||||
#ifdef _WIN32
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 3);
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MSILaptopController.cpp |
|
||||
| |
|
||||
| Driver for MSI laptop SteelSeries KLC/ALC RGB devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "MSILaptopController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
#define MSI_LAPTOP_REPORT_ID 0x00
|
||||
#define MSI_LAPTOP_COMMAND 0x0C
|
||||
#define MSI_LAPTOP_KLC_PACKET_ID 0x66
|
||||
#define MSI_LAPTOP_ALC_PACKET_ID 0x06
|
||||
#define MSI_LAPTOP_PACKET_SIZE 525
|
||||
#define MSI_LAPTOP_PAYLOAD_OFFSET 5
|
||||
|
||||
MSILaptopController::MSILaptopController(hid_device* dev_handle, const char* path, std::string dev_name, msi_laptop_device device_type)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
name = dev_name;
|
||||
type = device_type;
|
||||
}
|
||||
|
||||
MSILaptopController::~MSILaptopController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string MSILaptopController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string MSILaptopController::GetDeviceName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string MSILaptopController::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));
|
||||
}
|
||||
|
||||
msi_laptop_device MSILaptopController::GetDeviceType()
|
||||
{
|
||||
return(type);
|
||||
}
|
||||
|
||||
void MSILaptopController::SetLEDs(std::vector<led> leds, std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char buf[MSI_LAPTOP_PACKET_SIZE];
|
||||
unsigned int led_count = (leds.size() < colors.size()) ? leds.size() : colors.size();
|
||||
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
|
||||
buf[0x00] = MSI_LAPTOP_REPORT_ID;
|
||||
buf[0x01] = MSI_LAPTOP_COMMAND;
|
||||
buf[0x03] = (type == MSI_LAPTOP_KLC) ? MSI_LAPTOP_KLC_PACKET_ID : MSI_LAPTOP_ALC_PACKET_ID;
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
|
||||
{
|
||||
unsigned int offset = MSI_LAPTOP_PAYLOAD_OFFSET + (led_idx * 4);
|
||||
|
||||
if((offset + 3) >= sizeof(buf))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buf[offset + 0] = leds[led_idx].value;
|
||||
buf[offset + 1] = RGBGetRValue(colors[led_idx]);
|
||||
buf[offset + 2] = RGBGetGValue(colors[led_idx]);
|
||||
buf[offset + 3] = RGBGetBValue(colors[led_idx]);
|
||||
}
|
||||
|
||||
hid_send_feature_report(dev, buf, sizeof(buf));
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MSILaptopController.h |
|
||||
| |
|
||||
| Driver for MSI laptop SteelSeries KLC/ALC RGB devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MSI_LAPTOP_KLC,
|
||||
MSI_LAPTOP_ALC,
|
||||
|
||||
} msi_laptop_device;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* name;
|
||||
unsigned char id;
|
||||
|
||||
} msi_laptop_led;
|
||||
|
||||
struct MSILaptopModel
|
||||
{
|
||||
const char* sys_vendor;
|
||||
const char* product_name;
|
||||
|
||||
/* Keyboard layout */
|
||||
const msi_laptop_led* klc_leds;
|
||||
unsigned int klc_leds_count;
|
||||
unsigned int klc_matrix_height;
|
||||
unsigned int klc_matrix_width;
|
||||
const unsigned int* klc_matrix_map;
|
||||
|
||||
/* Lightbar layout */
|
||||
const msi_laptop_led* alc_leds;
|
||||
unsigned int alc_leds_count;
|
||||
unsigned int alc_lightbar_leds;
|
||||
};
|
||||
|
||||
class MSILaptopController
|
||||
{
|
||||
public:
|
||||
MSILaptopController(hid_device* dev_handle, const char* path, std::string dev_name, msi_laptop_device device_type);
|
||||
~MSILaptopController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetDeviceName();
|
||||
std::string GetSerialString();
|
||||
msi_laptop_device GetDeviceType();
|
||||
|
||||
void SetLEDs(std::vector<led> leds, std::vector<RGBColor> colors);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
msi_laptop_device type;
|
||||
};
|
||||
@@ -0,0 +1,225 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MSILaptopControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for MSI laptop SteelSeries RGB devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "Detector.h"
|
||||
#include "RGBControllerKeyNames.h"
|
||||
#include "RGBController_MSILaptop.h"
|
||||
#include "MSILaptopController.h"
|
||||
#include "dmiinfo.h"
|
||||
|
||||
#define MSI_LAPTOP_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define STEELSERIES_VID 0x1038
|
||||
#define STEELSERIES_MSI_RAIDER_A18_KLC_PID 0x1122
|
||||
#define STEELSERIES_MSI_RAIDER_A18_ALC_PID 0x1161
|
||||
|
||||
#define NA 0xFFFFFFFF
|
||||
#define MSI_LAPTOP_KLC_MATRIX_HEIGHT 6
|
||||
#define MSI_LAPTOP_KLC_MATRIX_WIDTH 23
|
||||
#define MSI_LAPTOP_ALC_LIGHTBAR_LEDS 5
|
||||
|
||||
static const msi_laptop_led msi_raider_a18_klc_leds[] =
|
||||
{
|
||||
{ KEY_EN_A, 0x04 },
|
||||
{ KEY_EN_B, 0x05 },
|
||||
{ KEY_EN_C, 0x06 },
|
||||
{ KEY_EN_D, 0x07 },
|
||||
{ KEY_EN_E, 0x08 },
|
||||
{ KEY_EN_F, 0x09 },
|
||||
{ KEY_EN_G, 0x0A },
|
||||
{ KEY_EN_H, 0x0B },
|
||||
{ KEY_EN_I, 0x0C },
|
||||
{ KEY_EN_J, 0x0D },
|
||||
{ KEY_EN_K, 0x0E },
|
||||
{ KEY_EN_L, 0x0F },
|
||||
{ KEY_EN_M, 0x10 },
|
||||
{ KEY_EN_N, 0x11 },
|
||||
{ KEY_EN_O, 0x12 },
|
||||
{ KEY_EN_P, 0x13 },
|
||||
{ KEY_EN_Q, 0x14 },
|
||||
{ KEY_EN_R, 0x15 },
|
||||
{ KEY_EN_S, 0x16 },
|
||||
{ KEY_EN_T, 0x17 },
|
||||
{ KEY_EN_U, 0x18 },
|
||||
{ KEY_EN_V, 0x19 },
|
||||
{ KEY_EN_W, 0x1A },
|
||||
{ KEY_EN_X, 0x1B },
|
||||
{ KEY_EN_Y, 0x1C },
|
||||
{ KEY_EN_Z, 0x1D },
|
||||
{ KEY_EN_1, 0x1E },
|
||||
{ KEY_EN_2, 0x1F },
|
||||
{ KEY_EN_3, 0x20 },
|
||||
{ KEY_EN_4, 0x21 },
|
||||
{ KEY_EN_5, 0x22 },
|
||||
{ KEY_EN_6, 0x23 },
|
||||
{ KEY_EN_7, 0x24 },
|
||||
{ KEY_EN_8, 0x25 },
|
||||
{ KEY_EN_9, 0x26 },
|
||||
{ KEY_EN_0, 0x27 },
|
||||
{ KEY_EN_ESCAPE, 0x29 },
|
||||
{ KEY_EN_TAB, 0x2B },
|
||||
{ KEY_EN_SPACE, 0x2C },
|
||||
{ KEY_EN_MINUS, 0x2D },
|
||||
{ KEY_EN_EQUALS, 0x2E },
|
||||
{ KEY_EN_LEFT_BRACKET, 0x2F },
|
||||
{ KEY_EN_RIGHT_BRACKET, 0x30 },
|
||||
{ KEY_EN_SEMICOLON, 0x33 },
|
||||
{ KEY_EN_QUOTE, 0x34 },
|
||||
{ KEY_EN_BACK_TICK, 0x35 },
|
||||
{ KEY_EN_COMMA, 0x36 },
|
||||
{ KEY_EN_PERIOD, 0x37 },
|
||||
{ KEY_EN_FORWARD_SLASH, 0x38 },
|
||||
{ KEY_EN_CAPS_LOCK, 0x39 },
|
||||
{ KEY_EN_F1, 0x3A },
|
||||
{ KEY_EN_F2, 0x3B },
|
||||
{ KEY_EN_F3, 0x3C },
|
||||
{ KEY_EN_F4, 0x3D },
|
||||
{ KEY_EN_F5, 0x3E },
|
||||
{ KEY_EN_F6, 0x3F },
|
||||
{ KEY_EN_F7, 0x40 },
|
||||
{ KEY_EN_F8, 0x41 },
|
||||
{ KEY_EN_F9, 0x42 },
|
||||
{ KEY_EN_F10, 0x43 },
|
||||
{ KEY_EN_F11, 0x44 },
|
||||
{ KEY_EN_F12, 0x45 },
|
||||
{ KEY_EN_PRINT_SCREEN, 0x46 },
|
||||
{ KEY_EN_SCROLL_LOCK, 0x47 },
|
||||
{ KEY_EN_INSERT, 0x49 },
|
||||
{ "Home/Page Up", 0x4B },
|
||||
{ KEY_EN_DELETE, 0x4C },
|
||||
{ KEY_EN_PAGE_DOWN, 0x4E },
|
||||
{ KEY_EN_RIGHT_ARROW, 0x4F },
|
||||
{ KEY_EN_LEFT_ARROW, 0x50 },
|
||||
{ KEY_EN_DOWN_ARROW, 0x51 },
|
||||
{ KEY_EN_UP_ARROW, 0x52 },
|
||||
{ KEY_EN_NUMPAD_LOCK, 0x53 },
|
||||
{ KEY_EN_NUMPAD_DIVIDE, 0x54 },
|
||||
{ KEY_EN_NUMPAD_TIMES, 0x55 },
|
||||
{ KEY_EN_NUMPAD_MINUS, 0x56 },
|
||||
{ KEY_EN_NUMPAD_PLUS, 0x57 },
|
||||
{ KEY_EN_NUMPAD_ENTER, 0x58 },
|
||||
{ KEY_EN_NUMPAD_1, 0x59 },
|
||||
{ KEY_EN_NUMPAD_2, 0x5A },
|
||||
{ KEY_EN_NUMPAD_3, 0x5B },
|
||||
{ KEY_EN_NUMPAD_4, 0x5C },
|
||||
{ KEY_EN_NUMPAD_5, 0x5D },
|
||||
{ KEY_EN_NUMPAD_6, 0x5E },
|
||||
{ KEY_EN_NUMPAD_7, 0x5F },
|
||||
{ KEY_EN_NUMPAD_8, 0x60 },
|
||||
{ KEY_EN_NUMPAD_9, 0x61 },
|
||||
{ KEY_EN_NUMPAD_0, 0x62 },
|
||||
{ KEY_EN_NUMPAD_PERIOD, 0x63 },
|
||||
{ KEY_EN_POWER, 0x66 },
|
||||
{ KEY_EN_LEFT_CONTROL, 0xE0 },
|
||||
{ KEY_EN_LEFT_SHIFT, 0xE1 },
|
||||
{ KEY_EN_LEFT_ALT, 0xE2 },
|
||||
{ KEY_EN_LEFT_WINDOWS, 0xE3 },
|
||||
{ KEY_EN_RIGHT_WINDOWS, 0xE4 },
|
||||
{ KEY_EN_RIGHT_FUNCTION, 0xF0 },
|
||||
{ KEY_EN_ANSI_ENTER, 0x28 },
|
||||
{ KEY_EN_BACKSPACE, 0x2A },
|
||||
{ KEY_EN_BACK_SLASH, 0x31 },
|
||||
{ KEY_EN_ISO_BACK_SLASH, 0x64 },
|
||||
{ KEY_EN_RIGHT_SHIFT, 0xE5 },
|
||||
{ KEY_EN_RIGHT_ALT, 0xE6 },
|
||||
};
|
||||
|
||||
static unsigned int msi_raider_a18_klc_matrix_map[MSI_LAPTOP_KLC_MATRIX_HEIGHT][MSI_LAPTOP_KLC_MATRIX_WIDTH] =
|
||||
{
|
||||
{ 36, NA, 50, 51, 52, 53, NA, 54, 55, 56, 57, NA, 58, 59, 60, 61, 62, 63, NA, NA, NA, NA, 89 },
|
||||
{ 45, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 39, 40, 97, NA, 64, 65, NA, 72, 73, 74, 75, NA },
|
||||
{ 37, 16, 22, 4, 17, 19, 24, 20, 8, 14, 15, 41, 42, 98, NA, 66, 67, NA, 84, 85, 86, 76, NA },
|
||||
{ 49, 0, 18, 3, 5, 6, 7, 9, 10, 11, 43, 44, 96, NA, NA, NA, NA, NA, 81, 82, 83, NA, NA },
|
||||
{ 91, 25, 23, 2, 21, 1, 13, 12, 46, 47, 48,100, NA, NA, NA, NA, 71, NA, 78, 79, 80, 77, NA },
|
||||
{ 90, 93, 92, NA, NA, NA, 38, NA, NA, NA,101, 94, 95, NA, 69, 70, 68, NA, 87, NA, 88, NA, NA },
|
||||
};
|
||||
|
||||
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 },
|
||||
};
|
||||
|
||||
static const MSILaptopModel msi_laptop_models[] =
|
||||
{
|
||||
{
|
||||
"Micro-Star International Co., Ltd.",
|
||||
"Raider A18 HX A9WJG",
|
||||
|
||||
/* Keyboard layout */
|
||||
msi_raider_a18_klc_leds,
|
||||
MSI_LAPTOP_ARRAY_SIZE(msi_raider_a18_klc_leds),
|
||||
MSI_LAPTOP_KLC_MATRIX_HEIGHT,
|
||||
MSI_LAPTOP_KLC_MATRIX_WIDTH,
|
||||
(const unsigned int*)msi_raider_a18_klc_matrix_map,
|
||||
|
||||
/* Lightbar layout */
|
||||
msi_raider_a18_alc_leds,
|
||||
MSI_LAPTOP_ARRAY_SIZE(msi_raider_a18_alc_leds),
|
||||
MSI_LAPTOP_ALC_LIGHTBAR_LEDS,
|
||||
},
|
||||
};
|
||||
|
||||
static const MSILaptopModel* GetMSILaptopModelDMI()
|
||||
{
|
||||
DMIInfo dmi;
|
||||
|
||||
for(unsigned int i = 0; i < MSI_LAPTOP_ARRAY_SIZE(msi_laptop_models); i++)
|
||||
{
|
||||
if((dmi.getManufacturer() == msi_laptop_models[i].sys_vendor) &&
|
||||
(dmi.getProductName() == msi_laptop_models[i].product_name))
|
||||
{
|
||||
return &msi_laptop_models[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DetectMSILaptop(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
const MSILaptopModel* model = GetMSILaptopModelDMI();
|
||||
if(!model)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
msi_laptop_device device_type;
|
||||
|
||||
if(info->product_id == STEELSERIES_MSI_RAIDER_A18_KLC_PID)
|
||||
{
|
||||
device_type = MSI_LAPTOP_KLC;
|
||||
}
|
||||
else if(info->product_id == STEELSERIES_MSI_RAIDER_A18_ALC_PID)
|
||||
{
|
||||
device_type = MSI_LAPTOP_ALC;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
MSILaptopController* controller = new MSILaptopController(dev, info->path, name, device_type);
|
||||
RGBController_MSILaptop* rgb_controller = new RGBController_MSILaptop(controller, model);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_I("MSI Laptop Keyboard", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_KLC_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("MSI Laptop Lightbar", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_ALC_PID, 0);
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSILaptop.cpp |
|
||||
| |
|
||||
| RGBController for MSI laptop SteelSeries RGB devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBControllerKeyNames.h"
|
||||
#include "RGBController_MSILaptop.h"
|
||||
|
||||
#define NA 0xFFFFFFFF
|
||||
/**------------------------------------------------------------------*\
|
||||
@name MSI Laptop SteelSeries RGB
|
||||
@category Keyboard
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectMSILaptop
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_MSILaptop::RGBController_MSILaptop(MSILaptopController* controller_ptr, const MSILaptopModel* model_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
model = model_ptr;
|
||||
|
||||
name = controller->GetDeviceName();
|
||||
vendor = "SteelSeries";
|
||||
description = std::string(model->sys_vendor) + " " + std::string(model->product_name) + " RGB Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
type = (controller->GetDeviceType() == MSI_LAPTOP_KLC) ? DEVICE_TYPE_KEYBOARD : DEVICE_TYPE_LEDSTRIP;
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_MSILaptop::~RGBController_MSILaptop()
|
||||
{
|
||||
for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
if(zones[zone_idx].matrix_map != NULL)
|
||||
{
|
||||
delete zones[zone_idx].matrix_map;
|
||||
}
|
||||
}
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_MSILaptop::SetupZones()
|
||||
{
|
||||
if(controller->GetDeviceType() == MSI_LAPTOP_KLC)
|
||||
{
|
||||
zone keyboard_zone;
|
||||
|
||||
keyboard_zone.name = ZONE_EN_KEYBOARD;
|
||||
keyboard_zone.type = ZONE_TYPE_MATRIX;
|
||||
keyboard_zone.leds_min = model->klc_leds_count;
|
||||
keyboard_zone.leds_max = model->klc_leds_count;
|
||||
keyboard_zone.leds_count = model->klc_leds_count;
|
||||
keyboard_zone.matrix_map = new matrix_map_type;
|
||||
keyboard_zone.matrix_map->height = model->klc_matrix_height;
|
||||
keyboard_zone.matrix_map->width = model->klc_matrix_width;
|
||||
keyboard_zone.matrix_map->map = (unsigned int *)model->klc_matrix_map;
|
||||
|
||||
zones.push_back(keyboard_zone);
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < model->klc_leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = model->klc_leds[led_idx].name;
|
||||
new_led.value = model->klc_leds[led_idx].id;
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
zone lightbar_zone;
|
||||
lightbar_zone.name = "Lightbar";
|
||||
lightbar_zone.type = ZONE_TYPE_LINEAR;
|
||||
lightbar_zone.start_idx = 0;
|
||||
lightbar_zone.leds_min = model->alc_lightbar_leds;
|
||||
lightbar_zone.leds_max = model->alc_lightbar_leds;
|
||||
lightbar_zone.leds_count = model->alc_lightbar_leds;
|
||||
lightbar_zone.matrix_map = NULL;
|
||||
zones.push_back(lightbar_zone);
|
||||
|
||||
zone logo_zone;
|
||||
logo_zone.name = "Logo";
|
||||
logo_zone.type = ZONE_TYPE_SINGLE;
|
||||
logo_zone.start_idx = model->alc_lightbar_leds;
|
||||
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(unsigned int led_idx = 0; led_idx < model->alc_leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = model->alc_leds[led_idx].name;
|
||||
new_led.value = model->alc_leds[led_idx].id;
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_MSILaptop::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
}
|
||||
|
||||
void RGBController_MSILaptop::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->SetLEDs(leds, colors);
|
||||
}
|
||||
|
||||
void RGBController_MSILaptop::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_MSILaptop::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_MSILaptop::DeviceUpdateMode()
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSILaptop.h |
|
||||
| |
|
||||
| RGBController for MSI laptop SteelSeries RGB devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "MSILaptopController.h"
|
||||
|
||||
class RGBController_MSILaptop : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_MSILaptop(MSILaptopController* controller_ptr, const MSILaptopModel* model_ptr);
|
||||
~RGBController_MSILaptop();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
MSILaptopController* controller;
|
||||
const MSILaptopModel* model;
|
||||
};
|
||||
@@ -0,0 +1,303 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RealtekBridge.cpp |
|
||||
| |
|
||||
| Controller for Realtek USB to SSD Bridge 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_RealtekBridge.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Realtek Bridge Device
|
||||
@category Storage
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :rotating_light:
|
||||
@effects :white_check_mark:
|
||||
@detectors RealtekBridgeControllerDetect
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RealtekBridge::RGBController_RealtekBridge(RealtekBridgeController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
name = controller_ptr->get_product_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 + "Storage Device";
|
||||
type = DEVICE_TYPE_STORAGE;
|
||||
|
||||
SetupModes();
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RealtekBridge::~RGBController_RealtekBridge()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::SetupModes()
|
||||
{
|
||||
int brightness = controller->get_argb_brightness() >> 8;
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = REALTEK_BRIDGE_LED_EFF_NONE;
|
||||
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_BRIDGE_LED_EFF_ALWAYS;
|
||||
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_BRIDGE_LED_EFF_BLINK;
|
||||
Blink.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Blink.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
Blink.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
Blink.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
Blink.colors_min = 1;
|
||||
Blink.colors_max = 1;
|
||||
Blink.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Blink.colors.resize(1);
|
||||
Blink.brightness_min = 0;
|
||||
Blink.brightness_max = 255;
|
||||
Blink.brightness = brightness;
|
||||
modes.push_back(Blink);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = REALTEK_BRIDGE_LED_EFF_BREATHE;
|
||||
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Breathing.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
Breathing.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
Breathing.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
Breathing.colors_min = 1;
|
||||
Breathing.colors_max = 1;
|
||||
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Breathing.colors.resize(1);
|
||||
Breathing.brightness_min = 0;
|
||||
Breathing.brightness_max = 255;
|
||||
Breathing.brightness = brightness;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Spectrum;
|
||||
Spectrum.name = "Spectrum";
|
||||
Spectrum.value = REALTEK_BRIDGE_LED_EFF_SPECTRUM;
|
||||
Spectrum.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Spectrum.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
Spectrum.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
Spectrum.speed = REALTEK_BRIDGE_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_BRIDGE_LED_EFF_SCROLL;
|
||||
Scroll.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Scroll.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
Scroll.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
Scroll.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
Scroll.colors_min = 1;
|
||||
Scroll.colors_max = 1;
|
||||
Scroll.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Scroll.colors.resize(1);
|
||||
Scroll.brightness_min = 0;
|
||||
Scroll.brightness_max = 255;
|
||||
Scroll.brightness = brightness;
|
||||
modes.push_back(Scroll);
|
||||
|
||||
mode RainbowScroll;
|
||||
RainbowScroll.name = "Rainbow Scroll";
|
||||
RainbowScroll.value = REALTEK_BRIDGE_LED_EFF_RAINBOW_SCROLL;
|
||||
RainbowScroll.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
RainbowScroll.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
RainbowScroll.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
RainbowScroll.speed = REALTEK_BRIDGE_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_BRIDGE_LED_EFF_RUNNING_WATER;
|
||||
RunningWater.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
RunningWater.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
RunningWater.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
RunningWater.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
RunningWater.colors_min = 1;
|
||||
RunningWater.colors_max = 1;
|
||||
RunningWater.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
RunningWater.colors.resize(1);
|
||||
RunningWater.brightness_min = 0;
|
||||
RunningWater.brightness_max = 255;
|
||||
RunningWater.brightness = brightness;
|
||||
modes.push_back(RunningWater);
|
||||
|
||||
mode Sliding;
|
||||
Sliding.name = "Sliding";
|
||||
Sliding.value = REALTEK_BRIDGE_LED_EFF_SLIDING;
|
||||
Sliding.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Sliding.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
Sliding.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
Sliding.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
Sliding.color_mode = MODE_COLORS_NONE;
|
||||
Sliding.brightness_min = 0;
|
||||
Sliding.brightness_max = 255;
|
||||
Sliding.brightness = brightness;
|
||||
modes.push_back(Sliding);
|
||||
|
||||
mode NewtonCradle;
|
||||
NewtonCradle.name = "Newton Cradle";
|
||||
NewtonCradle.value = REALTEK_BRIDGE_LED_EFF_NEWTON_CRADLE;
|
||||
NewtonCradle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
NewtonCradle.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
NewtonCradle.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
NewtonCradle.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
NewtonCradle.color_mode = MODE_COLORS_NONE;
|
||||
NewtonCradle.brightness_min = 0;
|
||||
NewtonCradle.brightness_max = 255;
|
||||
NewtonCradle.brightness = brightness;
|
||||
modes.push_back(NewtonCradle);
|
||||
|
||||
mode Meteor;
|
||||
Meteor.name = "Meteor";
|
||||
Meteor.value = REALTEK_BRIDGE_LED_EFF_METEOR;
|
||||
Meteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Meteor.speed_min = REALTEK_BRIDGE_SPEED_MIN;
|
||||
Meteor.speed_max = REALTEK_BRIDGE_SPEED_MAX;
|
||||
Meteor.speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
Meteor.colors_min = 1;
|
||||
Meteor.colors_max = 1;
|
||||
Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Meteor.colors.resize(1);
|
||||
Meteor.brightness_min = 0;
|
||||
Meteor.brightness_max = 255;
|
||||
Meteor.brightness = brightness;
|
||||
modes.push_back(Meteor);
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::SetupZones()
|
||||
{
|
||||
zone argb_zone;
|
||||
|
||||
argb_zone.name = "strip";
|
||||
argb_zone.type = ZONE_TYPE_LINEAR;
|
||||
argb_zone.leds_min = controller->get_argb_num();
|
||||
argb_zone.leds_max = controller->get_argb_num();
|
||||
argb_zone.leds_count = controller->get_argb_num();
|
||||
argb_zone.matrix_map = NULL;
|
||||
|
||||
zones.push_back(argb_zone);
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < argb_zone.leds_count; led_idx++)
|
||||
{
|
||||
led StripLED;
|
||||
StripLED.name = "led ";
|
||||
StripLED.name.append(std::to_string(led_idx + 1));
|
||||
leds.push_back(StripLED);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::DeviceUpdateLEDs()
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
unsigned short brightness = 0xFF;
|
||||
mode& curr_mode = modes[active_mode];
|
||||
|
||||
if(curr_mode.color_mode == MODE_COLORS_PER_LED &&
|
||||
curr_mode.value == REALTEK_BRIDGE_LED_EFF_NONE) //direct mode
|
||||
{
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_BRIGHTNESS)
|
||||
{
|
||||
brightness = curr_mode.brightness;
|
||||
}
|
||||
controller->set_argb_direct(colors, brightness);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSingleLED(0);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
unsigned char speed = REALTEK_BRIDGE_SPEED_NORMAL;
|
||||
unsigned char dir = 0;
|
||||
unsigned short brightness = 0xFF;
|
||||
mode& curr_mode = modes[active_mode];
|
||||
std::vector<RGBColor> rtk_colors = curr_mode.colors;
|
||||
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_SPEED)
|
||||
{
|
||||
speed = curr_mode.speed;
|
||||
}
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_BRIGHTNESS)
|
||||
{
|
||||
brightness = curr_mode.brightness;
|
||||
}
|
||||
if(curr_mode.flags & MODE_FLAG_HAS_DIRECTION_LR)
|
||||
{
|
||||
if(curr_mode.direction == MODE_DIRECTION_RIGHT)
|
||||
{
|
||||
dir = 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(curr_mode.value, rtk_colors, speed, brightness);
|
||||
}
|
||||
|
||||
void RGBController_RealtekBridge::DeviceUpdateMode()
|
||||
{
|
||||
if(modes[active_mode].value != REALTEK_BRIDGE_LED_EFF_NONE)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RealtekBridge.h |
|
||||
| |
|
||||
| Controller for Realtek USB to SSD Bridge 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 "RealtekBridgeController.h"
|
||||
|
||||
class RGBController_RealtekBridge : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RealtekBridge(RealtekBridgeController* controller_ptr);
|
||||
~RGBController_RealtekBridge();
|
||||
|
||||
void SetupModes();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RealtekBridgeController* controller;
|
||||
};
|
||||
@@ -0,0 +1,802 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RealtekBridgeController.cpp |
|
||||
| |
|
||||
| Controller for Realtek USB to SSD Bridge ICs |
|
||||
| |
|
||||
| Jerry Fan (JerryFan0612) 13 Mar 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RealtekBridgeController.h"
|
||||
#include "hsv.h"
|
||||
#include <StringUtils.h>
|
||||
#include <MathUtils.h>
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
RealtekBridgeController::RealtekBridgeController(hid_device* dev, hid_device_info* info)
|
||||
{
|
||||
hdev = dev;
|
||||
hidinfo = info;
|
||||
brctl_data = (unsigned char*)calloc(REALTEK_BRIDGE_CTL_DATA_SIZE, 1);
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
|
||||
set_write_unlock();
|
||||
get_brctl_hdr();
|
||||
get_brctl_data();
|
||||
set_appctl(true);
|
||||
}
|
||||
|
||||
RealtekBridgeController::~RealtekBridgeController()
|
||||
{
|
||||
if(hdev)
|
||||
{
|
||||
set_appctl(false);
|
||||
hid_close(hdev);
|
||||
hdev = NULL;
|
||||
}
|
||||
memset(brctl_hdr, 0, REALTEK_BRIDGE_CTL_HDR_SIZE);
|
||||
free(brctl_data);
|
||||
}
|
||||
|
||||
int RealtekBridgeController::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(!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 RealtekBridgeController::usb_hid_get_report(int data_len, int* id)
|
||||
{
|
||||
int retlen = 0;
|
||||
|
||||
if(data_len <= REALTEK_BRIDGE_HID_DATALEN_CH2)
|
||||
{
|
||||
*id = REALTEK_BRIDGE_HID_ID_DATA_CH2;
|
||||
retlen = REALTEK_BRIDGE_HID_DATALEN_CH2;
|
||||
}
|
||||
else if(data_len <= REALTEK_BRIDGE_HID_DATALEN_CH3)
|
||||
{
|
||||
*id = REALTEK_BRIDGE_HID_ID_DATA_CH3;
|
||||
retlen = REALTEK_BRIDGE_HID_DATALEN_CH3;
|
||||
}
|
||||
else if(data_len <= REALTEK_BRIDGE_HID_DATALEN_CH4)
|
||||
{
|
||||
*id = REALTEK_BRIDGE_HID_ID_DATA_CH4;
|
||||
retlen = REALTEK_BRIDGE_HID_DATALEN_CH4;
|
||||
}
|
||||
else if(data_len <= REALTEK_BRIDGE_HID_DATALEN_CH5)
|
||||
{
|
||||
*id = REALTEK_BRIDGE_HID_ID_DATA_CH5;
|
||||
retlen = REALTEK_BRIDGE_HID_DATALEN_CH5;
|
||||
}
|
||||
else
|
||||
{
|
||||
*id = REALTEK_BRIDGE_HID_ID_DATA_CH1;
|
||||
retlen = REALTEK_BRIDGE_HID_DATALEN_CH1;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_write_unlock()
|
||||
{
|
||||
int ret = 0;
|
||||
int buf_len = REALTEK_BRIDGE_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;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::get_brctl_hdr()
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_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, brctl_hdr, REALTEK_BRIDGE_CTL_HDR_SIZE, 0, true);
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_brctl_hdr()
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_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] = 0x02;
|
||||
return usb_hid_ioctl(usb_buf, brctl_hdr, REALTEK_BRIDGE_CTL_HDR_SIZE, 0, false);
|
||||
}
|
||||
|
||||
int RealtekBridgeController::get_brctl_data()
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_HID_DATALEN_CH1;
|
||||
int offset = REALTEK_BRIDGE_CTL_HDR_SIZE;
|
||||
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;
|
||||
memcpy(&usb_buf[0x17], &offset, sizeof(offset));
|
||||
return usb_hid_ioctl(usb_buf, brctl_data, REALTEK_BRIDGE_CTL_DATA_SIZE, 0, true);
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_brctl_data()
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_HID_DATALEN_CH1;
|
||||
int offset = REALTEK_BRIDGE_CTL_HDR_SIZE;
|
||||
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] = 0x02;
|
||||
memcpy(&usb_buf[0x17], &offset, sizeof(offset));
|
||||
return usb_hid_ioctl(usb_buf, brctl_data, REALTEK_BRIDGE_CTL_DATA_SIZE, 0, false);
|
||||
}
|
||||
|
||||
unsigned char RealtekBridgeController::get_support_openrgb()
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_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_BRIDGE_SYNC_METHOD_OPENRGB;
|
||||
if(usb_hid_ioctl(usb_buf, &is_support, sizeof(is_support), 0, true))
|
||||
{
|
||||
is_support = 0;
|
||||
}
|
||||
return is_support;
|
||||
}
|
||||
|
||||
std::string RealtekBridgeController::get_manu_name()
|
||||
{
|
||||
return StringUtils::wchar_to_char(hidinfo->manufacturer_string);
|
||||
}
|
||||
|
||||
std::string RealtekBridgeController::get_product_name()
|
||||
{
|
||||
return StringUtils::wchar_to_char(hidinfo->product_string);
|
||||
}
|
||||
|
||||
std::string RealtekBridgeController::get_sn()
|
||||
{
|
||||
return StringUtils::wchar_to_char(hidinfo->serial_number);
|
||||
}
|
||||
|
||||
std::string RealtekBridgeController::get_dev_loc()
|
||||
{
|
||||
return hidinfo->path;
|
||||
}
|
||||
|
||||
std::string RealtekBridgeController::get_fw_ver()
|
||||
{
|
||||
struct RealtekBridgeControllerFWVersion fw_ver;
|
||||
std::string ver = "";
|
||||
int buf_len = REALTEK_BRIDGE_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;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::get_argb_num()
|
||||
{
|
||||
int num_rgb = 0;
|
||||
memcpy(&num_rgb, &brctl_hdr[24], sizeof(num_rgb));
|
||||
|
||||
return num_rgb;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::get_argb_brightness()
|
||||
{
|
||||
int bright = 0;
|
||||
memcpy(&bright, &brctl_hdr[28], 2);
|
||||
|
||||
return bright;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_argb_brightness(unsigned short bright)
|
||||
{
|
||||
memcpy(&brctl_hdr[28], &bright, sizeof(bright));
|
||||
set_brctl_hdr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_appctl(unsigned char ctl_sts)
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_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;
|
||||
return usb_hid_ioctl(usb_buf, &ctl_sts, sizeof(ctl_sts), 0, false);
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_direct(unsigned char* color, int color_num)
|
||||
{
|
||||
int buf_len = REALTEK_BRIDGE_HID_DATALEN_CH1;
|
||||
int data_len = color_num * REALTEK_BRIDGE_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_BRIDGE_SYNC_METHOD_OPENRGB;
|
||||
memcpy(&usb_buf[0x17], &color_num, sizeof(color_num));
|
||||
return usb_hid_ioctl(usb_buf, color, data_len, 0, false);
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_always_on(RGBColor rgb)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int row = 1;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 1;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
|
||||
for(j = 0; j < row; j++)
|
||||
{
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_blink(RGBColor rgb, int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int row = 2;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 2;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 1;
|
||||
|
||||
for(j = 0; j < row; j++)
|
||||
{
|
||||
if((j & 0x1) == 0)
|
||||
{
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_breathe(RGBColor rgb, int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int row = 2;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 4;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 2;
|
||||
|
||||
for(j = 0; j < row; j++)
|
||||
{
|
||||
if((j & 0x1) == 0)
|
||||
{
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_spectrum(int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int row = 6;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
static const RGBColor rainbow_table[6] = {0x0000FF, 0x0050FF, 0x0080FF, 0x00FF00, 0xFF0000, 0xFF0080};
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 4;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 3;
|
||||
|
||||
for(j = 0; j < row; j++)
|
||||
{
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rainbow_table[j]);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rainbow_table[j]);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rainbow_table[j]);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_scroll(RGBColor rgb, int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int start_idx = -1;
|
||||
int row = get_argb_num() * 2 - 2;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 2;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 4;
|
||||
|
||||
if(start_idx == -1)
|
||||
{
|
||||
start_idx = i;
|
||||
}
|
||||
j = i - start_idx;
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
if(i != start_idx)
|
||||
{
|
||||
j = row - (i - start_idx);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_rainbow_scroll(int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int start_idx = -1;
|
||||
int row = get_argb_num() * 2 - 2;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
RGBColor slide_table[REALTEK_BRIDGE_MAX_ARGB_NUM] = {0};
|
||||
hsv_t hsv_color;
|
||||
|
||||
hsv_color.saturation = 255;
|
||||
hsv_color.value = 255;
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
hsv_color.hue = (i % get_argb_num()) * (360 / get_argb_num());
|
||||
slide_table[i] = hsv2rgb(&hsv_color);
|
||||
}
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 2;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 0x85;
|
||||
|
||||
if(start_idx == -1)
|
||||
{
|
||||
start_idx = i;
|
||||
}
|
||||
j = i - start_idx;
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(slide_table[i]);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(slide_table[i]);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(slide_table[i]);
|
||||
if(i != start_idx)
|
||||
{
|
||||
j = row - (i - start_idx);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(slide_table[i]);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(slide_table[i]);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(slide_table[i]);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_running_water(RGBColor rgb, int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int start_idx = -1;
|
||||
int row = get_argb_num() * 2;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 2;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 5;
|
||||
|
||||
if(start_idx == -1)
|
||||
{
|
||||
start_idx = i;
|
||||
}
|
||||
|
||||
for(j = i - start_idx; j < row / 2; j++)
|
||||
{
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_sliding(int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int start_idx = -1;
|
||||
int row = get_argb_num();
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
RGBColor slide_table[REALTEK_BRIDGE_MAX_ARGB_NUM] = {0};
|
||||
RGBColor rgb = 0;
|
||||
hsv_t hsv_color;
|
||||
|
||||
hsv_color.saturation = 255;
|
||||
hsv_color.value = 255;
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
hsv_color.hue = (i % get_argb_num()) * (360 / get_argb_num());
|
||||
slide_table[i] = hsv2rgb(&hsv_color);
|
||||
}
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 4;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 0x83;
|
||||
|
||||
if(start_idx == -1)
|
||||
{
|
||||
start_idx = i;
|
||||
}
|
||||
|
||||
for(j = 0; j < row; j++)
|
||||
{
|
||||
rgb = slide_table[(i - start_idx + j) % row];
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_newton_cradle(int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int start_idx = -1;
|
||||
int row;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
RGBColor rgb = 0;
|
||||
static const int const_ball_num = 3;
|
||||
static const RGBColor ball_color[] = {0x0080FF, 0x0000FF, 0x00FF00, 0xFF0000};
|
||||
static const int mid = get_argb_num() >> 1;
|
||||
|
||||
if(get_argb_num() <= const_ball_num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
row = (get_argb_num() - const_ball_num) * 2;
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 2;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
memcpy(&brctl_data[i * single_size + 2], &cycle, 2);
|
||||
brctl_data[i * single_size + 8] = 0x84;
|
||||
|
||||
if(start_idx == -1)
|
||||
{
|
||||
start_idx = i;
|
||||
}
|
||||
|
||||
for(j = 0; j < row; j++)
|
||||
{
|
||||
rgb = 0;
|
||||
if(i - start_idx > mid - 2 &&
|
||||
i - start_idx < mid + 2)
|
||||
{
|
||||
if(j < mid - 1 || j > row - mid)
|
||||
{
|
||||
if(i - start_idx == mid - 1)
|
||||
{
|
||||
rgb = ball_color[1];
|
||||
}
|
||||
else if(i - start_idx == mid)
|
||||
{
|
||||
rgb = ball_color[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb = ball_color[3];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i - start_idx == mid - 1)
|
||||
{
|
||||
rgb = ball_color[0];
|
||||
}
|
||||
else if(i - start_idx == mid)
|
||||
{
|
||||
rgb = ball_color[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb = ball_color[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(i - start_idx < mid)
|
||||
{
|
||||
if(i - start_idx == j || i - start_idx + j == row - 1)
|
||||
{
|
||||
rgb = ball_color[0];
|
||||
}
|
||||
}
|
||||
else if(i - start_idx > mid + 1)
|
||||
{
|
||||
if(i - start_idx - j == const_ball_num ||
|
||||
i - start_idx + j == row - 1 + const_ball_num)
|
||||
{
|
||||
rgb = ball_color[3];
|
||||
}
|
||||
}
|
||||
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::eff_set_meteor(RGBColor rgb, int cycle)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int row = 2;
|
||||
int maxrow = REALTEK_BRIDGE_MAX_APPCTL_ROW;
|
||||
int single_size = maxrow * REALTEK_BRIDGE_COLOR_DEPTH + 32;
|
||||
int stable_ms = cycle / row;
|
||||
int latency = stable_ms / get_argb_num();
|
||||
|
||||
memset(brctl_data, 0, REALTEK_BRIDGE_CTL_DATA_SIZE);
|
||||
for(i = 0; i < get_argb_num(); i++)
|
||||
{
|
||||
brctl_data[i * single_size + 0] = 4;
|
||||
brctl_data[i * single_size + 1] = row;
|
||||
brctl_data[i * single_size + 6] = stable_ms / 100;
|
||||
brctl_data[i * single_size + 7] = stable_ms / 100;
|
||||
brctl_data[i * single_size + 8] = 6;
|
||||
memcpy(&brctl_data[i * single_size + 9], &latency, 2);
|
||||
|
||||
j = 0;
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 32] = RGBGetRValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 33] = RGBGetGValue(rgb);
|
||||
brctl_data[i * single_size + j * REALTEK_BRIDGE_COLOR_DEPTH + 34] = RGBGetBValue(rgb);
|
||||
}
|
||||
return set_brctl_data();
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_argb_direct(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_BRIDGE_COLOR_DEPTH;
|
||||
static unsigned short prev_bright = 0xFFFF;
|
||||
unsigned char* buf;
|
||||
|
||||
if(color_num <= 0)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = set_appctl(true);
|
||||
if(ret)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(prev_bright != brightness)
|
||||
{
|
||||
prev_bright = brightness;
|
||||
ret = set_argb_brightness(brightness << 8);
|
||||
if(ret)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
buf = (unsigned char*)malloc(buf_len);
|
||||
memset(buf, 0, buf_len);
|
||||
for(int i = 0; i < (int)color_num; i++)
|
||||
{
|
||||
buf[i * REALTEK_BRIDGE_COLOR_DEPTH + 0] = RGBGetRValue(color_buf[i]);
|
||||
buf[i * REALTEK_BRIDGE_COLOR_DEPTH + 1] = RGBGetGValue(color_buf[i]);
|
||||
buf[i * REALTEK_BRIDGE_COLOR_DEPTH + 2] = RGBGetBValue(color_buf[i]);
|
||||
}
|
||||
ret = set_direct(buf, (int)color_num);
|
||||
free(buf);
|
||||
if(ret)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RealtekBridgeController::set_argb_effect(unsigned char mode, std::vector<RGBColor> color_buf, int speed, unsigned short brightness)
|
||||
{
|
||||
int ret = -1;
|
||||
int cycle = MathUtils::IntInterpolate(REALTEK_BRIDGE_CYCLE_MAX, REALTEK_BRIDGE_CYCLE_MIN, 0, REALTEK_BRIDGE_SPEED_MAX, speed);
|
||||
RGBColor rgb = 0;
|
||||
static unsigned short prev_bright = 0xFFFF;
|
||||
|
||||
if(color_buf.size() >= 1)
|
||||
{
|
||||
rgb = color_buf[0];
|
||||
}
|
||||
|
||||
if(prev_bright != brightness)
|
||||
{
|
||||
prev_bright = brightness;
|
||||
ret = set_argb_brightness(brightness << 8);
|
||||
if(ret)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case REALTEK_BRIDGE_LED_EFF_ALWAYS:
|
||||
ret = eff_set_always_on(rgb);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_BLINK:
|
||||
ret = eff_set_blink(rgb, cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_BREATHE:
|
||||
ret = eff_set_breathe(rgb, cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_SPECTRUM:
|
||||
ret = eff_set_spectrum(cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_SCROLL:
|
||||
ret = eff_set_scroll(rgb, cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_RAINBOW_SCROLL:
|
||||
ret = eff_set_rainbow_scroll(cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_RUNNING_WATER:
|
||||
ret = eff_set_running_water(rgb, cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_SLIDING:
|
||||
ret = eff_set_sliding(cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_NEWTON_CRADLE:
|
||||
ret = eff_set_newton_cradle(cycle);
|
||||
break;
|
||||
case REALTEK_BRIDGE_LED_EFF_METEOR:
|
||||
ret = eff_set_meteor(rgb, cycle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!ret)
|
||||
{
|
||||
ret = set_appctl(false);
|
||||
}
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RealtekBridgeController.h |
|
||||
| |
|
||||
| Controller for Realtek USB to SSD Bridge 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 <hidapi.h>
|
||||
|
||||
#include "RGBController.h"
|
||||
|
||||
#define REALTEK_BRIDGE_SYNC_METHOD_OPENRGB 6
|
||||
#define REALTEK_BRIDGE_COLOR_DEPTH 3
|
||||
#define REALTEK_BRIDGE_CTL_HDR_SIZE 64
|
||||
#define REALTEK_BRIDGE_CTL_DATA_SIZE 3220
|
||||
#define REALTEK_BRIDGE_MAX_ARGB_NUM 20
|
||||
#define REALTEK_BRIDGE_MAX_APPCTL_ROW 43
|
||||
|
||||
#define REALTEK_BRIDGE_HID_DATALEN_CH1 4096
|
||||
#define REALTEK_BRIDGE_HID_DATALEN_CH2 64
|
||||
#define REALTEK_BRIDGE_HID_DATALEN_CH3 512
|
||||
#define REALTEK_BRIDGE_HID_DATALEN_CH4 1200
|
||||
#define REALTEK_BRIDGE_HID_DATALEN_CH5 2048
|
||||
|
||||
#define REALTEK_BRIDGE_HID_ID_DATA_CH1 0x57
|
||||
#define REALTEK_BRIDGE_HID_ID_DATA_CH2 0x59
|
||||
#define REALTEK_BRIDGE_HID_ID_DATA_CH3 0x5A
|
||||
#define REALTEK_BRIDGE_HID_ID_DATA_CH4 0x5B
|
||||
#define REALTEK_BRIDGE_HID_ID_DATA_CH5 0x5C
|
||||
|
||||
enum REALTEK_BRIDGE_LED_EFF
|
||||
{
|
||||
REALTEK_BRIDGE_LED_EFF_NONE,
|
||||
REALTEK_BRIDGE_LED_EFF_ALWAYS,
|
||||
REALTEK_BRIDGE_LED_EFF_BLINK,
|
||||
REALTEK_BRIDGE_LED_EFF_BREATHE,
|
||||
REALTEK_BRIDGE_LED_EFF_SPECTRUM,
|
||||
REALTEK_BRIDGE_LED_EFF_SCROLL,
|
||||
REALTEK_BRIDGE_LED_EFF_RAINBOW_SCROLL,
|
||||
REALTEK_BRIDGE_LED_EFF_RUNNING_WATER,
|
||||
REALTEK_BRIDGE_LED_EFF_SLIDING,
|
||||
REALTEK_BRIDGE_LED_EFF_NEWTON_CRADLE,
|
||||
REALTEK_BRIDGE_LED_EFF_METEOR,
|
||||
REALTEK_BRIDGE_NUMBER_OF_LED_EFF_MODE,
|
||||
};
|
||||
|
||||
enum REALTEK_BRIDGE_SPEED
|
||||
{
|
||||
REALTEK_BRIDGE_SPEED_MIN = 1,
|
||||
REALTEK_BRIDGE_SPEED_NORMAL = 50,
|
||||
REALTEK_BRIDGE_SPEED_MAX = 100,
|
||||
};
|
||||
|
||||
enum REALTEK_BRIDGE_CYCLE_MS
|
||||
{
|
||||
REALTEK_BRIDGE_CYCLE_MIN = 200,
|
||||
REALTEK_BRIDGE_CYCLE_NORMAL = 2000,
|
||||
REALTEK_BRIDGE_CYCLE_MAX = 10000,
|
||||
};
|
||||
|
||||
struct RealtekBridgeControllerFWVersion
|
||||
{
|
||||
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 RealtekBridgeController
|
||||
{
|
||||
public:
|
||||
RealtekBridgeController(hid_device* dev, hid_device_info* info);
|
||||
~RealtekBridgeController();
|
||||
|
||||
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();
|
||||
int get_argb_num();
|
||||
int get_argb_brightness();
|
||||
int set_argb_brightness(unsigned short bright);
|
||||
|
||||
int set_argb_direct(std::vector<RGBColor> color_buf, unsigned short brightness);
|
||||
int set_argb_effect(unsigned char mode, std::vector<RGBColor> color_buf, int speed, unsigned short brightness);
|
||||
|
||||
private:
|
||||
hid_device* hdev;
|
||||
hid_device_info* hidinfo = NULL;
|
||||
unsigned char brctl_hdr[REALTEK_BRIDGE_CTL_HDR_SIZE] = {0};
|
||||
unsigned char* brctl_data = NULL;
|
||||
|
||||
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);
|
||||
int set_write_unlock();
|
||||
int get_brctl_hdr();
|
||||
int set_brctl_hdr();
|
||||
int get_brctl_data();
|
||||
int set_brctl_data();
|
||||
int set_appctl(unsigned char ctl_sts);
|
||||
int set_direct(unsigned char* color, int color_num);
|
||||
int eff_set_always_on(RGBColor rgb);
|
||||
int eff_set_blink(RGBColor rgb, int cycle);
|
||||
int eff_set_breathe(RGBColor rgb, int cycle);
|
||||
int eff_set_spectrum(int cycle);
|
||||
int eff_set_scroll(RGBColor rgb, int cycle);
|
||||
int eff_set_rainbow_scroll(int cycle);
|
||||
int eff_set_running_water(RGBColor rgb, int cycle);
|
||||
int eff_set_sliding(int cycle);
|
||||
int eff_set_newton_cradle(int cycle);
|
||||
int eff_set_meteor(RGBColor rgb, int cycle);
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RealtekBridgeControllerDetect.cpp |
|
||||
| |
|
||||
| Controller for Realtek USB to SSD Bridge 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_RealtekBridge.h"
|
||||
|
||||
#define REALTEK_BRIDGE_VID 0x0BDA
|
||||
#define REALTEK_BRIDGE_PID0 0x9220
|
||||
#define REALTEK_BRIDGE_PID1 0x9201
|
||||
#define REALTEK_BRIDGE_PID2 0x9210
|
||||
|
||||
#define REALTEK_HID2SCSI_PG 0xFF00
|
||||
#define REALTEK_HID2SCSI_USAGE 0x0001
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectRealtekBridgeControllers *
|
||||
* *
|
||||
* Tests the USB address to see if an Realtek Bridge controller exists there *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
void DetectRealtekBridgeControllers(hid_device_info* info, const std::string& /*name*/)
|
||||
{
|
||||
RealtekBridgeController* controller = NULL;
|
||||
RGBController_RealtekBridge* rgb_controller = NULL;
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
controller = new RealtekBridgeController(dev, info);
|
||||
if(controller->get_support_openrgb())
|
||||
{
|
||||
rgb_controller = new RGBController_RealtekBridge(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("RTL9220", DetectRealtekBridgeControllers, REALTEK_BRIDGE_VID, REALTEK_BRIDGE_PID0, REALTEK_HID2SCSI_PG, REALTEK_HID2SCSI_USAGE);
|
||||
REGISTER_HID_DETECTOR_PU("RTL9201", DetectRealtekBridgeControllers, REALTEK_BRIDGE_VID, REALTEK_BRIDGE_PID1, REALTEK_HID2SCSI_PG, REALTEK_HID2SCSI_USAGE);
|
||||
REGISTER_HID_DETECTOR_PU("RTL9210", DetectRealtekBridgeControllers, REALTEK_BRIDGE_VID, REALTEK_BRIDGE_PID2, REALTEK_HID2SCSI_PG, REALTEK_HID2SCSI_USAGE);
|
||||
+22
-4
@@ -86,9 +86,14 @@ device_info RoccatVulcanKeyboardController::InitDeviceInfo()
|
||||
buf[0] = report_id;
|
||||
hid_get_feature_report(dev_ctrl, buf, packet_length);
|
||||
|
||||
char version[5];
|
||||
snprintf(version, 5, "%d.%02d", buf[2] / 100, buf[2] % 100);
|
||||
/*-------------------------------------------------------------*\
|
||||
| buf[2] is version e.g. 103 means v1.03 |
|
||||
\*-------------------------------------------------------------*/
|
||||
dev_info.version_major = buf[2] / 100;
|
||||
dev_info.version_minor = buf[2] % 100;
|
||||
|
||||
char version[5];
|
||||
snprintf(version, 5, "%d.%02d", dev_info.version_major, dev_info.version_minor);
|
||||
dev_info.version = version;
|
||||
|
||||
if(device_pid == ROCCAT_MAGMA_PID || device_pid == ROCCAT_MAGMA_MINI_PID)
|
||||
@@ -116,6 +121,11 @@ device_info RoccatVulcanKeyboardController::GetDeviceInfo()
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
bool RoccatVulcanKeyboardController::IsBigEndianDirectMode()
|
||||
{
|
||||
return (dev_info.version_major >= 1 && dev_info.version_minor >= 16);
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::EnableDirect(bool on_off_switch)
|
||||
{
|
||||
uint8_t* buf;
|
||||
@@ -218,8 +228,16 @@ void RoccatVulcanKeyboardController::SendColors(std::vector<led_color> colors)
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs[0][3] = packet_length & 0xFF;
|
||||
bufs[0][4] = (packet_length >> 8) & 0xFF;
|
||||
if(IsBigEndianDirectMode())
|
||||
{
|
||||
bufs[0][3] = (packet_length >> 8) & 0xFF;
|
||||
bufs[0][4] = packet_length & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs[0][3] = packet_length & 0xFF;
|
||||
bufs[0][4] = (packet_length >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int data_length_packet = 64 - header_length_first;
|
||||
|
||||
+5
@@ -61,6 +61,8 @@ enum
|
||||
struct device_info
|
||||
{
|
||||
std::string version;
|
||||
int version_major;
|
||||
int version_minor;
|
||||
int layout_type;
|
||||
};
|
||||
|
||||
@@ -89,6 +91,7 @@ public:
|
||||
void AwaitResponse(int ms);
|
||||
void ClearResponses();
|
||||
|
||||
|
||||
uint16_t device_pid;
|
||||
|
||||
private:
|
||||
@@ -97,4 +100,6 @@ private:
|
||||
device_info dev_info;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
bool IsBigEndianDirectMode();
|
||||
};
|
||||
|
||||
+8
-7
@@ -46,7 +46,7 @@ std::string ThermaltakeRiingController::GetSerialString()
|
||||
|
||||
std::string ThermaltakeRiingController::GetFirmwareVersion()
|
||||
{
|
||||
unsigned char usb_buf[64];
|
||||
unsigned char usb_buf[65];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
@@ -56,14 +56,15 @@ std::string ThermaltakeRiingController::GetFirmwareVersion()
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up Get Firmware Version packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x33;
|
||||
usb_buf[0x01] = 0x50;
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = 0x33;
|
||||
usb_buf[0x02] = 0x50;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, 64);
|
||||
hid_read(dev, usb_buf, 64);
|
||||
hid_write(dev, usb_buf, 65);
|
||||
hid_read_timeout(dev, usb_buf, 65, 100);
|
||||
|
||||
std::string ret_str = std::to_string(usb_buf[2]) + "." + std::to_string(usb_buf[3]) + "." + std::to_string(usb_buf[4]);
|
||||
|
||||
@@ -117,7 +118,7 @@ void ThermaltakeRiingController::SendInit()
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, 65);
|
||||
hid_read(dev, usb_buf, 65);
|
||||
hid_read_timeout(dev, usb_buf, 65, 100);
|
||||
}
|
||||
|
||||
void ThermaltakeRiingController::SendRGB
|
||||
@@ -154,5 +155,5 @@ void ThermaltakeRiingController::SendRGB
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, 65);
|
||||
hid_read(dev, usb_buf, 65);
|
||||
hid_read_timeout(dev, usb_buf, 65, 100);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_ThrustmasterSol.cpp |
|
||||
| |
|
||||
| RGBController for Thrustmaster Sol series joysticks |
|
||||
| |
|
||||
| Ken Sanislo 02 Apr 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_ThrustmasterSol.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Thrustmaster Sol
|
||||
@category Gamepad
|
||||
@type USB
|
||||
@save :white_check_mark:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectThrustmasterSolControllers
|
||||
@comment Thrustmaster Sol series joystick RGB LED control. Supports
|
||||
Sol-R, Sol F16, and Sol F18 variants. Only Sol-R has been tested.
|
||||
Uses vendor-specific USB interface 1 (not HID).
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#define NA 0xFFFFFFFF
|
||||
|
||||
static unsigned int logo_matrix_map[2][2] =
|
||||
{
|
||||
{ 0, 3 },
|
||||
{ 1, 2 },
|
||||
};
|
||||
|
||||
static unsigned int ring_matrix_map[3][5] =
|
||||
{
|
||||
{ NA, 7, 0, 1, NA },
|
||||
{ 6, NA, NA, NA, 2 },
|
||||
{ NA, 5, 4, 3, NA },
|
||||
};
|
||||
|
||||
static unsigned int right_buttons_matrix_map[2][2] =
|
||||
{
|
||||
{ 0, 1 },
|
||||
{ 2, 3 },
|
||||
};
|
||||
|
||||
static unsigned int left_buttons_matrix_map[2][2] =
|
||||
{
|
||||
{ 0, 1 },
|
||||
{ 2, 3 },
|
||||
};
|
||||
|
||||
RGBController_ThrustmasterSol::RGBController_ThrustmasterSol(ThrustmasterSolController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
vendor = "Thrustmaster";
|
||||
type = DEVICE_TYPE_GAMEPAD;
|
||||
description = "Thrustmaster Sol Series Joystick";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Read current EEPROM colors from device so the UI starts |
|
||||
| with the actual hardware state rather than all-black |
|
||||
\*---------------------------------------------------------*/
|
||||
std::vector<unsigned int> hw_zones;
|
||||
std::vector<RGBColor> hw_colors;
|
||||
controller->ReadColors(hw_zones, hw_colors);
|
||||
|
||||
for(unsigned int i = 0; i < hw_zones.size(); i++)
|
||||
{
|
||||
for(unsigned int j = 0; j < leds.size(); j++)
|
||||
{
|
||||
if(leds[j].value == hw_zones[i])
|
||||
{
|
||||
colors[j] = hw_colors[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RGBController_ThrustmasterSol::~RGBController_ThrustmasterSol()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::SetupZones()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Thumbstick zone (grip, 1 LED) |
|
||||
\*---------------------------------------------------------*/
|
||||
zone thumbstick_zone;
|
||||
thumbstick_zone.name = "Thumbstick";
|
||||
thumbstick_zone.type = ZONE_TYPE_SINGLE;
|
||||
thumbstick_zone.leds_min = 1;
|
||||
thumbstick_zone.leds_max = 1;
|
||||
thumbstick_zone.leds_count = 1;
|
||||
thumbstick_zone.matrix_map = NULL;
|
||||
zones.push_back(thumbstick_zone);
|
||||
|
||||
led thumbstick_led;
|
||||
thumbstick_led.name = "Thumbstick";
|
||||
thumbstick_led.value = THRUSTMASTER_SOL_GRIP_FLAG | 0x00;
|
||||
leds.push_back(thumbstick_led);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| TM Logo zone (3 LEDs) |
|
||||
\*---------------------------------------------------------*/
|
||||
zone logo_zone;
|
||||
logo_zone.name = "TM Logo";
|
||||
logo_zone.type = ZONE_TYPE_MATRIX;
|
||||
logo_zone.leds_min = 4;
|
||||
logo_zone.leds_max = 4;
|
||||
logo_zone.leds_count = 4;
|
||||
logo_zone.matrix_map = new matrix_map_type;
|
||||
logo_zone.matrix_map->height = 2;
|
||||
logo_zone.matrix_map->width = 2;
|
||||
logo_zone.matrix_map->map = (unsigned int *)&logo_matrix_map;
|
||||
zones.push_back(logo_zone);
|
||||
|
||||
led logo_top_left;
|
||||
logo_top_left.name = "TM Logo Top Left";
|
||||
logo_top_left.value = 0x01;
|
||||
leds.push_back(logo_top_left);
|
||||
|
||||
led logo_bottom_left;
|
||||
logo_bottom_left.name = "TM Logo Bottom Left";
|
||||
logo_bottom_left.value = 0x02;
|
||||
leds.push_back(logo_bottom_left);
|
||||
|
||||
led logo_bottom_right;
|
||||
logo_bottom_right.name = "TM Logo Bottom Right";
|
||||
logo_bottom_right.value = 0x03;
|
||||
leds.push_back(logo_bottom_right);
|
||||
|
||||
led logo_top_right;
|
||||
logo_top_right.name = "TM Logo Top Right";
|
||||
logo_top_right.value = 0x00;
|
||||
leds.push_back(logo_top_right);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Left Buttons zone (4 LEDs: buttons 5-8) |
|
||||
\*---------------------------------------------------------*/
|
||||
zone left_buttons_zone;
|
||||
left_buttons_zone.name = "Left Buttons";
|
||||
left_buttons_zone.type = ZONE_TYPE_MATRIX;
|
||||
left_buttons_zone.leds_min = 4;
|
||||
left_buttons_zone.leds_max = 4;
|
||||
left_buttons_zone.leds_count = 4;
|
||||
left_buttons_zone.matrix_map = new matrix_map_type;
|
||||
left_buttons_zone.matrix_map->height = 2;
|
||||
left_buttons_zone.matrix_map->width = 2;
|
||||
left_buttons_zone.matrix_map->map = (unsigned int *)&left_buttons_matrix_map;
|
||||
zones.push_back(left_buttons_zone);
|
||||
|
||||
led btn5;
|
||||
btn5.name = "Button 5";
|
||||
btn5.value = 0x11;
|
||||
leds.push_back(btn5);
|
||||
|
||||
led btn6;
|
||||
btn6.name = "Button 6";
|
||||
btn6.value = 0x10;
|
||||
leds.push_back(btn6);
|
||||
|
||||
led btn7;
|
||||
btn7.name = "Button 7";
|
||||
btn7.value = 0x12;
|
||||
leds.push_back(btn7);
|
||||
|
||||
led btn8;
|
||||
btn8.name = "Button 8";
|
||||
btn8.value = 0x13;
|
||||
leds.push_back(btn8);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Base Ring zone (8 LEDs, clockwise from top) |
|
||||
\*---------------------------------------------------------*/
|
||||
zone ring_zone;
|
||||
ring_zone.name = "Base Ring";
|
||||
ring_zone.type = ZONE_TYPE_MATRIX;
|
||||
ring_zone.leds_min = 8;
|
||||
ring_zone.leds_max = 8;
|
||||
ring_zone.leds_count = 8;
|
||||
ring_zone.matrix_map = new matrix_map_type;
|
||||
ring_zone.matrix_map->height = 3;
|
||||
ring_zone.matrix_map->width = 5;
|
||||
ring_zone.matrix_map->map = (unsigned int *)&ring_matrix_map;
|
||||
zones.push_back(ring_zone);
|
||||
|
||||
led ring_upper;
|
||||
ring_upper.name = "Upper";
|
||||
ring_upper.value = 0x04;
|
||||
leds.push_back(ring_upper);
|
||||
|
||||
led ring_upper_right;
|
||||
ring_upper_right.name = "Upper Right";
|
||||
ring_upper_right.value = 0x05;
|
||||
leds.push_back(ring_upper_right);
|
||||
|
||||
led ring_right;
|
||||
ring_right.name = "Right";
|
||||
ring_right.value = 0x06;
|
||||
leds.push_back(ring_right);
|
||||
|
||||
led ring_bottom_right;
|
||||
ring_bottom_right.name = "Bottom Right";
|
||||
ring_bottom_right.value = 0x0B;
|
||||
leds.push_back(ring_bottom_right);
|
||||
|
||||
led ring_bottom;
|
||||
ring_bottom.name = "Bottom";
|
||||
ring_bottom.value = 0x0C;
|
||||
leds.push_back(ring_bottom);
|
||||
|
||||
led ring_bottom_left;
|
||||
ring_bottom_left.name = "Bottom Left";
|
||||
ring_bottom_left.value = 0x0D;
|
||||
leds.push_back(ring_bottom_left);
|
||||
|
||||
led ring_left;
|
||||
ring_left.name = "Left";
|
||||
ring_left.value = 0x0E;
|
||||
leds.push_back(ring_left);
|
||||
|
||||
led ring_upper_left;
|
||||
ring_upper_left.name = "Upper Left";
|
||||
ring_upper_left.value = 0x0F;
|
||||
leds.push_back(ring_upper_left);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Right Buttons zone (4 LEDs: buttons 16-19) |
|
||||
\*---------------------------------------------------------*/
|
||||
zone right_buttons_zone;
|
||||
right_buttons_zone.name = "Right Buttons";
|
||||
right_buttons_zone.type = ZONE_TYPE_MATRIX;
|
||||
right_buttons_zone.leds_min = 4;
|
||||
right_buttons_zone.leds_max = 4;
|
||||
right_buttons_zone.leds_count = 4;
|
||||
right_buttons_zone.matrix_map = new matrix_map_type;
|
||||
right_buttons_zone.matrix_map->height = 2;
|
||||
right_buttons_zone.matrix_map->width = 2;
|
||||
right_buttons_zone.matrix_map->map = (unsigned int *)&right_buttons_matrix_map;
|
||||
zones.push_back(right_buttons_zone);
|
||||
|
||||
led btn17;
|
||||
btn17.name = "Button 17";
|
||||
btn17.value = 0x07;
|
||||
leds.push_back(btn17);
|
||||
|
||||
led btn16;
|
||||
btn16.name = "Button 16";
|
||||
btn16.value = 0x08;
|
||||
leds.push_back(btn16);
|
||||
|
||||
led btn19;
|
||||
btn19.name = "Button 19";
|
||||
btn19.value = 0x0A;
|
||||
leds.push_back(btn19);
|
||||
|
||||
led btn18;
|
||||
btn18.name = "Button 18";
|
||||
btn18.value = 0x09;
|
||||
leds.push_back(btn18);
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::DeviceUpdateLEDs()
|
||||
{
|
||||
unsigned int led_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
RGBColor led_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++)
|
||||
{
|
||||
led_zones[led_idx] = leds[led_idx].value;
|
||||
led_colors[led_idx] = colors[led_idx];
|
||||
}
|
||||
|
||||
controller->SetLEDColors(led_zones, led_colors, static_cast<unsigned int>(leds.size()));
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::UpdateZoneLEDs(int zone)
|
||||
{
|
||||
unsigned int start_idx = 0;
|
||||
unsigned int zone_size = 0;
|
||||
|
||||
for(unsigned int z_idx = 0; z_idx < zones.size(); z_idx++)
|
||||
{
|
||||
if(z_idx == (unsigned int)zone)
|
||||
{
|
||||
zone_size = zones[z_idx].leds_count;
|
||||
break;
|
||||
}
|
||||
|
||||
start_idx += zones[z_idx].leds_count;
|
||||
}
|
||||
|
||||
unsigned int led_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
RGBColor led_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < zone_size; led_idx++)
|
||||
{
|
||||
unsigned int current_idx = start_idx + led_idx;
|
||||
led_zones[led_idx] = leds[current_idx].value;
|
||||
led_colors[led_idx] = colors[current_idx];
|
||||
}
|
||||
|
||||
controller->SetLEDColors(led_zones, led_colors, zone_size);
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::UpdateSingleLED(int led)
|
||||
{
|
||||
controller->SetLEDColor(leds[led].value, colors[led]);
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::DeviceUpdateMode()
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_ThrustmasterSol::DeviceSaveMode()
|
||||
{
|
||||
unsigned int led_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
RGBColor led_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++)
|
||||
{
|
||||
led_zones[led_idx] = leds[led_idx].value;
|
||||
led_colors[led_idx] = colors[led_idx];
|
||||
}
|
||||
|
||||
controller->SaveColors(led_zones, led_colors, static_cast<unsigned int>(leds.size()));
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_ThrustmasterSol.h |
|
||||
| |
|
||||
| RGBController for Thrustmaster Sol series joysticks |
|
||||
| |
|
||||
| Ken Sanislo 02 Apr 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "ThrustmasterSolController.h"
|
||||
|
||||
class RGBController_ThrustmasterSol : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_ThrustmasterSol(ThrustmasterSolController* controller_ptr);
|
||||
~RGBController_ThrustmasterSol();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
void DeviceSaveMode();
|
||||
|
||||
private:
|
||||
ThrustmasterSolController* controller;
|
||||
};
|
||||
@@ -0,0 +1,315 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| ThrustmasterSolController.cpp |
|
||||
| |
|
||||
| Driver for Thrustmaster Sol series joysticks |
|
||||
| |
|
||||
| Ken Sanislo 02 Apr 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "ThrustmasterSolController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
ThrustmasterSolController::ThrustmasterSolController(libusb_device_handle* dev_handle,
|
||||
const char* path,
|
||||
unsigned short pid)
|
||||
{
|
||||
dev = dev_handle;
|
||||
this->pid = pid;
|
||||
|
||||
location = "USB: ";
|
||||
location += path;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Get serial number string descriptor |
|
||||
\*---------------------------------------------------------*/
|
||||
libusb_device_descriptor desc;
|
||||
libusb_get_device_descriptor(libusb_get_device(dev_handle), &desc);
|
||||
|
||||
if(desc.iSerialNumber != 0)
|
||||
{
|
||||
unsigned char serial_str[256];
|
||||
int ret = libusb_get_string_descriptor_ascii(dev_handle,
|
||||
desc.iSerialNumber,
|
||||
serial_str,
|
||||
sizeof(serial_str));
|
||||
if(ret > 0)
|
||||
{
|
||||
serial = std::string(reinterpret_cast<char*>(serial_str), ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThrustmasterSolController::~ThrustmasterSolController()
|
||||
{
|
||||
if(dev != nullptr)
|
||||
{
|
||||
libusb_release_interface(dev, THRUSTMASTER_SOL_INTERFACE);
|
||||
libusb_close(dev);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ThrustmasterSolController::GetDeviceLocation()
|
||||
{
|
||||
return(location);
|
||||
}
|
||||
|
||||
std::string ThrustmasterSolController::GetSerialString()
|
||||
{
|
||||
return(serial);
|
||||
}
|
||||
|
||||
unsigned short ThrustmasterSolController::GetPID()
|
||||
{
|
||||
return(pid);
|
||||
}
|
||||
|
||||
void ThrustmasterSolController::SendPacket(unsigned char* packet, unsigned int size)
|
||||
{
|
||||
if(dev == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int actual_length = 0;
|
||||
libusb_interrupt_transfer(dev,
|
||||
THRUSTMASTER_SOL_ENDPOINT_OUT,
|
||||
packet,
|
||||
size,
|
||||
&actual_length,
|
||||
1000);
|
||||
}
|
||||
|
||||
void ThrustmasterSolController::BuildAndSendPackets(unsigned int* zones,
|
||||
RGBColor* colors,
|
||||
unsigned int count,
|
||||
bool persistent)
|
||||
{
|
||||
unsigned char persist_flag = persistent ? THRUSTMASTER_SOL_PERSISTENT
|
||||
: THRUSTMASTER_SOL_VOLATILE;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Separate grip zones from base zones. Zone 0x00 exists on |
|
||||
| both the base (logo LED) and the grip (thumbstick LED). |
|
||||
| The GRIP_FLAG bit selects the grip report type. |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char base_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
RGBColor base_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
|
||||
unsigned int base_count = 0;
|
||||
|
||||
for(unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if(zones[i] & THRUSTMASTER_SOL_GRIP_FLAG)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Send grip packet for thumbstick immediately |
|
||||
\*-------------------------------------------------*/
|
||||
unsigned char zone_id = zones[i] & 0xFF;
|
||||
|
||||
unsigned char packet[THRUSTMASTER_SOL_PACKET_SIZE];
|
||||
memset(packet, 0x00, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
|
||||
packet[0] = THRUSTMASTER_SOL_REPORT_GRIP_LO;
|
||||
packet[1] = THRUSTMASTER_SOL_REPORT_GRIP_HI;
|
||||
packet[2] = persist_flag | 0x01;
|
||||
packet[3] = THRUSTMASTER_SOL_MARKER;
|
||||
packet[4] = zone_id;
|
||||
packet[5] = RGBGetRValue(colors[i]);
|
||||
packet[6] = RGBGetGValue(colors[i]);
|
||||
packet[7] = RGBGetBValue(colors[i]);
|
||||
|
||||
SendPacket(packet, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
base_zones[base_count] = zones[i] & 0xFF;
|
||||
base_colors[base_count] = colors[i];
|
||||
base_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Send base zone packets, batching up to 15 entries each |
|
||||
\*---------------------------------------------------------*/
|
||||
for(unsigned int offset = 0; offset < base_count; offset += THRUSTMASTER_SOL_MAX_ENTRIES)
|
||||
{
|
||||
unsigned int entries = base_count - offset;
|
||||
|
||||
if(entries > THRUSTMASTER_SOL_MAX_ENTRIES)
|
||||
{
|
||||
entries = THRUSTMASTER_SOL_MAX_ENTRIES;
|
||||
}
|
||||
|
||||
unsigned char packet[THRUSTMASTER_SOL_PACKET_SIZE];
|
||||
memset(packet, 0x00, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
|
||||
packet[0] = THRUSTMASTER_SOL_REPORT_BASE_LO;
|
||||
packet[1] = THRUSTMASTER_SOL_REPORT_BASE_HI;
|
||||
packet[2] = persist_flag | (unsigned char)entries;
|
||||
packet[3] = THRUSTMASTER_SOL_MARKER;
|
||||
|
||||
for(unsigned int j = 0; j < entries; j++)
|
||||
{
|
||||
unsigned int idx = offset + j;
|
||||
packet[4 + j * 4] = base_zones[idx];
|
||||
packet[4 + j * 4 + 1] = RGBGetRValue(base_colors[idx]);
|
||||
packet[4 + j * 4 + 2] = RGBGetGValue(base_colors[idx]);
|
||||
packet[4 + j * 4 + 3] = RGBGetBValue(base_colors[idx]);
|
||||
}
|
||||
|
||||
SendPacket(packet, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
}
|
||||
}
|
||||
|
||||
void ThrustmasterSolController::SetLEDColor(unsigned int zone, RGBColor color)
|
||||
{
|
||||
BuildAndSendPackets(&zone, &color, 1, false);
|
||||
}
|
||||
|
||||
void ThrustmasterSolController::SetLEDColors(unsigned int* zones,
|
||||
RGBColor* colors,
|
||||
unsigned int count)
|
||||
{
|
||||
BuildAndSendPackets(zones, colors, count, false);
|
||||
}
|
||||
|
||||
void ThrustmasterSolController::SaveColors(unsigned int* zones,
|
||||
RGBColor* colors,
|
||||
unsigned int count)
|
||||
{
|
||||
BuildAndSendPackets(zones, colors, count, true);
|
||||
}
|
||||
|
||||
void ThrustmasterSolController::ReadColors(std::vector<unsigned int>& zones,
|
||||
std::vector<RGBColor>& colors)
|
||||
{
|
||||
if(dev == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
zones.clear();
|
||||
colors.clear();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Read base zones (report 0x0002). May require multiple |
|
||||
| queries if more than 14 zones are returned per response. |
|
||||
| Zone IDs are returned without the grip flag, so they |
|
||||
| match the base LED values (including zone 0x00 = logo). |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char start = 0;
|
||||
|
||||
for(int page = 0; page < 4; page++)
|
||||
{
|
||||
unsigned char query[THRUSTMASTER_SOL_PACKET_SIZE];
|
||||
memset(query, 0x00, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
|
||||
query[0] = THRUSTMASTER_SOL_READ_BASE_LO;
|
||||
query[1] = THRUSTMASTER_SOL_READ_BASE_HI;
|
||||
query[2] = start;
|
||||
|
||||
SendPacket(query, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
|
||||
unsigned char resp[THRUSTMASTER_SOL_PACKET_SIZE];
|
||||
int actual = 0;
|
||||
int ret = libusb_interrupt_transfer(dev,
|
||||
THRUSTMASTER_SOL_ENDPOINT_IN,
|
||||
resp,
|
||||
THRUSTMASTER_SOL_PACKET_SIZE,
|
||||
&actual,
|
||||
1000);
|
||||
|
||||
if(ret != LIBUSB_SUCCESS || actual < 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int n = resp[2] & 0x0F;
|
||||
|
||||
if(n == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned char last = start;
|
||||
|
||||
for(unsigned int i = 0; i < n; i++)
|
||||
{
|
||||
unsigned int off = 4 + i * 4;
|
||||
|
||||
if(off + 3 >= (unsigned int)actual)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned char zid = resp[off];
|
||||
unsigned char r = resp[off + 1];
|
||||
unsigned char g = resp[off + 2];
|
||||
unsigned char b = resp[off + 3];
|
||||
|
||||
zones.push_back(zid);
|
||||
colors.push_back(ToRGBColor(r, g, b));
|
||||
last = zid;
|
||||
}
|
||||
|
||||
start = last + 1;
|
||||
|
||||
if(n < 14 || start > 0x20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Read grip zones (report 0x8002). Grip zone IDs are |
|
||||
| returned with the GRIP_FLAG set so they match the |
|
||||
| thumbstick LED value. They are added as new entries, |
|
||||
| not overwriting base entries (zone 0x00 exists on both). |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char grip_query[THRUSTMASTER_SOL_PACKET_SIZE];
|
||||
memset(grip_query, 0x00, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
|
||||
grip_query[0] = THRUSTMASTER_SOL_READ_GRIP_LO;
|
||||
grip_query[1] = THRUSTMASTER_SOL_READ_GRIP_HI;
|
||||
|
||||
SendPacket(grip_query, THRUSTMASTER_SOL_PACKET_SIZE);
|
||||
|
||||
unsigned char grip_resp[THRUSTMASTER_SOL_PACKET_SIZE];
|
||||
int grip_actual = 0;
|
||||
int grip_ret = libusb_interrupt_transfer(dev,
|
||||
THRUSTMASTER_SOL_ENDPOINT_IN,
|
||||
grip_resp,
|
||||
THRUSTMASTER_SOL_PACKET_SIZE,
|
||||
&grip_actual,
|
||||
1000);
|
||||
|
||||
if(grip_ret == LIBUSB_SUCCESS && grip_actual >= 8)
|
||||
{
|
||||
unsigned int grip_n = grip_resp[2] & 0x0F;
|
||||
|
||||
for(unsigned int i = 0; i < grip_n; i++)
|
||||
{
|
||||
unsigned int off = 4 + i * 4;
|
||||
|
||||
if(off + 3 >= (unsigned int)grip_actual)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned char zid = grip_resp[off];
|
||||
unsigned char r = grip_resp[off + 1];
|
||||
unsigned char g = grip_resp[off + 2];
|
||||
unsigned char b = grip_resp[off + 3];
|
||||
|
||||
zones.push_back(THRUSTMASTER_SOL_GRIP_FLAG | zid);
|
||||
colors.push_back(ToRGBColor(r, g, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| ThrustmasterSolController.h |
|
||||
| |
|
||||
| Driver for Thrustmaster Sol series joysticks |
|
||||
| |
|
||||
| Ken Sanislo 02 Apr 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "RGBController.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "dependencies/libusb-1.0.27/include/libusb.h"
|
||||
#else
|
||||
#include <libusb.h>
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster vendor ID |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_VID 0x044F
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol series product IDs |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_R_RIGHT_PID 0x0422
|
||||
#define THRUSTMASTER_SOL_R_LEFT_PID 0x042A
|
||||
#define THRUSTMASTER_SOL_F16_RIGHT_PID 0x0420
|
||||
#define THRUSTMASTER_SOL_F18_RIGHT_PID 0x0421
|
||||
#define THRUSTMASTER_SOL_F16_LEFT_PID 0x0428
|
||||
#define THRUSTMASTER_SOL_F18_LEFT_PID 0x0429
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol USB constants |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_INTERFACE 1
|
||||
#define THRUSTMASTER_SOL_ENDPOINT_OUT 0x02
|
||||
#define THRUSTMASTER_SOL_ENDPOINT_IN 0x82
|
||||
#define THRUSTMASTER_SOL_PACKET_SIZE 64
|
||||
#define THRUSTMASTER_SOL_MAX_ENTRIES 15
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol report type identifiers |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_REPORT_BASE_LO 0x01
|
||||
#define THRUSTMASTER_SOL_REPORT_BASE_HI 0x08
|
||||
#define THRUSTMASTER_SOL_REPORT_GRIP_LO 0x01
|
||||
#define THRUSTMASTER_SOL_REPORT_GRIP_HI 0x88
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol persistence flags |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_VOLATILE 0x00
|
||||
#define THRUSTMASTER_SOL_PERSISTENT 0x80
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol read query report types |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_READ_BASE_LO 0x02
|
||||
#define THRUSTMASTER_SOL_READ_BASE_HI 0x00
|
||||
#define THRUSTMASTER_SOL_READ_GRIP_LO 0x02
|
||||
#define THRUSTMASTER_SOL_READ_GRIP_HI 0x80
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol zone constants |
|
||||
| |
|
||||
| Zone 0x00 is shared: on the base it is a logo LED, |
|
||||
| on the grip it is the thumbstick LED. The grip flag |
|
||||
| (bit 8) selects the grip report type for zone 0x00. |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_ZONE_THUMBSTICK 0x00
|
||||
#define THRUSTMASTER_SOL_GRIP_FLAG 0x100
|
||||
#define THRUSTMASTER_SOL_MARKER 0xFF
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Thrustmaster Sol zone count for Sol-R |
|
||||
| 19 base zones + thumbstick + logo zone 0x00 = 21 |
|
||||
\*-----------------------------------------------------*/
|
||||
#define THRUSTMASTER_SOL_R_ZONE_COUNT 21
|
||||
|
||||
class ThrustmasterSolController
|
||||
{
|
||||
public:
|
||||
ThrustmasterSolController(libusb_device_handle* dev_handle,
|
||||
const char* path,
|
||||
unsigned short pid);
|
||||
~ThrustmasterSolController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetSerialString();
|
||||
unsigned short GetPID();
|
||||
|
||||
void SetLEDColor(unsigned int zone, RGBColor color);
|
||||
void SetLEDColors(unsigned int* zones, RGBColor* colors,
|
||||
unsigned int count);
|
||||
void SaveColors(unsigned int* zones, RGBColor* colors,
|
||||
unsigned int count);
|
||||
void ReadColors(std::vector<unsigned int>& zones,
|
||||
std::vector<RGBColor>& colors);
|
||||
|
||||
private:
|
||||
libusb_device_handle* dev;
|
||||
std::string location;
|
||||
std::string serial;
|
||||
unsigned short pid;
|
||||
|
||||
void SendPacket(unsigned char* packet, unsigned int size);
|
||||
void BuildAndSendPackets(unsigned int* zones, RGBColor* colors,
|
||||
unsigned int count, bool persistent);
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| ThrustmasterSolControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Thrustmaster Sol series joysticks |
|
||||
| |
|
||||
| Ken Sanislo 02 Apr 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "Detector.h"
|
||||
#include "ThrustmasterSolController.h"
|
||||
#include "RGBController_ThrustmasterSol.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short usb_vid;
|
||||
unsigned short usb_pid;
|
||||
const char* name;
|
||||
} thrustmaster_sol_device;
|
||||
|
||||
#define THRUSTMASTER_SOL_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[0]))
|
||||
|
||||
static const thrustmaster_sol_device device_list[] =
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------------------------*\
|
||||
| Sol-R variants (tested) |
|
||||
\*-----------------------------------------------------------------------------------------------------*/
|
||||
{ THRUSTMASTER_VID, THRUSTMASTER_SOL_R_RIGHT_PID, "Thrustmaster Sol-R Right" },
|
||||
{ THRUSTMASTER_VID, THRUSTMASTER_SOL_R_LEFT_PID, "Thrustmaster Sol-R Left" },
|
||||
/*-----------------------------------------------------------------------------------------------------*\
|
||||
| Sol F16/F18 variants (untested, same base protocol) |
|
||||
\*-----------------------------------------------------------------------------------------------------*/
|
||||
{ THRUSTMASTER_VID, THRUSTMASTER_SOL_F16_RIGHT_PID, "Thrustmaster Sol F16 Right" },
|
||||
{ THRUSTMASTER_VID, THRUSTMASTER_SOL_F18_RIGHT_PID, "Thrustmaster Sol F18 Right" },
|
||||
{ THRUSTMASTER_VID, THRUSTMASTER_SOL_F16_LEFT_PID, "Thrustmaster Sol F16 Left" },
|
||||
{ THRUSTMASTER_VID, THRUSTMASTER_SOL_F18_LEFT_PID, "Thrustmaster Sol F18 Left" },
|
||||
};
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectThrustmasterSolControllers *
|
||||
* *
|
||||
* Detect Thrustmaster Sol series joysticks via libusb. *
|
||||
* LED control is on USB interface 1 (vendor-specific class 255, not HID). *
|
||||
* Interface 0 (joystick HID) is not touched. *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
void DetectThrustmasterSolControllers()
|
||||
{
|
||||
libusb_init(NULL);
|
||||
|
||||
#ifdef _WIN32
|
||||
libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK);
|
||||
#endif
|
||||
|
||||
libusb_device** devs;
|
||||
ssize_t num_devs = libusb_get_device_list(NULL, &devs);
|
||||
|
||||
if(num_devs <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(ssize_t i = 0; i < num_devs; i++)
|
||||
{
|
||||
libusb_device_descriptor desc;
|
||||
|
||||
if(libusb_get_device_descriptor(devs[i], &desc) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(std::size_t d = 0; d < THRUSTMASTER_SOL_NUM_DEVICES; d++)
|
||||
{
|
||||
if(desc.idVendor == device_list[d].usb_vid &&
|
||||
desc.idProduct == device_list[d].usb_pid)
|
||||
{
|
||||
libusb_device_handle* handle = NULL;
|
||||
|
||||
if(libusb_open(devs[i], &handle) != LIBUSB_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
libusb_set_auto_detach_kernel_driver(handle, 1);
|
||||
|
||||
if(libusb_claim_interface(handle, THRUSTMASTER_SOL_INTERFACE) != LIBUSB_SUCCESS)
|
||||
{
|
||||
libusb_close(handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t bus = libusb_get_bus_number(devs[i]);
|
||||
uint8_t address = libusb_get_device_address(devs[i]);
|
||||
char path[32];
|
||||
snprintf(path, sizeof(path), "%d-%d", bus, address);
|
||||
|
||||
ThrustmasterSolController* controller = new ThrustmasterSolController(handle, path, desc.idProduct);
|
||||
RGBController_ThrustmasterSol* rgb_controller = new RGBController_ThrustmasterSol(controller);
|
||||
|
||||
rgb_controller->name = device_list[d].name;
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_device_list(devs, 1);
|
||||
}
|
||||
|
||||
REGISTER_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers);
|
||||
/*---------------------------------------------------------------------------------------------------------*\
|
||||
| Entries for dynamic UDEV rules |
|
||||
| |
|
||||
| DUMMY_DEVICE_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers, 0x044F, 0x0420 ) |
|
||||
| DUMMY_DEVICE_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers, 0x044F, 0x0421 ) |
|
||||
| DUMMY_DEVICE_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers, 0x044F, 0x0422 ) |
|
||||
| DUMMY_DEVICE_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers, 0x044F, 0x0428 ) |
|
||||
| DUMMY_DEVICE_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers, 0x044F, 0x0429 ) |
|
||||
| DUMMY_DEVICE_DETECTOR("Thrustmaster Sol", DetectThrustmasterSolControllers, 0x044F, 0x042A ) |
|
||||
\*---------------------------------------------------------------------------------------------------------*/
|
||||
@@ -187,50 +187,21 @@ static const char *led_names[] =
|
||||
\*---------------------------------------------------------*/
|
||||
RGBController_XPGSummoner::RGBController_XPGSummoner(XPGSummonerController *controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
name = controller->GetNameString();
|
||||
vendor = "XPG";
|
||||
description = "XPG Summoner Keyboard Device";
|
||||
location = controller->GetLocationString();
|
||||
serial = controller->GetSerialString();
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
controller = controller_ptr;
|
||||
name = controller->GetNameString();
|
||||
vendor = "XPG";
|
||||
description = "XPG Summoner Keyboard Device";
|
||||
location = controller->GetLocationString();
|
||||
serial = controller->GetSerialString();
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = XPG_SUMMONER_MODE_DIRECT;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = XPG_SUMMONER_MODE_DIRECT;
|
||||
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 = XPG_SUMMONER_MODE_STATIC;
|
||||
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Static.colors_min = 1;
|
||||
Static.colors_max = 1;
|
||||
Static.brightness_min = 5;
|
||||
Static.brightness_max = 64;
|
||||
Static.colors.resize(1);
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Stars;
|
||||
Stars.name = "Stars";
|
||||
Stars.value = XPG_SUMMONER_MODE_STARS;
|
||||
Stars.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
|
||||
Stars.colors_min = 1;
|
||||
Stars.colors_max = 1;
|
||||
Stars.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Stars.colors.resize(1);
|
||||
modes.push_back(Stars);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = XPG_SUMMONER_MODE_OFF;
|
||||
Off.flags = 0;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
@@ -321,7 +292,9 @@ void RGBController_XPGSummoner::DeviceUpdateLEDs()
|
||||
for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++)
|
||||
{
|
||||
if(leds[led_idx].value == NA)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(modes[active_mode].color_mode == MODE_COLORS_PER_LED)
|
||||
{
|
||||
std::size_t real_idx = leds[led_idx].value;
|
||||
@@ -330,76 +303,6 @@ void RGBController_XPGSummoner::DeviceUpdateLEDs()
|
||||
frame_buf[(real_idx * 4) + 2] = RGBGetGValue(colors[led_idx]);
|
||||
frame_buf[(real_idx * 4) + 3] = RGBGetBValue(colors[led_idx]);
|
||||
}
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && modes[active_mode].value == XPG_SUMMONER_MODE_STATIC)
|
||||
{
|
||||
std::size_t real_idx = leds[led_idx].value;
|
||||
frame_buf[(real_idx * 4) + 0] = modes[active_mode].brightness;
|
||||
frame_buf[(real_idx * 4) + 1] = RGBGetRValue(modes[active_mode].colors[0]);
|
||||
frame_buf[(real_idx * 4) + 2] = RGBGetGValue(modes[active_mode].colors[0]);
|
||||
frame_buf[(real_idx * 4) + 3] = RGBGetBValue(modes[active_mode].colors[0]);
|
||||
}
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && modes[active_mode].value == XPG_SUMMONER_MODE_STARS)
|
||||
{
|
||||
for(std::size_t i = 0; i < leds.size(); ++i)
|
||||
{
|
||||
std::size_t real_idx = leds[i].value;
|
||||
frame_buf[(real_idx * 4) + 0] = 0;
|
||||
frame_buf[(real_idx * 4) + 1] = 0;
|
||||
frame_buf[(real_idx * 4) + 2] = 0;
|
||||
frame_buf[(real_idx * 4) + 3] = 0;
|
||||
}
|
||||
controller->SendColors(frame_buf, sizeof(frame_buf));
|
||||
|
||||
/*---------------------------------------------------*\
|
||||
| Select a random central LED in the physical matrix |
|
||||
\*---------------------------------------------------*/
|
||||
int rows = 6;
|
||||
int cols = 21;
|
||||
int center_row = rand() % rows;
|
||||
int center_col = rand() % cols;
|
||||
unsigned int center_led = matrix_map[center_row][center_col];
|
||||
|
||||
if(center_led != NA)
|
||||
{
|
||||
frame_buf[(center_led * 4) + 0] = brightness;
|
||||
frame_buf[(center_led * 4) + 1] = RGBGetRValue(modes[active_mode].colors[0]);
|
||||
frame_buf[(center_led * 4) + 2] = RGBGetGValue(modes[active_mode].colors[0]);
|
||||
frame_buf[(center_led * 4) + 3] = RGBGetBValue(modes[active_mode].colors[0]);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*\
|
||||
| Neighbors (fade effect) |
|
||||
\*---------------------------------------------------*/
|
||||
unsigned char fade_brightness = 0x32;
|
||||
int neighbor_offsets[4][2] = { {0, -1}, {0, +1}, {-1, 0}, {+1, 0} };
|
||||
|
||||
for(int k = 0; k < 4; ++k)
|
||||
{
|
||||
int n_row = center_row + neighbor_offsets[k][0];
|
||||
int n_col = center_col + neighbor_offsets[k][1];
|
||||
if(n_row >= 0 && n_row < rows && n_col >= 0 && n_col < cols)
|
||||
{
|
||||
unsigned int neighbor_led = matrix_map[n_row][n_col];
|
||||
if(neighbor_led != NA)
|
||||
{
|
||||
frame_buf[(neighbor_led * 4) + 0] = fade_brightness;
|
||||
frame_buf[(neighbor_led * 4) + 1] = RGBGetRValue(modes[active_mode].colors[0]);
|
||||
frame_buf[(neighbor_led * 4) + 2] = RGBGetGValue(modes[active_mode].colors[0]);
|
||||
frame_buf[(neighbor_led * 4) + 3] = RGBGetBValue(modes[active_mode].colors[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
controller->SendColors(frame_buf, sizeof(frame_buf));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_NONE)
|
||||
{
|
||||
std::size_t real_idx = leds[led_idx].value;
|
||||
frame_buf[(real_idx * 4) + 0] = 0;
|
||||
frame_buf[(real_idx * 4) + 1] = 0;
|
||||
frame_buf[(real_idx * 4) + 2] = 0;
|
||||
frame_buf[(real_idx * 4) + 3] = 0;
|
||||
}
|
||||
}
|
||||
controller->SendColors(frame_buf, sizeof(frame_buf));
|
||||
}
|
||||
|
||||
@@ -27,10 +27,7 @@
|
||||
|
||||
enum
|
||||
{
|
||||
XPG_SUMMONER_MODE_OFF = 0x00,
|
||||
XPG_SUMMONER_MODE_DIRECT = 0x01,
|
||||
XPG_SUMMONER_MODE_STATIC = 0x02,
|
||||
XPG_SUMMONER_MODE_STARS = 0x03
|
||||
XPG_SUMMONER_MODE_DIRECT = 0x01
|
||||
};
|
||||
|
||||
class XPGSummonerController
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MathUtils.cpp |
|
||||
| |
|
||||
| Math utility functions |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <math.h>
|
||||
#include "MathUtils.h"
|
||||
|
||||
int MathUtils::IntInterpolate(int y0, int y1, int x0, int x1, int x)
|
||||
{
|
||||
if(x1 == x0)
|
||||
return y0;
|
||||
|
||||
if(y0 == y1)
|
||||
return y0;
|
||||
|
||||
double t = (double)(x - x0) / (double)(x1 - x0);
|
||||
double y = y0 * (1.0 - t) + y1 * t;
|
||||
return (int)round(y);
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MathUtils.h |
|
||||
| |
|
||||
| Math utility functions |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class MathUtils
|
||||
{
|
||||
public:
|
||||
static int IntInterpolate(int y0, int y1, int x0, int x1, int x);
|
||||
};
|
||||
@@ -199,6 +199,7 @@ HEADERS +=
|
||||
serial_port/find_usb_serial_port.h \
|
||||
serial_port/serial_port.h \
|
||||
super_io/super_io.h \
|
||||
MathUtils.h \
|
||||
StringUtils.h \
|
||||
SuspendResume/SuspendResume.h \
|
||||
AutoStart/AutoStart.h \
|
||||
@@ -265,6 +266,7 @@ SOURCES +=
|
||||
interop/DeviceGuardManager.cpp \
|
||||
net_port/net_port.cpp \
|
||||
serial_port/serial_port.cpp \
|
||||
MathUtils.cpp \
|
||||
StringUtils.cpp \
|
||||
AutoStart/AutoStart.cpp \
|
||||
KeyboardLayoutManager/KeyboardLayoutManager.cpp \
|
||||
@@ -437,6 +439,7 @@ win32:contains(QMAKE_TARGET.arch, x86_64) {
|
||||
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/SmbusPIIX4.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
|
||||
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/SmbusI801.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
|
||||
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/SmbusNCT6793.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
|
||||
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/SmbusIntelSkylakeIMC.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
|
||||
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/LpcIO.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
|
||||
first.depends = $(first) copydata
|
||||
export(first.depends)
|
||||
|
||||
@@ -94,3 +94,10 @@ const std::string StringUtils::remove_null_terminating_chars(std::string input)
|
||||
|
||||
return(input);
|
||||
}
|
||||
|
||||
std::string StringUtils::u32int_to_hexString(unsigned int value)
|
||||
{
|
||||
char hex_str[20] = {0};
|
||||
snprintf(hex_str, sizeof(hex_str), "%X", value);
|
||||
return std::string(hex_str);
|
||||
}
|
||||
@@ -18,4 +18,5 @@ public:
|
||||
static std::string wstring_to_string(const std::wstring wstring);
|
||||
static std::string u16string_to_string(const std::u16string wstring);
|
||||
static const std::string remove_null_terminating_chars(std::string input);
|
||||
static std::string u32int_to_hexString(unsigned int value);
|
||||
};
|
||||
|
||||
Binary file not shown.
@@ -147,7 +147,7 @@ bool i2c_smbus_linux_detect()
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
strncat(path, ent->d_name, sizeof(path) - strlen(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
if(ent->d_type == DT_LNK)
|
||||
if(ent->d_type == DT_LNK || ent->d_type == DT_UNKNOWN)
|
||||
{
|
||||
ptr = realpath(path, NULL);
|
||||
if(ptr == NULL)
|
||||
@@ -155,9 +155,20 @@ bool i2c_smbus_linux_detect()
|
||||
|
||||
strncpy(path, ptr, sizeof(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
strncat(path, "/..", sizeof(path) - strlen(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
free(ptr);
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Truncate at last '/' to get the parent PCI device directory. |
|
||||
| For AMDGPU i2c buses the realpath resolves to something like: |
|
||||
| /sys/devices/pci.../0000:03:00.0/i2c-4 |
|
||||
| The parent (0000:03:00.0) contains vendor/device/subsystem |
|
||||
| files. Using /..' traversal is unreliable in sysfs; directly |
|
||||
| truncating the path is correct and portable. |
|
||||
\*-------------------------------------------------------------*/
|
||||
char* last_slash = strrchr(path, '/');
|
||||
if(last_slash == NULL || last_slash == path)
|
||||
continue;
|
||||
*last_slash = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -385,6 +385,15 @@ bool i2c_smbus_pawnio_detect()
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Try to load Intel Skylake IMC SMBus driver |
|
||||
\*-----------------------------------------------------*/
|
||||
if(i2c_smbus_pawnio::start_pawnio("SmbusIntelSkylakeIMC.bin", &pawnio_handle) == S_OK)
|
||||
{
|
||||
bus = new i2c_smbus_pawnio(pawnio_handle, "Intel Skylake IMC");
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -358,11 +358,13 @@
|
||||
#define ASUS_TUF_RTX_5060_O8G_GAMING 0x8A1A
|
||||
#define ASUS_TUF_RTX_5070_O12G_GAMING 0x89F2
|
||||
#define ASUS_TUF_RTX_5070TI_O16G_GAMING 0x89F4
|
||||
#define ASUS_TUF_RTX_5070TI_O16G_GAMING_WHITE 0x8A0C
|
||||
#define ASUS_ROG_STRIX_RTX_5070TI_O16G_GAMING_OC 0x8A0D
|
||||
#define ASUS_TUF_RTX_5080_O16G_GAMING 0x89D7
|
||||
#define ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING 0x89DE
|
||||
#define ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING_WHITE 0x8A2B
|
||||
#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_BTF 0x8A3C
|
||||
#define ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_WHITE 0x8A2E
|
||||
@@ -442,6 +444,8 @@
|
||||
#define COLORFUL_IGAME_RTX_4080_ULTRAW_OCV2 0x1501
|
||||
#define COLORFUL_IGAME_RTX_4090_ADVANCED_OCV 0x1400
|
||||
#define COLORFUL_IGAME_RTX_4090_ADVANCED_OCV2 0x1401
|
||||
#define COLORFUL_IGAME_RTX_5060_ULTRAW_OC 0x1500
|
||||
#define COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC_2 0x1530
|
||||
#define COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC 0x1531
|
||||
#define COLORFUL_IGAME_RTX_5070_ULTRAW_OCV 0x1500
|
||||
#define COLORFUL_IGAME_RTX_5070_ULTRAW_OCV2 0x1501
|
||||
@@ -721,6 +725,7 @@
|
||||
#define GIGABYTE_RTX5080_GAMING_OC_16G_SUB_DEV 0x4176
|
||||
#define GIGABYTE_AORUS_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV 0x418A
|
||||
#define GIGABYTE_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV 0x418B
|
||||
#define GIGABYTE_AORUS_RTX5080_MASTER_ICE_16G_SUB_DEV 0x418C
|
||||
#define GIGABYTE_AORUS_RTX5080_MASTER_16G_SUB_DEV 0x4178
|
||||
#define GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV 0x416F
|
||||
#define GIGABYTE_AORUS_RTX5090_MASTER_32G_SUB_DEV 0x416E
|
||||
@@ -741,6 +746,7 @@
|
||||
#define GIGABYTE_RX9070XT_GAMING_16G_SUB_DEV 0x2431
|
||||
#define GIGABYTE_RX7900GRE_GAMING_OC_16G_SUB_DEV 0x2410
|
||||
#define GIGABYTE_RX7900XT_GAMING_OC_20G_SUB_DEV 0x240C
|
||||
#define GIGABYTE_AORUS_RX7900XTX_ELITE_24G_SUB_DEV 0x240D
|
||||
#define GIGABYTE_RX7600_GAMING_OC_8G_SUB_DEV 0x240B
|
||||
#define GIGABYTE_RX7900XTX_GAMING_OC_24G_SUB_DEV 0x240E
|
||||
#define GIGABYTE_RX7600_GAMING_OC_8G_SUB_DEV2 0x242B
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
# OpenRGB MSI Builder for Windows
|
||||
# PowerShell conversion of build-msi.sh
|
||||
|
||||
# Add Wix to path
|
||||
$env:Path += ";C:\Program Files (x86)\WiX Toolset v3.14\bin"
|
||||
|
||||
# Add Qt to path
|
||||
$env:Path += ";C:\Qt\6.8.3\msvc2022_64\bin"
|
||||
|
||||
# Function to generate random UUID v4
|
||||
function Generate-UUIDv4
|
||||
{
|
||||
return [guid]::NewGuid().ToString().ToUpper()
|
||||
}
|
||||
|
||||
# Function to generate namespace-based UUID (SHA1)
|
||||
function Generate-NamespaceUUID
|
||||
{
|
||||
param
|
||||
(
|
||||
[guid]$Namespace,
|
||||
[string]$Name
|
||||
)
|
||||
|
||||
$nameBytes = [System.Text.Encoding]::UTF8.GetBytes($Name)
|
||||
$combined = $Namespace.ToByteArray() + $nameBytes
|
||||
$hash = [System.Security.Cryptography.SHA1]::Create().ComputeHash($combined)
|
||||
|
||||
# Set version to 5 (SHA1-based namespace UUID)
|
||||
$hash[6] = ($hash[6] -band 0x0f) -bor 0x50
|
||||
$hash[8] = ($hash[8] -band 0x3f) -bor 0x80
|
||||
|
||||
$uuidBytes = [byte[]]($hash[0..15])
|
||||
$uuid = [guid]$uuidBytes
|
||||
|
||||
return $uuid.ToString().ToUpper()
|
||||
}
|
||||
|
||||
# Configuration
|
||||
$PRODUCTNAME = "OpenRGB"
|
||||
$VENDOR = $PRODUCTNAME
|
||||
|
||||
$TLD = "org"
|
||||
$WEBSITE = "https://$($PRODUCTNAME.ToLower()).$TLD"
|
||||
|
||||
# URL namespace UUID (RFC 4122, version 4 namespace)
|
||||
$URLNamespace = [guid]'6ba7b810-9dad-11d1-80b4-00c04fd430c8'
|
||||
$NAMESPACE = Generate-NamespaceUUID $URLNamespace $WEBSITE
|
||||
|
||||
$VENDOR_ID = "$TLD.$VENDOR"
|
||||
$APP_ID = "$VENDOR_ID.$($PRODUCTNAME.ToLower())"
|
||||
|
||||
$GITURL = "https://gitlab.com/CalcProgrammer1/OpenRGB/-"
|
||||
$GITPARAM = "?inline=false"
|
||||
$ICONFILE = "qt/OpenRGB.ico"
|
||||
$LICENSEFILE = "scripts/License.rtf"
|
||||
$BANNERIMAGE = "scripts/banner.bmp"
|
||||
$DIALOGBACKGROUND = "scripts/dialog_background.bmp"
|
||||
$PROJECT_FILE = "OpenRGB.pro"
|
||||
$XMLOUTFILE = "$($PRODUCTNAME.ToLower()).wxs"
|
||||
|
||||
# Extract version from project file
|
||||
$VERSION = & qmake $PROJECT_FILE 2>&1 | Select-String 'VERSION_WIX' | Select-Object -First 1 | ForEach-Object {
|
||||
$_.Line -split ':' | Select-Object -Last 1 | ForEach-Object { $_.Trim() }
|
||||
}
|
||||
|
||||
# Check for suffix to determine channel
|
||||
$CHANNEL = ""
|
||||
$SUFFIX = Select-String -Path $PROJECT_FILE -Pattern 'SUFFIX\s' | ForEach-Object {
|
||||
$_.Line -split '=' | Select-Object -Last 1 | ForEach-Object { $_.Trim() }
|
||||
}
|
||||
|
||||
if($SUFFIX)
|
||||
{
|
||||
$CHANNEL = "-git"
|
||||
}
|
||||
|
||||
# Calculate upgrade code
|
||||
$UPGRADECODE = Generate-NamespaceUUID ([guid]$NAMESPACE) $APP_ID
|
||||
|
||||
$PRODUCTCOMMENT = "Open source RGB lighting control that doesn't depend on manufacturer software."
|
||||
|
||||
# Print Metadata to the log
|
||||
Write-Host "Icon URL:`t" $GITURL$ICONFILE
|
||||
Write-Host "License URL:`t" $GITURL$LICENSEFILE
|
||||
Write-Host "AppID - Channel:`t" $APP_ID " - " $CHANNEL
|
||||
Write-Host "Upgrade UUID:`t" $UPGRADECODE
|
||||
Write-Host "Product Name:`t" $PRODUCTNAME
|
||||
Write-Host "Vendor - VendorID:`t`t" $VENDOR " - " $VENDOR_ID
|
||||
Write-Host "Version:`t" $VERSION
|
||||
|
||||
# Copy build directory to working path
|
||||
$BUILT_PATH = "OpenRGB Windows 64-bit\*"
|
||||
$WORKING_PATH = "OpenRGB Windows MSI Installer\"
|
||||
|
||||
if(Test-Path $BUILT_PATH)
|
||||
{
|
||||
Copy-Item -Path $BUILT_PATH -Destination $WORKING_PATH -Recurse -Force
|
||||
}
|
||||
|
||||
$count = 1
|
||||
$EXE_FILE = ""
|
||||
$SVC_FILE = ""
|
||||
$FILES = ""
|
||||
$COMPONENTS = ""
|
||||
$DIRECTORIES = ""
|
||||
|
||||
# Build file list for files in the working path
|
||||
Get-ChildItem -Path $WORKING_PATH -Force | ForEach-Object {
|
||||
$file = $_
|
||||
$filename = $_.Name
|
||||
|
||||
if($filename -eq "$PRODUCTNAME.exe")
|
||||
{
|
||||
# If this is the executable, treat as special case
|
||||
$script:EXE_ID = "$($PRODUCTNAME)00"
|
||||
$script:SVC_ID = "$($PRODUCTNAME)00_SVC"
|
||||
$script:EXE_FILE = " <File Id='$($script:EXE_ID)' Source='$WORKING_PATH$filename' KeyPath='yes'/>`r`n"
|
||||
$script:SVC_FILE = " <File Id='$($script:SVC_ID)' Source='$WORKING_PATH$filename' KeyPath='yes'/>`r`n"
|
||||
}
|
||||
elseif($_.PSIsContainer)
|
||||
{
|
||||
# If this is a directory, add another component
|
||||
$script:COMPONENTS += " <ComponentRef Id='$($filename)Files'/>`r`n"
|
||||
$guid = Generate-UUIDv4
|
||||
$TEMP = " <Directory Id='$filename' Name='$filename'>`r`n"
|
||||
$TEMP += " <Component Id='$($filename)Files' Guid='$guid'>`r`n"
|
||||
|
||||
Get-ChildItem -Path $file.FullName -Force | ForEach-Object {
|
||||
$filename2 = $_.Name
|
||||
$TEMP += " <File Id='$($PRODUCTNAME)$($script:count)' Source='$WORKING_PATH$filename/$filename2'/>`r`n"
|
||||
$script:count++
|
||||
}
|
||||
|
||||
$TEMP += " </Component>`r`n </Directory>`r`n"
|
||||
$script:DIRECTORIES += $TEMP
|
||||
}
|
||||
else
|
||||
{
|
||||
# Any other file to files list
|
||||
$script:FILES += " <File Id='$($PRODUCTNAME)$($script:count)' Source='$WORKING_PATH$filename'/>`r`n"
|
||||
$script:count++
|
||||
}
|
||||
}
|
||||
|
||||
# Create the Wix XML file
|
||||
$XML_FILE = ""
|
||||
|
||||
$XML_FILE += "<?xml version='1.0' encoding='windows-1252'?>`r`n"
|
||||
$XML_FILE += "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>`r`n"
|
||||
$XML_FILE += " <Product Name='$PRODUCTNAME' Manufacturer='$VENDOR'`r`n"
|
||||
$XML_FILE += " Id='*'`r`n"
|
||||
$XML_FILE += " UpgradeCode='$UPGRADECODE'`r`n"
|
||||
$XML_FILE += " Language='1033' Codepage='1252' Version='$VERSION'>`r`n"
|
||||
$XML_FILE += " <Package Keywords='Installer' Description='$PRODUCTNAME Installer'`r`n"
|
||||
$XML_FILE += " Comments=`"$PRODUCTCOMMENT`" Manufacturer='OpenRGB'`r`n"
|
||||
$XML_FILE += " InstallerVersion='200' Languages='1033' Compressed='yes' SummaryCodepage='1252' Platform='x64'/>`r`n"
|
||||
$XML_FILE += " <Media Id='1' Cabinet='$($PRODUCTNAME.ToLower()).cab' EmbedCab='yes'/>`r`n"
|
||||
$XML_FILE += " <Condition Message='This package supports Windows 64bit Only'>VersionNT64</Condition>`r`n"
|
||||
$XML_FILE += " <MajorUpgrade Schedule='afterInstallInitialize' AllowDowngrades='yes'/>`r`n"
|
||||
$XML_FILE += " <Icon Id='OpenRGBIcon' SourceFile='$ICONFILE'/>`r`n"
|
||||
$XML_FILE += " <Property Id='ARPPRODUCTICON' Value='OpenRGBIcon'/>`r`n"
|
||||
$XML_FILE += " <Property Id='ARPURLINFOABOUT' Value='https://www.openrgb.org'/>`r`n"
|
||||
$XML_FILE += " <Property Id='WIXUI_INSTALLDIR' Value='INSTALLDIR'/>`r`n"
|
||||
$XML_FILE += " <WixVariable Id='WixUILicenseRtf' Value='$LICENSEFILE'/>`r`n"
|
||||
$XML_FILE += " <WixVariable Id='WixUIBannerBmp' Value='$BANNERIMAGE'/>`r`n"
|
||||
$XML_FILE += " <WixVariable Id='WixUIDialogBmp' Value='$DIALOGBACKGROUND'/>`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <UI>`r`n"
|
||||
$XML_FILE += " <UIRef Id='WixUI_InstallDir'/>`r`n"
|
||||
$XML_FILE += " <UIRef Id='WixUI_ErrorProgressText'/>`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <Dialog Id='PawnIODialog' Width='370' Height='270' Title='!(loc.InstallDirDlg_Title)'>`r`n"
|
||||
$XML_FILE += " <Control Id='Next' Type='PushButton' X='236' Y='243' Width='56' Height='17' Default='yes' Text='!(loc.WixUINext)' />`r`n"
|
||||
$XML_FILE += " <Control Id='Back' Type='PushButton' X='180' Y='243' Width='56' Height='17' Text='!(loc.WixUIBack)' />`r`n"
|
||||
$XML_FILE += " <Control Id='Cancel' Type='PushButton' X='304' Y='243' Width='56' Height='17' Cancel='yes' Text='!(loc.WixUICancel)'>`r`n"
|
||||
$XML_FILE += " <Publish Event='SpawnDialog' Value='CancelDlg' />`r`n"
|
||||
$XML_FILE += " </Control>`r`n"
|
||||
$XML_FILE += " <Control Id='Description' Type='Text' X='25' Y='23' Width='280' Height='15' Transparent='yes' NoPrefix='yes' Text='Install PawnIO for RGB RAM and Motherboard control.' />`r`n"
|
||||
$XML_FILE += " <Control Id='Title' Type='Text' X='15' Y='6' Width='200' Height='15' Transparent='yes' NoPrefix='yes' Text='PawnIO' />`r`n"
|
||||
$XML_FILE += " <Control Id='BannerBitmap' Type='Bitmap' X='0' Y='0' Width='370' Height='44' TabSkip='no' Text='!(loc.InstallDirDlgBannerBitmap)' />`r`n"
|
||||
$XML_FILE += " <Control Id='BannerLine' Type='Line' X='0' Y='44' Width='373' Height='0' />`r`n"
|
||||
$XML_FILE += " <Control Id='BottomLine' Type='Line' X='0' Y='234' Width='373' Height='0' />`r`n"
|
||||
$XML_FILE += " <Control Id='MainText' Type='Text' X='40' Y='60' Width='300' Height='40' Text='OpenRGB uses the PawnIO driver to control RGB lighting on DRAM modules and some older motherboards. For these devices to work, you must manually install PawnIO by visiting the link below.' />`r`n"
|
||||
$XML_FILE += " <Control Id='SecondText' Type='Text' X='40' Y='100' Width='300' Height='40' Text='If you do not need support for these devices, you can safely skip this step and continue with the installation.' />`r`n"
|
||||
$XML_FILE += " <Control Id='MainLink' Type='Hyperlink' X='40' Y='140' Width='300' Height='20' Text='<a href=`"https://pawnio.eu`">https://pawnio.eu</a>' />`r`n"
|
||||
$XML_FILE += " <Control Id='ThirdText' Type='Text' X='40' Y='180' Width='300' Height='40' Text='With PawnIO installed, OpenRGB must be run as administrator to access these devices.' />`r`n"
|
||||
$XML_FILE += " </Dialog>`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <Dialog Id='ServiceDialog' Width='370' Height='270' Title='!(loc.InstallDirDlg_Title)'>`r`n"
|
||||
$XML_FILE += " <Control Id='Next' Type='PushButton' X='236' Y='243' Width='56' Height='17' Default='yes' Text='!(loc.WixUINext)' />`r`n"
|
||||
$XML_FILE += " <Control Id='Back' Type='PushButton' X='180' Y='243' Width='56' Height='17' Text='!(loc.WixUIBack)' />`r`n"
|
||||
$XML_FILE += " <Control Id='Cancel' Type='PushButton' X='304' Y='243' Width='56' Height='17' Cancel='yes' Text='!(loc.WixUICancel)'>`r`n"
|
||||
$XML_FILE += " <Publish Event='SpawnDialog' Value='CancelDlg' />`r`n"
|
||||
$XML_FILE += " </Control>`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <Control Id='Description' Type='Text' X='25' Y='23' Width='280' Height='15' Transparent='yes' NoPrefix='yes' Text='Choose whether to register $PRODUCTNAME as a system service.' />`r`n"
|
||||
$XML_FILE += " <Control Id='Title' Type='Text' X='15' Y='6' Width='200' Height='15' Transparent='yes' NoPrefix='yes' Text='$PRODUCTNAME Service' />`r`n"
|
||||
$XML_FILE += " <Control Id='BannerBitmap' Type='Bitmap' X='0' Y='0' Width='370' Height='44' TabSkip='no' Text='!(loc.InstallDirDlgBannerBitmap)' />`r`n"
|
||||
$XML_FILE += " <Control Id='BannerLine' Type='Line' X='0' Y='44' Width='373' Height='0' />`r`n"
|
||||
$XML_FILE += " <Control Id='BottomLine' Type='Line' X='0' Y='234' Width='373' Height='0' />`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <Control Id='TypicalText' Type='Text' X='40' Y='60' Width='300' Height='40' Text='Installing OpenRGB without registering as a system service means nothing runs automatically in the background by default. Accessing devices through PawnIO will require running OpenRGB as administrator.' />`r`n"
|
||||
$XML_FILE += " <Control Id='TypicalButton' Type='PushButton' X='40' Y='100' Width='200' Height='17' ToolTip='Does not register OpenRGB as a system service. Accessing certain devices will require running the application as administrator.' Default='yes' Text='Do not Install System Service (Default)'>`r`n"
|
||||
$XML_FILE += " <Publish Property='WixUI_InstallMode' Value='InstallTypical'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Event='SetInstallLevel' Value='1'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Event='NewDialog' Value='VerifyReadyDlg'>1</Publish>`r`n"
|
||||
$XML_FILE += " </Control>`r`n"
|
||||
$XML_FILE += " <Control Id='CompleteText' Type='Text' X='40' Y='120' Width='300' Height='40' Text='Installing OpenRGB as a system service means the application will run automatically in the background. Accessing devices through PawnIO will not require running OpenRGB as administrator.' />`r`n"
|
||||
$XML_FILE += " <Control Id='CompleteWarning' Type='Text' X='40' Y='160' Width='300' Height='40' Text='Warning: Installing OpenRGB as a system service is experimental in the current release. Settings do not synchronize between the user interface and the service. If you encounter issues with the service, you can uninstall it and use the non-service installation instead.' />`r`n"
|
||||
$XML_FILE += " <Control Id='CompleteButton' Type='PushButton' X='40' Y='210' Width='200' Height='17' ToolTip='Registers OpenRGB system service, allowing access to devices which require administrator access without having to run the application as administrator.' Text='Install System Service'>`r`n"
|
||||
$XML_FILE += " <Publish Property='WixUI_InstallMode' Value='InstallComplete'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Event='SetInstallLevel' Value='2'>2</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Event='NewDialog' Value='VerifyReadyDlg'>1</Publish>`r`n"
|
||||
$XML_FILE += " </Control>`r`n"
|
||||
$XML_FILE += " </Dialog>`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <Publish Dialog='InstallDirDlg' Control='Next' Event='NewDialog' Value='PawnIODialog' Order='5'>WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=`"1`"</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Dialog='VerifyReadyDlg' Control='Back' Event='NewDialog' Value='ServiceDialog' Order='2'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Dialog='PawnIODialog' Control='Next' Event='NewDialog' Value='ServiceDialog' Order='2'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Dialog='PawnIODialog' Control='Back' Event='NewDialog' Value='InstallDirDlg' Order='2'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Dialog='ServiceDialog' Control='Next' Event='NewDialog' Value='VerifyReadyDlg' Order='2'>1</Publish>`r`n"
|
||||
$XML_FILE += " <Publish Dialog='ServiceDialog' Control='Back' Event='NewDialog' Value='PawnIODialog' Order='2'>1</Publish>`r`n"
|
||||
$XML_FILE += " </UI>`r`n"
|
||||
$XML_FILE += "`r`n"
|
||||
$XML_FILE += " <Directory Id='TARGETDIR' Name='SourceDir'>`r`n"
|
||||
$XML_FILE += " <Directory Id='ProgramFiles64Folder'>`r`n"
|
||||
$XML_FILE += " <Directory Id='INSTALLDIR' Name='$PRODUCTNAME'>`r`n"
|
||||
|
||||
$guid1 = Generate-UUIDv4
|
||||
$XML_FILE += " <Component Id='$($PRODUCTNAME)Files' Guid='$guid1'>`r`n"
|
||||
$XML_FILE += $EXE_FILE
|
||||
$XML_FILE += $FILES
|
||||
$XML_FILE += " </Component>`r`n"
|
||||
|
||||
$guid2 = Generate-UUIDv4
|
||||
$XML_FILE += " <Component Id='$($PRODUCTNAME)Service' Guid='$guid2'>`r`n"
|
||||
$XML_FILE += $SVC_FILE
|
||||
$XML_FILE += " <ServiceInstall Id='ServiceInstaller' Type='ownProcess' Name='OpenRGB' DisplayName='OpenRGB' Description='OpenRGB SDK Server' Start='auto' Account='[SERVICEACCOUNT]' Password='[SERVICEPASSWORD]' ErrorControl='normal'/>`r`n"
|
||||
$XML_FILE += " <ServiceControl Id='StartService' Start='install' Stop='both' Remove='uninstall' Name='OpenRGB' Wait='yes'/>`r`n"
|
||||
$XML_FILE += " </Component>`r`n"
|
||||
$XML_FILE += $DIRECTORIES
|
||||
$XML_FILE += " </Directory>`r`n"
|
||||
$XML_FILE += " </Directory>`r`n"
|
||||
$XML_FILE += " <Directory Id='ProgramMenuFolder' Name='Programs'>`r`n"
|
||||
|
||||
$guid3 = Generate-UUIDv4
|
||||
$XML_FILE += " <Component Id='ProgramMenuShortcut' Guid='$guid3'>`r`n"
|
||||
$XML_FILE += " <Shortcut Id='startmenu$PRODUCTNAME' Directory='ProgramMenuFolder' Name='$PRODUCTNAME' Target='[#$EXE_ID]' WorkingDirectory='INSTALLDIR' Advertise='no'/>`r`n"
|
||||
$XML_FILE += " <RemoveFile Id='ProgramMenuShortcut' Name='$PRODUCTNAME.lnk' Directory='ProgramMenuFolder' On='uninstall'/>`r`n"
|
||||
$XML_FILE += " <RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes'/>`r`n"
|
||||
$XML_FILE += " </Component>`r`n"
|
||||
$XML_FILE += " </Directory>`r`n"
|
||||
$XML_FILE += " </Directory>`r`n"
|
||||
$XML_FILE += " <Feature Id='$($PRODUCTNAME)Application' Title='$PRODUCTNAME' Description='Install the $PRODUCTNAME application files.' Level='1' AllowAdvertise='no' ConfigurableDirectory='INSTALLDIR' InstallDefault='local'>`r`n"
|
||||
$XML_FILE += " <ComponentRef Id='$($PRODUCTNAME)Files'/>`r`n"
|
||||
$XML_FILE += $COMPONENTS
|
||||
$XML_FILE += " <ComponentRef Id='ProgramMenuShortcut'/>`r`n"
|
||||
$XML_FILE += " </Feature>`r`n"
|
||||
$XML_FILE += " <Feature Id='$($PRODUCTNAME)RegisterService' Title='$PRODUCTNAME' Description='Register $PRODUCTNAME as a system service.' Display='expand' Level='2' ConfigurableDirectory='INSTALLDIR'>`r`n"
|
||||
$XML_FILE += " <ComponentRef Id='$($PRODUCTNAME)Service'/>`r`n"
|
||||
$XML_FILE += " </Feature>`r`n"
|
||||
$XML_FILE += " </Product>`r`n"
|
||||
$XML_FILE += "</Wix>"
|
||||
|
||||
# Write XML file
|
||||
$XML_FILE | Out-File -FilePath $XMLOUTFILE -Encoding UTF8
|
||||
|
||||
# Print the XML for debugging
|
||||
Write-Host (Get-Content $XMLOUTFILE)
|
||||
|
||||
# Build the MSI package
|
||||
Write-Host "`nBuilding MSI package..."
|
||||
|
||||
$wixObjFile = "$($PRODUCTNAME.ToLower()).wixobj"
|
||||
$msiFile = "$($PRODUCTNAME)_Windows_64.msi"
|
||||
|
||||
& candle -arch x64 $XMLOUTFILE
|
||||
& light -sval -ext WixUIExtension $wixObjFile -out $msiFile
|
||||
+29
-7
@@ -115,6 +115,23 @@ XML_FILE+=" <UI>\r\n"
|
||||
XML_FILE+=" <UIRef Id='WixUI_InstallDir'/>\r\n"
|
||||
XML_FILE+=" <UIRef Id='WixUI_ErrorProgressText'/>\r\n"
|
||||
XML_FILE+="\r\n"
|
||||
XML_FILE+=" <Dialog Id='PawnIODialog' Width='370' Height='270' Title='!(loc.InstallDirDlg_Title)'>\r\n"
|
||||
XML_FILE+=" <Control Id='Next' Type='PushButton' X='236' Y='243' Width='56' Height='17' Default='yes' Text='!(loc.WixUINext)' />\r\n"
|
||||
XML_FILE+=" <Control Id='Back' Type='PushButton' X='180' Y='243' Width='56' Height='17' Text='!(loc.WixUIBack)' />\r\n"
|
||||
XML_FILE+=" <Control Id='Cancel' Type='PushButton' X='304' Y='243' Width='56' Height='17' Cancel='yes' Text='!(loc.WixUICancel)'>\r\n"
|
||||
XML_FILE+=" <Publish Event='SpawnDialog' Value='CancelDlg' />\r\n"
|
||||
XML_FILE+=" </Control>\r\n"
|
||||
XML_FILE+=" <Control Id='Description' Type='Text' X='25' Y='23' Width='280' Height='15' Transparent='yes' NoPrefix='yes' Text='Install PawnIO for RGB RAM and Motherboard control.' />\r\n"
|
||||
XML_FILE+=" <Control Id='Title' Type='Text' X='15' Y='6' Width='200' Height='15' Transparent='yes' NoPrefix='yes' Text='PawnIO' />\r\n"
|
||||
XML_FILE+=" <Control Id='BannerBitmap' Type='Bitmap' X='0' Y='0' Width='370' Height='44' TabSkip='no' Text='!(loc.InstallDirDlgBannerBitmap)' />\r\n"
|
||||
XML_FILE+=" <Control Id='BannerLine' Type='Line' X='0' Y='44' Width='373' Height='0' />\r\n"
|
||||
XML_FILE+=" <Control Id='BottomLine' Type='Line' X='0' Y='234' Width='373' Height='0' />\r\n"
|
||||
XML_FILE+=" <Control Id='MainText' Type='Text' X='40' Y='60' Width='300' Height='40' Text='OpenRGB uses the PawnIO driver to control RGB lighting on DRAM modules and some older motherboards. For these devices to work, you must manually install PawnIO by visiting the link below.' />\r\n"
|
||||
XML_FILE+=" <Control Id='SecondText' Type='Text' X='40' Y='100' Width='300' Height='40' Text='If you do not need support for these devices, you can safely skip this step and continue with the installation.' />\r\n"
|
||||
XML_FILE+=" <Control Id='MainLink' Type='Hyperlink' X='40' Y='140' Width='300' Height='20' Text='<a href=\"https://pawnio.eu\">https://pawnio.eu</a>' />\r\n"
|
||||
XML_FILE+=" <Control Id='ThirdText' Type='Text' X='40' Y='180' Width='300' Height='40' Text='With PawnIO installed, OpenRGB must be run as administrator to access these devices.' />\r\n"
|
||||
XML_FILE+=" </Dialog>\r\n"
|
||||
XML_FILE+="\r\n"
|
||||
XML_FILE+=" <Dialog Id='ServiceDialog' Width='370' Height='270' Title='!(loc.InstallDirDlg_Title)'>\r\n"
|
||||
XML_FILE+=" <Control Id='Next' Type='PushButton' X='236' Y='243' Width='56' Height='17' Default='yes' Text='!(loc.WixUINext)' />\r\n"
|
||||
XML_FILE+=" <Control Id='Back' Type='PushButton' X='180' Y='243' Width='56' Height='17' Text='!(loc.WixUIBack)' />\r\n"
|
||||
@@ -122,28 +139,33 @@ XML_FILE+=" <Control Id='Cancel' Type='PushButton' X='304' Y='243
|
||||
XML_FILE+=" <Publish Event='SpawnDialog' Value='CancelDlg' />\r\n"
|
||||
XML_FILE+=" </Control>\r\n"
|
||||
XML_FILE+="\r\n"
|
||||
XML_FILE+=" <Control Id='Description' Type='Text' X='25' Y='23' Width='280' Height='15' Transparent='yes' NoPrefix='yes' Text='Choose whether to register ${PRODUCTNAME} as a system service.' />\r\n"
|
||||
XML_FILE+=" <Control Id='Title' Type='Text' X='15' Y='6' Width='200' Height='15' Transparent='yes' NoPrefix='yes' Text='${PRODUCTNAME} Service' />\r\n"
|
||||
XML_FILE+=" <Control Id='Description' Type='Text' X='25' Y='23' Width='280' Height='15' Transparent='yes' NoPrefix='yes' Text='Choose whether to register $PRODUCTNAME as a system service.' />\r\n"
|
||||
XML_FILE+=" <Control Id='Title' Type='Text' X='15' Y='6' Width='200' Height='15' Transparent='yes' NoPrefix='yes' Text='$PRODUCTNAME Service' />\r\n"
|
||||
XML_FILE+=" <Control Id='BannerBitmap' Type='Bitmap' X='0' Y='0' Width='370' Height='44' TabSkip='no' Text='!(loc.InstallDirDlgBannerBitmap)' />\r\n"
|
||||
XML_FILE+=" <Control Id='BannerLine' Type='Line' X='0' Y='44' Width='373' Height='0' />\r\n"
|
||||
XML_FILE+=" <Control Id='BottomLine' Type='Line' X='0' Y='234' Width='373' Height='0' />\r\n"
|
||||
XML_FILE+="\r\n"
|
||||
XML_FILE+=" <Control Id='TypicalButton' Type='PushButton' X='40' Y='65' Width='200' Height='17' ToolTip='Does not register OpenRGB as a system service. Accessing certain devices will require running the application as administrator.' Default='yes' Text='Do not Install System Service (Default)'>\r\n"
|
||||
XML_FILE+=" <Control Id='TypicalText' Type='Text' X='40' Y='60' Width='300' Height='40' Text='Installing OpenRGB without registering as a system service means nothing runs automatically in the background by default. Accessing devices through PawnIO will require running OpenRGB as administrator.' />\r\n"
|
||||
XML_FILE+=" <Control Id='TypicalButton' Type='PushButton' X='40' Y='100' Width='200' Height='17' ToolTip='Does not register OpenRGB as a system service. Accessing certain devices will require running the application as administrator.' Default='yes' Text='Do not Install System Service (Default)'>\r\n"
|
||||
XML_FILE+=" <Publish Property='WixUI_InstallMode' Value='InstallTypical'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Event='SetInstallLevel' Value='1'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Event='NewDialog' Value='VerifyReadyDlg'>1</Publish>\r\n"
|
||||
XML_FILE+=" </Control>\r\n"
|
||||
XML_FILE+=" <Control Id='CompleteButton' Type='PushButton' X='40' Y='171' Width='200' Height='17' ToolTip='Registers OpenRGB system service, allowing access to devices which require administrator access without having to run the application as administrator.' Text='Install System Service'>\r\n"
|
||||
XML_FILE+=" <Control Id='CompleteText' Type='Text' X='40' Y='120' Width='300' Height='40' Text='Installing OpenRGB as a system service means the application will run automatically in the background. Accessing devices through PawnIO will not require running OpenRGB as administrator.' />\r\n"
|
||||
XML_FILE+=" <Control Id='CompleteWarning' Type='Text' X='40' Y='160' Width='300' Height='40' Text='Warning: Installing OpenRGB as a system service is experimental in the current release. Settings do not synchronize between the user interface and the service. If you encounter issues with the service, you can uninstall it and use the non-service installation instead.' />\r\n"
|
||||
XML_FILE+=" <Control Id='CompleteButton' Type='PushButton' X='40' Y='210' Width='200' Height='17' ToolTip='Registers OpenRGB system service, allowing access to devices which require administrator access without having to run the application as administrator.' Text='Install System Service'>\r\n"
|
||||
XML_FILE+=" <Publish Property='WixUI_InstallMode' Value='InstallComplete'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Event='SetInstallLevel' Value='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Event='SetInstallLevel' Value='2'>2</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Event='NewDialog' Value='VerifyReadyDlg'>1</Publish>\r\n"
|
||||
XML_FILE+=" </Control>\r\n"
|
||||
XML_FILE+=" </Dialog>\r\n"
|
||||
XML_FILE+="\r\n"
|
||||
XML_FILE+=" <Publish Dialog='InstallDirDlg' Control='Next' Event='NewDialog' Value='ServiceDialog' Order='5'>WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=\"1\"</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='InstallDirDlg' Control='Next' Event='NewDialog' Value='PawnIODialog' Order='5'>WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=`"1`"</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='VerifyReadyDlg' Control='Back' Event='NewDialog' Value='ServiceDialog' Order='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='PawnIODialog' Control='Next' Event='NewDialog' Value='ServiceDialog' Order='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='PawnIODialog' Control='Back' Event='NewDialog' Value='InstallDirDlg' Order='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='ServiceDialog' Control='Next' Event='NewDialog' Value='VerifyReadyDlg' Order='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='ServiceDialog' Control='Back' Event='NewDialog' Value='InstallDirDlg' Order='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" <Publish Dialog='ServiceDialog' Control='Back' Event='NewDialog' Value='PawnIODialog' Order='2'>1</Publish>\r\n"
|
||||
XML_FILE+=" </UI>\r\n"
|
||||
XML_FILE+="\r\n"
|
||||
XML_FILE+=" <Directory Id='TARGETDIR' Name='SourceDir'>\r\n"
|
||||
|
||||
Reference in New Issue
Block a user