Compare commits
56
Commits
next
...
show_hide_rework
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
227fd375fb | ||
|
|
069eeccb60 | ||
|
|
da77b63bea | ||
|
|
791d8820d6 | ||
|
|
05fbe381dd | ||
|
|
3b2466ba10 | ||
|
|
acc7fa6754 | ||
|
|
394a5c8eb0 | ||
|
|
ac6d89b611 | ||
|
|
46cdd6fbe1 | ||
|
|
14d543b9e4 | ||
|
|
8a831cef04 | ||
|
|
9fd79b1ad2 | ||
|
|
c9c37a4576 | ||
|
|
fe53d90664 | ||
|
|
8e8a9c8e05 | ||
|
|
dafc6e9cbc | ||
|
|
68b113bf86 | ||
|
|
eb5d8b579c | ||
|
|
56df76dbfc | ||
|
|
878f32fccf | ||
|
|
63828313bd | ||
|
|
31992acad1 | ||
|
|
bd41ba3b5c | ||
|
|
b9309c61e1 | ||
|
|
7fc8aea930 | ||
|
|
b35e119325 | ||
|
|
8fb790358f | ||
|
|
39c6dbf361 | ||
|
|
9d189d5b9b | ||
|
|
9e5c63cc64 | ||
|
|
b664f35e17 | ||
|
|
381e3ac70c | ||
|
|
e3225d93c4 | ||
|
|
1b3480bf8a | ||
|
|
a6bea17df2 | ||
|
|
28d73d74bc | ||
|
|
cf383cacdd | ||
|
|
d9b0995b44 | ||
|
|
79eb758a52 | ||
|
|
75463b8772 | ||
|
|
5da92fca4e | ||
|
|
d11be2aa0b | ||
|
|
285a7bce4e | ||
|
|
21009cdc45 | ||
|
|
a0cee2ce2b | ||
|
|
ba33ff0c35 | ||
|
|
795616e62d | ||
|
|
baa033ff7f | ||
|
|
33ec03d129 | ||
|
|
a0d5a985f0 | ||
|
|
1275fe816b | ||
|
|
d4e1ed5245 | ||
|
|
b833a43490 | ||
|
|
94295c52ba | ||
|
|
f32aa29ecd |
@@ -1,66 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| A4TechDetector.cpp |
|
||||
| |
|
||||
| Detector for A4Tech Devices |
|
||||
| |
|
||||
| Chris M (Dr_No) 30 Jun 2022 |
|
||||
| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "BloodyB820RController.h"
|
||||
#include "BloodyMouseController.h"
|
||||
#include "DetectionManager.h"
|
||||
#include "RGBController_BloodyB820R.h"
|
||||
#include "RGBController_BloodyMouse.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| A4 Tech USB vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define A4_TECH_VID 0x09DA
|
||||
|
||||
DetectedControllers DetectA4TechMouseControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
BloodyMouseController* controller = new BloodyMouseController(dev, info->path, info->product_id, name);
|
||||
RGBController_BloodyMouse* rgb_controller = new RGBController_BloodyMouse(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectBloodyB820R(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
BloodyB820RController* controller = new BloodyB820RController(dev, info->path, name);
|
||||
RGBController_BloodyB820R* rgb_controller = new RGBController_BloodyB820R(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W70 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W70_MAX_PID, 2, 0xFF33, 0x0518);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W90 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_MAX_PID, 2, 0xFF33, 0x053D);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W90 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_PRO_PID, 2, 0xFF33, 0x054D);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody B820R", DetectBloodyB820R, A4_TECH_VID, BLOODY_B820R_PID, 2, 0xFF52, 0x0210);
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| BloodyB820RControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Bloody B820R Devices |
|
||||
| |
|
||||
| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "BloodyB820RController.h"
|
||||
#include "DetectionManager.h"
|
||||
#include "RGBController_BloodyB820R.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| A4 Tech USB vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define A4_TECH_VID 0x09DA
|
||||
|
||||
DetectedControllers DetectBloodyB820R(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
BloodyB820RController* controller = new BloodyB820RController(dev, info->path, name);
|
||||
RGBController_BloodyB820R* rgb_controller = new RGBController_BloodyB820R(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody B820R", DetectBloodyB820R, A4_TECH_VID, BLOODY_B820R_PID, 2, 0xFF52, 0x0210);
|
||||
@@ -0,0 +1,44 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| BloodyMouseControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Bloody Mouse Devices |
|
||||
| |
|
||||
| Chris M (Dr_No) 30 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "BloodyMouseController.h"
|
||||
#include "DetectionManager.h"
|
||||
#include "RGBController_BloodyMouse.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| A4 Tech USB vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define A4_TECH_VID 0x09DA
|
||||
|
||||
DetectedControllers DetectBloodyMouseControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
BloodyMouseController* controller = new BloodyMouseController(dev, info->path, info->product_id, name);
|
||||
RGBController_BloodyMouse* rgb_controller = new RGBController_BloodyMouse(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W70 Max", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W70_MAX_PID, 2, 0xFF33, 0x0518);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W90 Max", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W90_MAX_PID, 2, 0xFF33, 0x053D);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody W90 Pro", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W90_PRO_PID, 2, 0xFF33, 0x054D);
|
||||
REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009);
|
||||
@@ -334,9 +334,14 @@ void RGBController_PolychromeUSB::DeviceUpdateLEDs()
|
||||
}
|
||||
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
if(zones[zone_idx].leds_count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char set_mode = zones_info[zone_idx].mode;
|
||||
|
||||
if (set_mode>modes.size())
|
||||
if(set_mode>modes.size())
|
||||
{
|
||||
set_mode = active_mode;
|
||||
}
|
||||
@@ -347,6 +352,11 @@ void RGBController_PolychromeUSB::DeviceUpdateLEDs()
|
||||
|
||||
void RGBController_PolychromeUSB::DeviceUpdateZoneLEDs(int zone)
|
||||
{
|
||||
if(zones[zone].leds_count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char set_mode=zones_info[zone].mode;
|
||||
|
||||
if(set_mode > modes.size())
|
||||
@@ -354,7 +364,7 @@ void RGBController_PolychromeUSB::DeviceUpdateZoneLEDs(int zone)
|
||||
set_mode = active_mode;
|
||||
}
|
||||
|
||||
controller->WriteZone(zone, set_mode, zones_info[zone].speed, zones[zone].colors[0], false);
|
||||
controller->WriteZone((unsigned char)zone, set_mode, zones_info[zone].speed, zones[zone].colors[0], false);
|
||||
}
|
||||
|
||||
void RGBController_PolychromeUSB::DeviceUpdateSingleLED(int led)
|
||||
@@ -362,12 +372,17 @@ void RGBController_PolychromeUSB::DeviceUpdateSingleLED(int led)
|
||||
unsigned int channel = leds[led].value;
|
||||
unsigned char set_mode = zones_info[channel].mode;
|
||||
|
||||
if(zones[channel].leds_count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(set_mode > modes.size())
|
||||
{
|
||||
set_mode = active_mode;
|
||||
}
|
||||
|
||||
controller->WriteZone(channel, set_mode, zones_info[channel].speed, zones[channel].colors[0], false);
|
||||
controller->WriteZone((unsigned char)channel, set_mode, zones_info[channel].speed, zones[channel].colors[0], false);
|
||||
}
|
||||
|
||||
unsigned char RGBController_PolychromeUSB::GetDeviceMode(unsigned char zone)
|
||||
|
||||
+4
-26
@@ -1,7 +1,7 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| AlienwareKeyboardControllerDetect.cpp |
|
||||
| AlienwareAW410KControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Alienware Keyboard |
|
||||
| Detector for Alienware AW410K Keyboard |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
@@ -10,38 +10,17 @@
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "AlienwareAW410KController.h"
|
||||
#include "AlienwareAW510KController.h"
|
||||
#include "RGBController_AlienwareAW410K.h"
|
||||
#include "RGBController_AlienwareAW510K.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Alienware vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define ALIENWARE_VID 0x04F2
|
||||
#define ALIENWARE_VID 0x04F2
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define ALIENWARE_AW510K_PID 0x1830
|
||||
#define ALIENWARE_AW410K_PID 0x1968
|
||||
|
||||
DetectedControllers DetectAlienwareAW510KControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
AlienwareAW510KController* controller = new AlienwareAW510KController(dev, info->path, name);
|
||||
RGBController_AlienwareAW510K* rgb_controller = new RGBController_AlienwareAW510K(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
#define ALIENWARE_AW410K_PID 0x1968
|
||||
|
||||
DetectedControllers DetectAlienwareAW410KControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
@@ -61,5 +40,4 @@ DetectedControllers DetectAlienwareAW410KControllers(hid_device_info* info, cons
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Alienware AW510K", DetectAlienwareAW510KControllers, ALIENWARE_VID, ALIENWARE_AW510K_PID, 0x02, 0xFF00, 0x01);
|
||||
REGISTER_HID_DETECTOR_IPU("Alienware AW410K", DetectAlienwareAW410KControllers, ALIENWARE_VID, ALIENWARE_AW410K_PID, 0x02, 0xFF00, 0x01);
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| AlienwareAW510KControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Alienware AW510K Keyboard |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "AlienwareAW510KController.h"
|
||||
#include "RGBController_AlienwareAW510K.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Alienware vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define ALIENWARE_VID 0x04F2
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define ALIENWARE_AW510K_PID 0x1830
|
||||
|
||||
DetectedControllers DetectAlienwareAW510KControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
AlienwareAW510KController* controller = new AlienwareAW510KController(dev, info->path, name);
|
||||
RGBController_AlienwareAW510K* rgb_controller = new RGBController_AlienwareAW510K(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Alienware AW510K", DetectAlienwareAW510KControllers, ALIENWARE_VID, ALIENWARE_AW510K_PID, 0x02, 0xFF00, 0x01);
|
||||
@@ -45,7 +45,8 @@ void ColorfulGPUController::SetDirect(RGBColor color)
|
||||
uint8_t g = RGBGetGValue(color);
|
||||
uint8_t b = RGBGetBValue(color);
|
||||
|
||||
if(this->bus->info.pci_subsystem_device == COLORFUL_IGAME_RTX_4070_VULCAN_OCV)
|
||||
if(this->bus->info.pci_subsystem_device == COLORFUL_IGAME_RTX_4070_VULCAN_OCV
|
||||
|| this->bus->info.pci_subsystem_device == COLORFUL_IGAME_RTX_4090_NEPTUNE_OCV)
|
||||
{
|
||||
uint8_t data_pkt[COLORFUL_PACKET_LENGTH_V2] = { 0xAA, 0xEF, 0x01, 0x04, 0x88, 0x26 };
|
||||
for(int i=6; i < COLORFUL_PACKET_LENGTH_V2 -2; i = i + 3)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*---------------------------------------------------------*\
|
||||
/*---------------------------------------------------------*\
|
||||
| ColorfulGPUControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Colorful GPU |
|
||||
@@ -74,6 +74,7 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Vulcan OC-V", Detec
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 SUPER Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070S_ULTRAW_OCV, 0x61);
|
||||
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_OCV, 0x61);
|
||||
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 Neptune OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_NEPTUNE_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_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 Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060_ULTRAW_OC, 0x61);
|
||||
@@ -81,4 +82,5 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ultra W OC", Detec
|
||||
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);
|
||||
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);
|
||||
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ti Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070TI_ULTRAW_OC, 0x61);
|
||||
@@ -526,27 +526,26 @@ void CorsairPeripheralController::ReadFirmwareInfo()
|
||||
char offset = 0;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
| Some Corsair keyboards (e.g. K70 RGB MK.2) do not |
|
||||
| answer the firmware-info query on the control |
|
||||
| interface until several seconds after the host first |
|
||||
| talks to them following a cold boot. A single read |
|
||||
| attempt returns all zeros, the device type comes back |
|
||||
| as 0x00, and the device is discarded as UNKNOWN. |
|
||||
| Retry the query until a valid device type byte is |
|
||||
| returned or the attempt cap is reached. Each failed |
|
||||
| attempt is paced by the 1s hid_read_timeout below, so |
|
||||
| the cap also bounds the detection stall for a device |
|
||||
| that opens but never answers. Observed need |
|
||||
| on a K70 RGB MK.2 cold boot is 2 attempts; the cap |
|
||||
| leaves generous headroom. |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
int attempt = 0;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up Read Firmware Info packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = CORSAIR_COMMAND_READ;
|
||||
usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet and try reading it using an HID read |
|
||||
| If that fails, repeat the send and read the reply as |
|
||||
| a feature report. |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
actual = hid_read_timeout(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH, 1000);
|
||||
|
||||
if(actual == 0)
|
||||
do
|
||||
{
|
||||
offset = 0;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-------------------------------------------------*/
|
||||
@@ -559,10 +558,48 @@ void CorsairPeripheralController::ReadFirmwareInfo()
|
||||
usb_buf[0x01] = CORSAIR_COMMAND_READ;
|
||||
usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
actual = hid_get_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
offset = 1;
|
||||
}
|
||||
/*-------------------------------------------------*\
|
||||
| Send packet and try reading it using an HID read |
|
||||
| If that fails, repeat the send and read the reply |
|
||||
| as a feature report. |
|
||||
\*-------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
actual = hid_read_timeout(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH, 1000);
|
||||
|
||||
if(actual == 0)
|
||||
{
|
||||
/*---------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*---------------------------------------------*/
|
||||
memset(usb_buf, 0x00, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| Set up Read Firmware Info packet |
|
||||
\*---------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = CORSAIR_COMMAND_READ;
|
||||
usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
actual = hid_get_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
attempt++;
|
||||
|
||||
LOG_DEBUG("[%s] Firmware info attempt %d/%d: device type %02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, attempt, CORSAIR_FW_INFO_MAX_ATTEMPTS, usb_buf[0x14 + offset]);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Stop as soon as a valid device type is returned |
|
||||
| 0xC0 keyboard / 0xC1 mouse / 0xC2 pad or stand |
|
||||
\*-------------------------------------------------*/
|
||||
if(usb_buf[0x14 + offset] == 0xC0
|
||||
|| usb_buf[0x14 + offset] == 0xC1
|
||||
|| usb_buf[0x14 + offset] == 0xC2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while(attempt < CORSAIR_FW_INFO_MAX_ATTEMPTS);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Get device type |
|
||||
@@ -570,7 +607,7 @@ void CorsairPeripheralController::ReadFirmwareInfo()
|
||||
| 0xC1 Device is a mouse |
|
||||
| 0xC2 Device is a mousepad or headset stand |
|
||||
\*-----------------------------------------------------*/
|
||||
LOG_DEBUG("[%s] Device type %02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, usb_buf[0x14 + offset]);
|
||||
LOG_DEBUG("[%s] Device type %02X after %d attempt(s)", CORSAIR_PERIPHERAL_CONTROLLER_NAME, usb_buf[0x14 + offset], attempt);
|
||||
|
||||
switch(usb_buf[0x14 + offset])
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "RGBController.h"
|
||||
|
||||
#define CORSAIR_PERIPHERAL_PACKET_LENGTH 65
|
||||
#define CORSAIR_FW_INFO_MAX_ATTEMPTS 10
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| EVGAKeyboardControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for EVGA keyboard devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "RGBController_EVGAKeyboard.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| EVGA USB vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVGA_USB_VID 0x3842
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define Z15_ISO_PID 0x260E
|
||||
#define Z15_ANSI_PID 0x2608
|
||||
#define Z20_ANSI_PID 0x260A
|
||||
#define Z20_UK_PID 0x2610
|
||||
|
||||
DetectedControllers DetectEVGAKeyboardControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVGAKeyboardController* controller = new EVGAKeyboardController(dev, info->path, info->product_id, name);
|
||||
RGBController_EVGAKeyboard* rgb_controller = new RGBController_EVGAKeyboard(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ISO_PID, 1, 0x08, 0x4B);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ANSI_PID, 1, 0x08, 0x4B);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_ANSI_PID, 1, 0x08, 0x4B);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_UK_PID, 1, 0x08, 0x4B);
|
||||
|
||||
+5
-37
@@ -1,7 +1,7 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| EVGAUSBControllerDetect.cpp |
|
||||
| EVGAMouseControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for EVGA USB devices |
|
||||
| Detector for EVGA mouse devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
@@ -9,45 +9,18 @@
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "RGBController_EVGAKeyboard.h"
|
||||
#include "RGBController_EVGAMouse.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| EVGA USB vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVGA_USB_VID 0x3842
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define Z15_ISO_PID 0x260E
|
||||
#define Z15_ANSI_PID 0x2608
|
||||
#define Z20_ANSI_PID 0x260A
|
||||
#define Z20_UK_PID 0x2610
|
||||
#define EVGA_USB_VID 0x3842
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Mouse product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define X20_WIRED_PID 0x2420
|
||||
#define X20_WIRELESS_ADAPTER_PID 0x2402
|
||||
|
||||
DetectedControllers DetectEVGAKeyboardControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVGAKeyboardController* controller = new EVGAKeyboardController(dev, info->path, info->product_id, name);
|
||||
RGBController_EVGAKeyboard* rgb_controller = new RGBController_EVGAKeyboard(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
#define X20_WIRED_PID 0x2420
|
||||
#define X20_WIRELESS_ADAPTER_PID 0x2402
|
||||
|
||||
DetectedControllers DetectEVGAMouse(hid_device_info* info, const std::string &name, int connection_type)
|
||||
{
|
||||
@@ -77,10 +50,5 @@ DetectedControllers DetectWirelessEVGAMouse(hid_device_info* info, const std::st
|
||||
return(DetectEVGAMouse(info, name, EVGA_PERIPHERAL_CONNECTION_TYPE_WIRELESS));
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ISO_PID, 1, 0x08, 0x4B);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ANSI_PID, 1, 0x08, 0x4B);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_ANSI_PID, 1, 0x08, 0x4B);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_UK_PID, 1, 0x08, 0x4B);
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA X20 Gaming Mouse", DetectWiredEVGAMouse, EVGA_USB_VID, X20_WIRED_PID, 2, 0xFFFF, 0);
|
||||
REGISTER_HID_DETECTOR_IPU("EVGA X20 USB Receiver", DetectWirelessEVGAMouse, EVGA_USB_VID, X20_WIRELESS_ADAPTER_PID, 2, 0xFFFF, 0);
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| EVisionKeyboardControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for EVision/Huafenda keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "EVisionKeyboardController.h"
|
||||
#include "RGBController_EVisionKeyboard.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| EVision vendor ID |
|
||||
| NOTE: EVision (and Huafenda) use rebranded Sonix MCUs |
|
||||
| Some EVision/Huafenda keyboards use the Sonix VID while |
|
||||
| others use EVision's VID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define SONIX_VID 0x0C45
|
||||
#define EVISION_VID 0x320F
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| EVision Usage Page |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVISION_SONIX_5004_PID 0x5004
|
||||
#define EVISION_SONIX_5104_PID 0x5104
|
||||
#define EVISION_SONIX_5204_PID 0x5204
|
||||
#define EVISION_SONIX_652F_PID 0x652F
|
||||
#define EVISION_SONIX_7672_PID 0x7672
|
||||
#define EVISION_SONIX_7698_PID 0x7698
|
||||
#define EVISION_SONIX_8520_PID 0x8520
|
||||
#define EVISION_5000_PID 0x5000
|
||||
#define EVISION_502A_PID 0x502A
|
||||
#define EVISION_505B_PID 0x505B
|
||||
#define EVISION_5064_PID 0x5064
|
||||
#define EVISION_5078_PID 0x5078
|
||||
#define EVISION_5084_PID 0x5084
|
||||
|
||||
DetectedControllers DetectEVisionKeyboards(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVisionKeyboardController* controller = new EVisionKeyboardController(dev, info->path, name);
|
||||
RGBController_EVisionKeyboard* rgb_controller = new RGBController_EVisionKeyboard(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboards |
|
||||
\*---------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5004", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_5004_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5104", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_5104_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5204", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_5204_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:652F", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_652F_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7672", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_7672_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7698", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_7698_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:8520", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_8520_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5000", DetectEVisionKeyboards, EVISION_VID, EVISION_5000_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:502A", DetectEVisionKeyboards, EVISION_VID, EVISION_502A_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:505B", DetectEVisionKeyboards, EVISION_VID, EVISION_505B_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5078", DetectEVisionKeyboards, EVISION_VID, EVISION_5078_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5064", DetectEVisionKeyboards, EVISION_VID, EVISION_5064_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5084", DetectEVisionKeyboards, EVISION_VID, EVISION_5084_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
@@ -1,129 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| EVisionKeyboardControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for EVision keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "EVisionKeyboardController.h"
|
||||
#include "EVisionV2KeyboardController.h"
|
||||
#include "RGBController_EVisionKeyboard.h"
|
||||
#include "RGBController_EVisionV2Keyboard.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVISION_KEYBOARD_VID 0x0C45
|
||||
#define EVISION_KEYBOARD2_VID 0x320F
|
||||
#define EVISION_KEYBOARD3_VID 0x3299
|
||||
#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C
|
||||
#define ENDORFY_OMNIS_PID 0x0012
|
||||
#define DEXP_BLAZE_PID 0x5084
|
||||
#define GLORIOUS_GMMK_TKL_PID 0x5064
|
||||
#define REDRAGON_K550_PID 0x5204
|
||||
#define MARS_GAMING_MKMINI_PID 0x5078
|
||||
#define SKILLKORP_K5_PID 0x505B
|
||||
#define REDRAGON_K552_PID 0x5104
|
||||
#define REDRAGON_K552_V2_PID 0x5000
|
||||
#define REDRAGON_K556_PID 0x5004
|
||||
#define TECWARE_PHANTOM_ELITE_PID 0x652F
|
||||
#define WARRIOR_KANE_TC235 0x8520
|
||||
#define WOMIER_K87_PID 0x502A
|
||||
#define WOMIER_K66_PID 0x7698
|
||||
#define BYGG_CSB_ICL01_PID 0x5041
|
||||
#define GAMEPOWER_OGRE_RGB_PID 0x7672
|
||||
|
||||
DetectedControllers DetectEVisionKeyboards(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVisionKeyboardController* controller = new EVisionKeyboardController(dev, info->path, name);
|
||||
RGBController_EVisionKeyboard* rgb_controller = new RGBController_EVisionKeyboard(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectEVisionV2Keyboards(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EVision2Settings");
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, EVISION_V2_KEYBOARD_LAYOUT, name);
|
||||
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
|
||||
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
|
||||
{
|
||||
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_LOGO);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
|
||||
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_EDGE);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectEndorfyKeyboards(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EndorfySettings");
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, ENDORFY_KEYBOARD_LAYOUT, name);
|
||||
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
|
||||
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
|
||||
{
|
||||
rgb_controller = new RGBController_EVisionV2Keyboard(controller, ENDORFY_KEYBOARD_PART_EDGE);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Keyboards |
|
||||
\*---------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5078", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, MARS_GAMING_MKMINI_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5204", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K550_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5104", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K552_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5000", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, REDRAGON_K552_V2_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5004", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K556_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:652F", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, TECWARE_PHANTOM_ELITE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:8520", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WARRIOR_KANE_TC235, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:502A", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, WOMIER_K87_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7698", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WOMIER_K66_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5064", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, GLORIOUS_GMMK_TKL_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5084", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, DEXP_BLAZE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:505B", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, SKILLKORP_K5_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("Endorfy Omnis", DetectEndorfyKeyboards, EVISION_KEYBOARD3_VID, ENDORFY_OMNIS_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("CSB/ICL01 Keyboard", DetectEVisionV2Keyboards, EVISION_KEYBOARD2_VID, BYGG_CSB_ICL01_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("Gamepower Ogre RGB 0C45:7672", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, GAMEPOWER_OGRE_RGB_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| EVisionKeyboardV2ControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for EVision V2 keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "EVisionV2KeyboardController.h"
|
||||
#include "RGBController_EVisionV2Keyboard.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| EVision vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVISION_VID 0x320F
|
||||
#define SPCGEAR_VID 0x3299
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| EVision Usage Page |
|
||||
\*---------------------------------------------------------*/
|
||||
#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define ENDORFY_OMNIS_PID 0x0012
|
||||
#define BYGG_CSB_ICL01_PID 0x5041
|
||||
|
||||
DetectedControllers DetectEVisionV2Keyboards(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EVision2Settings");
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, EVISION_V2_KEYBOARD_LAYOUT, name);
|
||||
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
|
||||
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
|
||||
{
|
||||
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_LOGO);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
|
||||
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_EDGE);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectEndorfyKeyboards(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EndorfySettings");
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, ENDORFY_KEYBOARD_LAYOUT, name);
|
||||
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
|
||||
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
|
||||
{
|
||||
rgb_controller = new RGBController_EVisionV2Keyboard(controller, ENDORFY_KEYBOARD_PART_EDGE);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboards |
|
||||
\*---------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5041", DetectEVisionV2Keyboards, EVISION_VID, BYGG_CSB_ICL01_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
REGISTER_HID_DETECTOR_IP("Endorfy Omnis", DetectEndorfyKeyboards, SPCGEAR_VID, ENDORFY_OMNIS_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
|
||||
@@ -99,3 +99,4 @@ REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Phoenix", DetectGa
|
||||
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080TI_DEV, 0x49);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3090_DEV, 0x49);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Ti Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3090TI_PHANTOM, 0x49);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 4080 Phantom GS", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4080_PHANTOM_GS_SUB_DEV, 0x49);
|
||||
|
||||
@@ -170,6 +170,7 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER ICE",
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7600 GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7600_GAMING_OC_8G_SUB_DEV, 0x55);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7600 GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7600_GAMING_OC_8G_SUB_DEV2, 0x55);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7600 XT GAMING OC 16G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7600XT_GAMING_OC_16G_SUB_DEV, 0x55);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6700 XT EAGLE 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX6700XT_EAGLE_12G_SUB_DEV, 0x63);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6700 XT GAMING OC 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX6700XT_GAMING_OC_12G_SUB_DEV, 0x62);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6800 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, GIGABYTE_SUB_VEN, GIGABYTE_RX6800XT_GAMING_OC_SUB_DEV, 0x62);
|
||||
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6900 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, GIGABYTE_SUB_VEN, GIGABYTE_RX6900XT_GAMING_OC_SUB_DEV, 0x62);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,7 @@ RGBFusion2USBController::RGBFusion2USBController(hid_device* handle, const char*
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(report.support_cmd_flag >= 0x02)
|
||||
if(report.support_cmd_flag & 0x02)
|
||||
{
|
||||
EnableLampArray(false);
|
||||
}
|
||||
@@ -365,7 +365,18 @@ bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
|
||||
|
||||
if(hdr == -1)
|
||||
{
|
||||
bitmask = 0x01 | 0x02 | 0x08 | 0x10;
|
||||
switch(product_id)
|
||||
{
|
||||
case 0xa100:
|
||||
bitmask = 0x01;
|
||||
break;
|
||||
case 0x5711:
|
||||
bitmask = 0x01 | 0x02 | 0x08 | 0x10;
|
||||
break;
|
||||
default:
|
||||
bitmask = 0x01 | 0x02;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -394,8 +405,6 @@ bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
|
||||
int new_effect_disabled = enable
|
||||
? (base_mask & ~bitmask)
|
||||
: (base_mask | bitmask);
|
||||
|
||||
// Skip redundant writes only after we have synchronized at least once
|
||||
if(effect_disabled >= 0 && new_effect_disabled == effect_disabled)
|
||||
{
|
||||
return true;
|
||||
@@ -440,7 +449,11 @@ bool RGBFusion2USBController::EnableLampArray(bool enable)
|
||||
|
||||
std::string RGBFusion2USBController::GetDeviceName()
|
||||
{
|
||||
return(name);
|
||||
if(product_id == 0xa100)
|
||||
{
|
||||
return ("GC-USB");
|
||||
}
|
||||
return (name);
|
||||
}
|
||||
|
||||
std::string RGBFusion2USBController::GetDeviceDescription()
|
||||
@@ -736,31 +749,39 @@ std::vector<Gen2StripInfo> RGBFusion2USBController::ExportGen2Strips() const
|
||||
/*---------------------------------------------------------*\
|
||||
| Scan Headers for Gen2 Devices |
|
||||
\*---------------------------------------------------------*/
|
||||
bool RGBFusion2USBController::ScanGen2Strips()
|
||||
bool RGBFusion2USBController::ScanGen2Strips(uint8_t enabled_headers)
|
||||
{
|
||||
for(unsigned i = 0; i < 4; ++i)
|
||||
for(unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
if(g2_strip_info[i].LedsOfStrip.capacity() < 15)
|
||||
{
|
||||
g2_strip_info[i].LedsOfStrip.reserve(15);
|
||||
}
|
||||
g2_strip_info[i].numStrip = 0;
|
||||
g2_strip_info[i].totalLeds = 0;
|
||||
g2_strip_info[i].LedsOfStrip.resize(0);
|
||||
|
||||
g2_strip_info[i].numStrip = 0;
|
||||
g2_strip_info[i].totalLeds = 0;
|
||||
g2_strip_info[i].LedsOfStrip.clear();
|
||||
}
|
||||
|
||||
const unsigned int hdr_lim = (product_id == 0x5711) ? 4u : 2u;
|
||||
|
||||
for(unsigned int slot = 0; slot < hdr_lim; ++slot)
|
||||
{
|
||||
if(!(enabled_headers & (1U << slot)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
static constexpr uint8_t delta[4] = {4, 5, 0, 1};
|
||||
uint8_t scan_cmd = static_cast<uint8_t>(GEN2_LED_BASE_SCAN + delta[slot]);
|
||||
uint8_t info_cmd = static_cast<uint8_t>(scan_cmd + 2);
|
||||
|
||||
uint8_t scan_cmd = GEN2_LED_BASE_SCAN + delta[slot];
|
||||
uint8_t info_cmd = scan_cmd + 2;
|
||||
|
||||
if(!SendCCReport(scan_cmd, 0x00, 0x00))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(700));
|
||||
|
||||
if(!SendCCReport(info_cmd, 0x00, 0x00))
|
||||
@@ -768,48 +789,60 @@ bool RGBFusion2USBController::ScanGen2Strips()
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char feature_buf[64] = {0};
|
||||
feature_buf[0] = report_id;
|
||||
int recv_len = hid_get_feature_report(dev, feature_buf, sizeof(feature_buf));
|
||||
unsigned char feat_buf[64] = {0};
|
||||
feat_buf[0] = report_id;
|
||||
|
||||
int recv_len = hid_get_feature_report
|
||||
(
|
||||
dev,
|
||||
feat_buf,
|
||||
sizeof(feat_buf)
|
||||
);
|
||||
|
||||
if(recv_len < 64)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int seg_count = static_cast<int>(feature_buf[1]);
|
||||
if(seg_count < 0)
|
||||
{
|
||||
seg_count = 0;
|
||||
}
|
||||
int seg_count = feat_buf[1];
|
||||
|
||||
if(seg_count > 15)
|
||||
{
|
||||
seg_count = 15;
|
||||
seg_count = 15;
|
||||
}
|
||||
Gen2StripInfo& dst = g2_strip_info[slot];
|
||||
dst.numStrip = static_cast<uint8_t>(seg_count);
|
||||
dst.LedsOfStrip.resize(static_cast<size_t>(seg_count));
|
||||
|
||||
uint32_t total_leds = 0;
|
||||
const int counts_base = 2;
|
||||
Gen2StripInfo& dst = g2_strip_info[slot];
|
||||
dst.numStrip = seg_count;
|
||||
dst.LedsOfStrip.resize(seg_count);
|
||||
uint32_t total_leds = 0;
|
||||
const int counts_base = 2;
|
||||
|
||||
for(int k = 0; k < seg_count; ++k)
|
||||
{
|
||||
const int off = counts_base + (k * 2);
|
||||
uint16_t lo = static_cast<uint16_t>(feature_buf[off + 0]);
|
||||
uint16_t hi = static_cast<uint16_t>(feature_buf[off + 1]);
|
||||
uint16_t cnt = static_cast<uint16_t>(lo | (hi << 8));
|
||||
|
||||
dst.LedsOfStrip[static_cast<size_t>(k)] = cnt;
|
||||
total_leds += cnt;
|
||||
const int off = counts_base + (k * 2);
|
||||
uint16_t lo = feat_buf[off];
|
||||
uint16_t hi = feat_buf[off + 1];
|
||||
uint16_t cnt = lo | (hi << 8);
|
||||
dst.LedsOfStrip[k] = cnt;
|
||||
total_leds += cnt;
|
||||
}
|
||||
|
||||
dst.totalLeds = total_leds;
|
||||
dst.totalLeds = total_leds;
|
||||
|
||||
SetLedCount(0, 0, 0, 0);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
|
||||
SaveLEDState(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Check controller for persistent state support |
|
||||
\*---------------------------------------------------------*/
|
||||
bool RGBFusion2USBController::SupportsSaveLEDState() const
|
||||
{
|
||||
return(report_loaded && (report.support_cmd_flag & 0x01));
|
||||
}
|
||||
|
||||
@@ -234,6 +234,10 @@ union PktEffect
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
e.report_id = report_id;
|
||||
if(pid ==0xA100)
|
||||
{
|
||||
led = -1;
|
||||
}
|
||||
if(led == -1)
|
||||
{
|
||||
e.zone0 = (pid == 0x5711) ? 0x07FF : 0xFF;
|
||||
@@ -337,7 +341,9 @@ public:
|
||||
bool SetStripBuiltinEffectState(int hdr, bool enable);
|
||||
void SetStripColors(unsigned int hdr, RGBColor * colors, unsigned int num_colors, int single_led = -1);
|
||||
bool SupportsGen2() const;
|
||||
bool ScanGen2Strips();
|
||||
bool ScanGen2Strips(uint8_t hdr_mask);
|
||||
bool SaveLEDState(bool enable);
|
||||
bool SupportsSaveLEDState() const;
|
||||
|
||||
EncodedCalibration GetCalibration(bool refresh_from_hw = false);
|
||||
std::string GetDeviceName();
|
||||
@@ -357,7 +363,6 @@ private:
|
||||
uint32_t EncodeCalibrationBuffer(const std::string& rgb_order);
|
||||
bool RefreshHardwareInfo();
|
||||
void ResetController();
|
||||
bool SaveLEDState(bool enable);
|
||||
bool SaveCalState();
|
||||
bool SendCCReport(uint8_t a, uint8_t b, uint8_t c = 0);
|
||||
bool SendReport(uint8_t id, uint8_t a, uint8_t b, uint8_t c = 0);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#define DETECTOR_NAME "Gigabyte RGB Fusion 2 USB"
|
||||
|
||||
#define GC_USB_VID 0x0414
|
||||
#define IT8297_VID 0x048D
|
||||
#define IT8297_IFC 0
|
||||
#define IT8297_U 0xCC
|
||||
@@ -47,3 +48,4 @@ REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers,
|
||||
REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x8950, IT8297_UPG, IT8297_U);
|
||||
REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x5702, IT8297_UPG, IT8297_U);
|
||||
REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x5711, IT8297_UPG, IT8297_U);
|
||||
REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, GC_USB_VID, 0xa100, IT8297_UPG, IT8297_U);
|
||||
|
||||
+487
-104
@@ -46,7 +46,8 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0xFFFF;
|
||||
Direct.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Direct.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Direct.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -56,7 +57,9 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = EFFECT_STATIC;
|
||||
Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
|
||||
Static.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_MODE_SPECIFIC_COLOR
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Static.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Static.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Static.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -69,7 +72,11 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = EFFECT_PULSE;
|
||||
Breathing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
|
||||
Breathing.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_SPEED
|
||||
| MODE_FLAG_HAS_MODE_SPECIFIC_COLOR
|
||||
| MODE_FLAG_HAS_RANDOM_COLOR
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Breathing.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Breathing.brightness_max = 100; // Set 100 max due to controller quirks
|
||||
Breathing.brightness = Breathing.brightness_max;
|
||||
@@ -85,7 +92,11 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Blinking;
|
||||
Blinking.name = "Flashing";
|
||||
Blinking.value = EFFECT_BLINKING;
|
||||
Blinking.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
|
||||
Blinking.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_SPEED
|
||||
| MODE_FLAG_HAS_MODE_SPECIFIC_COLOR
|
||||
| MODE_FLAG_HAS_RANDOM_COLOR
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Blinking.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Blinking.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Blinking.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -101,7 +112,9 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode ColorCycle;
|
||||
ColorCycle.name = "Color Cycle";
|
||||
ColorCycle.value = EFFECT_COLORCYCLE;
|
||||
ColorCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
ColorCycle.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_SPEED
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
ColorCycle.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
ColorCycle.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
ColorCycle.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -114,7 +127,11 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Flashing;
|
||||
Flashing.name = "Double Flash";
|
||||
Flashing.value = EFFECT_DFLASH;
|
||||
Flashing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
|
||||
Flashing.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_SPEED
|
||||
| MODE_FLAG_HAS_MODE_SPECIFIC_COLOR
|
||||
| MODE_FLAG_HAS_RANDOM_COLOR
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Flashing.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Flashing.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Flashing.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -130,7 +147,10 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Wave;
|
||||
Wave.name = "Wave";
|
||||
Wave.value = EFFECT_WAVE;
|
||||
Wave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Wave.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_HAS_SPEED
|
||||
| MODE_FLAG_REQUIRES_ENTIRE_DEVICE
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Wave.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Wave.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Wave.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -145,7 +165,8 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Random;
|
||||
Random.name = "Random";
|
||||
Random.value = EFFECT_RANDOM;
|
||||
Random.flags = MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Random.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Random.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Random.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Random.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -157,7 +178,9 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Wave1;
|
||||
Wave1.name = "Wave 1";
|
||||
Wave1.value = EFFECT_WAVE1;
|
||||
Wave1.flags = MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Wave1.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_REQUIRES_ENTIRE_DEVICE
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Wave1.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Wave1.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Wave1.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -169,7 +192,9 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Wave2;
|
||||
Wave2.name = "Wave 2";
|
||||
Wave2.value = EFFECT_WAVE2;
|
||||
Wave2.flags = MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Wave2.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_REQUIRES_ENTIRE_DEVICE
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Wave2.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Wave2.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Wave2.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -181,7 +206,9 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Wave3;
|
||||
Wave3.name = "Wave 3";
|
||||
Wave3.value = EFFECT_WAVE3;
|
||||
Wave3.flags = MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Wave3.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_REQUIRES_ENTIRE_DEVICE
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Wave3.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Wave3.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Wave3.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -193,7 +220,9 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
mode Wave4;
|
||||
Wave4.name = "Wave 4";
|
||||
Wave4.value = EFFECT_WAVE4;
|
||||
Wave4.flags = MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Wave4.flags = MODE_FLAG_HAS_BRIGHTNESS
|
||||
| MODE_FLAG_REQUIRES_ENTIRE_DEVICE
|
||||
| MODE_FLAG_MANUAL_SAVE;
|
||||
Wave4.brightness_min = RGBFUSION2_BRIGHTNESS_MIN;
|
||||
Wave4.brightness_max = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
Wave4.brightness = RGBFUSION2_BRIGHTNESS_MAX;
|
||||
@@ -202,6 +231,14 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController
|
||||
Wave4.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Wave4);
|
||||
|
||||
if(!controller->SupportsSaveLEDState())
|
||||
{
|
||||
for(unsigned int mode_idx = 0; mode_idx < modes.size(); mode_idx++)
|
||||
{
|
||||
modes[mode_idx].flags &= ~MODE_FLAG_MANUAL_SAVE;
|
||||
}
|
||||
}
|
||||
|
||||
Init_Controller();
|
||||
SetupZones();
|
||||
}
|
||||
@@ -225,7 +262,7 @@ RGBController_RGBFusion2USB::~RGBController_RGBFusion2USB()
|
||||
\*---------------------------------------------------------*/
|
||||
void RGBController_RGBFusion2USB::Init_Controller()
|
||||
{
|
||||
|
||||
bool settings_changed = false;
|
||||
const gb_fusion2_device* src_layout = gb_fusion2_device_list[device_index];
|
||||
const std::string SectionGen2 = "Gigabyte-Gen2-ARGB";
|
||||
const std::string SectionCustomBase = "CustomLayout";
|
||||
@@ -240,37 +277,101 @@ void RGBController_RGBFusion2USB::Init_Controller()
|
||||
\*---------------------------------------------------------*/
|
||||
if(controller->SupportsGen2())
|
||||
{
|
||||
if(!device_settings.contains(SectionGen2))
|
||||
static const char* gen2_header_keys[4] =
|
||||
{
|
||||
device_settings[SectionGen2]["Enabled"] = false;
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
"D_LED1",
|
||||
"D_LED2",
|
||||
"D_LED3",
|
||||
"D_LED4"
|
||||
};
|
||||
|
||||
const unsigned int header_count = controller->ExportGen2Strips().size();
|
||||
|
||||
bool default_enabled = false;
|
||||
uint8_t enabled_headers = 0;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Preserve the old global setting when migrating |
|
||||
\*-----------------------------------------------------*/
|
||||
if(device_settings[SectionGen2].contains("Enabled"))
|
||||
{
|
||||
default_enabled = device_settings[SectionGen2]["Enabled"];
|
||||
|
||||
device_settings[SectionGen2].erase("Enabled");
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
supports_gen2 = device_settings[SectionGen2]["Enabled"];
|
||||
/*-----------------------------------------------------*\
|
||||
| Create and read the per-header settings |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int header = 0; header < header_count; ++header)
|
||||
{
|
||||
if(!device_settings[SectionGen2].contains(gen2_header_keys[header]))
|
||||
{
|
||||
device_settings[SectionGen2][gen2_header_keys[header]] = default_enabled;
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if(device_settings[SectionGen2][gen2_header_keys[header]])
|
||||
{
|
||||
enabled_headers |= 1U << header;
|
||||
}
|
||||
}
|
||||
|
||||
supports_gen2 = enabled_headers != 0;
|
||||
|
||||
if(supports_gen2)
|
||||
{
|
||||
controller->ScanGen2Strips();
|
||||
controller->ScanGen2Strips(enabled_headers);
|
||||
}
|
||||
}
|
||||
else if(device_settings.contains(SectionGen2))
|
||||
{
|
||||
device_settings.erase(SectionGen2);
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if(settings_changed)
|
||||
{
|
||||
settings_manager->SetSettings(detector_name, device_settings);
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create the custom layout from the generic layout |
|
||||
\*---------------------------------------------------------*/
|
||||
switch(product_id)
|
||||
if(device_num == 1)
|
||||
{
|
||||
case 0x8950:
|
||||
src_layout = gb_fusion2_device_list[device_index + 1];
|
||||
break;
|
||||
case 0x5711:
|
||||
src_layout = gb_fusion2_device_list[device_index + 2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch(product_id)
|
||||
{
|
||||
break;
|
||||
case 0x5711:
|
||||
src_layout = gb_fusion2_device_list[device_index + 4];
|
||||
break;
|
||||
default:
|
||||
src_layout = gb_fusion2_device_list[device_index + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(product_id)
|
||||
{
|
||||
case 0x8950:
|
||||
src_layout = gb_fusion2_device_list[device_index + 2];
|
||||
break;
|
||||
case 0x5711:
|
||||
src_layout = gb_fusion2_device_list[device_index + 3];
|
||||
break;
|
||||
case 0xa100:
|
||||
src_layout = gb_fusion2_device_list[device_index + 5];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!device_settings.contains(SectionCustom))
|
||||
if(!device_settings.contains(SectionCustom) && (product_id != 0xA100))
|
||||
{
|
||||
device_settings[SectionCustom]["Enabled"] = false;
|
||||
device_settings[SectionCustom]["Data"] = BuildCustomLayoutJson(src_layout, ReverseLedLookup);
|
||||
@@ -282,7 +383,7 @@ void RGBController_RGBFusion2USB::Init_Controller()
|
||||
|
||||
EncodedCalibration hw_cal = controller->GetCalibration(false);
|
||||
|
||||
if(device_num == 0)
|
||||
if(device_num == 0 || product_id != 0xa100)
|
||||
{
|
||||
if(!device_settings.contains(SectionCalibration))
|
||||
{
|
||||
@@ -382,7 +483,7 @@ void RGBController_RGBFusion2USB::Init_Controller()
|
||||
(*instance_layout.zones)[zi] = (*src_layout->zones)[zi];
|
||||
}
|
||||
|
||||
if(custom_layout)
|
||||
if(custom_layout && (product_id != 0xA100))
|
||||
{
|
||||
LoadCustomLayoutFromJson(device_settings[SectionCustom]["Data"], LedLookup, &instance_layout);
|
||||
}
|
||||
@@ -428,6 +529,7 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
first_run = true;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Clear any existing color/LED configuration |
|
||||
\*-----------------------------------------------------*/
|
||||
@@ -441,7 +543,7 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
|
||||
for(num_zones = 0; num_zones < GB_FUSION2_ZONES_MAX; num_zones++)
|
||||
{
|
||||
if(!gb_fusion2_device_list[device_index]->zones[0][num_zones])
|
||||
if(!(*instance_layout.zones)[num_zones])
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -452,13 +554,20 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
unsigned int d1 = 0, d2 = 0, d3 = 0, d4 = 0;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up zones (Fixed so as to not spam the controller) |
|
||||
| Retrieve the latest Gen2 scan results |
|
||||
\*-----------------------------------------------------*/
|
||||
std::vector<Gen2StripInfo> strips;
|
||||
|
||||
if(supports_gen2)
|
||||
{
|
||||
strips = controller->ExportGen2Strips();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up zones |
|
||||
\*-----------------------------------------------------*/
|
||||
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Get zone configuration from device data |
|
||||
\*-------------------------------------------------*/
|
||||
const gb_fusion2_zone* zone_at_idx = (*instance_layout.zones)[zone_idx];
|
||||
|
||||
if(!zone_at_idx)
|
||||
@@ -466,36 +575,241 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
continue;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Check if this is a fixed-size zone |
|
||||
\*-------------------------------------------------*/
|
||||
bool fixed_zone = (zone_at_idx->leds_min == zone_at_idx->leds_max);
|
||||
|
||||
const Gen2StripInfo* gen2_info = nullptr;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| (Re-)initialize the zone |
|
||||
| Locate the Gen2 result corresponding to this zone |
|
||||
\*-------------------------------------------------*/
|
||||
if(fixed_zone)
|
||||
if(supports_gen2 && !fixed_zone)
|
||||
{
|
||||
unsigned int slot = 0;
|
||||
|
||||
switch(zone_at_idx->idx)
|
||||
{
|
||||
case LED4:
|
||||
case HDR_D_LED2:
|
||||
slot = 1;
|
||||
break;
|
||||
case HDR_D_LED3:
|
||||
slot = 2;
|
||||
break;
|
||||
case HDR_D_LED4:
|
||||
slot = 3;
|
||||
break;
|
||||
default:
|
||||
slot = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(slot < strips.size())
|
||||
{
|
||||
if(strips[slot].totalLeds > 0)
|
||||
{
|
||||
gen2_info = &strips[slot];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Automatically detected Gen2 ARGB zone |
|
||||
\*-------------------------------------------------*/
|
||||
if(gen2_info != nullptr)
|
||||
{
|
||||
bool preserve_segments = false;
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| A saved segment configuration may only rename |
|
||||
| or subdivide each detected physical strip. |
|
||||
\*---------------------------------------------*/
|
||||
if(zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURED_SEGMENTS)
|
||||
{
|
||||
bool valid_segments = true;
|
||||
std::size_t segment_idx = 0;
|
||||
|
||||
for(std::size_t strip_idx = 0; strip_idx < gen2_info->LedsOfStrip.size(); strip_idx++)
|
||||
{
|
||||
unsigned int strip_leds = gen2_info->LedsOfStrip[strip_idx];
|
||||
|
||||
/*-------------------------------------*\
|
||||
| Require one group for this strip |
|
||||
\*-------------------------------------*/
|
||||
if(segment_idx >= zones[zone_idx].segments.size())
|
||||
{
|
||||
valid_segments = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(zones[zone_idx].segments[segment_idx].flags & SEGMENT_FLAG_GROUP_START))
|
||||
{
|
||||
valid_segments = false;
|
||||
break;
|
||||
}
|
||||
|
||||
segment_idx++;
|
||||
|
||||
/*-------------------------------------*\
|
||||
| Validate subdivisions of this strip |
|
||||
\*-------------------------------------*/
|
||||
unsigned int member_leds = 0;
|
||||
bool found_member = false;
|
||||
|
||||
while(segment_idx < zones[zone_idx].segments.size())
|
||||
{
|
||||
const segment& member = zones[zone_idx].segments[segment_idx];
|
||||
|
||||
if(member.flags & SEGMENT_FLAG_GROUP_START)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(member.flags & SEGMENT_FLAG_GROUP_MEMBER)
|
||||
|| member.type != ZONE_TYPE_LINEAR
|
||||
|| member.leds_count == 0)
|
||||
{
|
||||
valid_segments = false;
|
||||
break;
|
||||
}
|
||||
|
||||
member_leds += member.leds_count;
|
||||
|
||||
if(member_leds > strip_leds)
|
||||
{
|
||||
valid_segments = false;
|
||||
break;
|
||||
}
|
||||
|
||||
found_member = true;
|
||||
segment_idx++;
|
||||
}
|
||||
|
||||
if(!valid_segments)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(!found_member || member_leds != strip_leds)
|
||||
{
|
||||
valid_segments = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(segment_idx != zones[zone_idx].segments.size())
|
||||
{
|
||||
valid_segments = false;
|
||||
}
|
||||
|
||||
preserve_segments = valid_segments;
|
||||
}
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| Gen2 scan controls all zone-level geometry |
|
||||
\*---------------------------------------------*/
|
||||
zones[zone_idx].name = zone_at_idx->name;
|
||||
zones[zone_idx].type = ZONE_TYPE_SEGMENTED;
|
||||
zones[zone_idx].leds_count = gen2_info->totalLeds;
|
||||
zones[zone_idx].leds_min = zones[zone_idx].leds_count;
|
||||
zones[zone_idx].leds_max = zones[zone_idx].leds_count;
|
||||
zones[zone_idx].matrix_map.width = 0;
|
||||
zones[zone_idx].matrix_map.height = 0;
|
||||
zones[zone_idx].matrix_map.map.clear();
|
||||
zones[zone_idx].flags = ZONE_FLAG_MANUALLY_CONFIGURABLE_SEGMENTS;
|
||||
|
||||
if(preserve_segments)
|
||||
{
|
||||
zones[zone_idx].flags |= ZONE_FLAG_MANUALLY_CONFIGURED_SEGMENTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
zones[zone_idx].segments.clear();
|
||||
zones[zone_idx].segments.reserve(gen2_info->LedsOfStrip.size() * 2);
|
||||
|
||||
unsigned int start_idx = 0;
|
||||
|
||||
for(std::size_t strip_idx = 0; strip_idx < gen2_info->LedsOfStrip.size(); strip_idx++)
|
||||
{
|
||||
unsigned int strip_leds = gen2_info->LedsOfStrip[strip_idx];
|
||||
|
||||
/*-------------------------------------*\
|
||||
| Empty marker for a physical strip |
|
||||
\*-------------------------------------*/
|
||||
segment group;
|
||||
|
||||
group.name = "Strip " + std::to_string(strip_idx + 1);
|
||||
group.type = ZONE_TYPE_LINEAR;
|
||||
group.start_idx = 0;
|
||||
group.leds_count = 0;
|
||||
group.flags = SEGMENT_FLAG_GROUP_START;
|
||||
group.matrix_map.width = 0;
|
||||
group.matrix_map.height = 0;
|
||||
group.matrix_map.map.clear();
|
||||
|
||||
zones[zone_idx].segments.push_back(group);
|
||||
|
||||
/*-------------------------------------*\
|
||||
| Initial member covers the whole strip |
|
||||
\*-------------------------------------*/
|
||||
segment member;
|
||||
|
||||
member.name = "Strip " + std::to_string(strip_idx + 1);
|
||||
member.type = ZONE_TYPE_LINEAR;
|
||||
member.start_idx = start_idx;
|
||||
member.leds_count = strip_leds;
|
||||
member.flags = SEGMENT_FLAG_GROUP_MEMBER;
|
||||
member.matrix_map.width = 0;
|
||||
member.matrix_map.height = 0;
|
||||
member.matrix_map.map.clear();
|
||||
zones[zone_idx].segments.push_back(member);
|
||||
start_idx += strip_leds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Fixed motherboard zone |
|
||||
\*-------------------------------------------------*/
|
||||
else if(fixed_zone)
|
||||
{
|
||||
zones[zone_idx].name = zone_at_idx->name;
|
||||
zones[zone_idx].type = ZONE_TYPE_SINGLE;
|
||||
zones[zone_idx].leds_min = zone_at_idx->leds_min;
|
||||
zones[zone_idx].leds_max = zone_at_idx->leds_max;
|
||||
zones[zone_idx].leds_count = zones[zone_idx].leds_min;
|
||||
zones[zone_idx].leds_count = zone_at_idx->leds_min;
|
||||
zones[zone_idx].flags = 0;
|
||||
zones[zone_idx].matrix_map.width = 0;
|
||||
zones[zone_idx].matrix_map.height = 0;
|
||||
zones[zone_idx].matrix_map.map.clear();
|
||||
zones[zone_idx].segments.clear();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Manually configurable ARGB zone |
|
||||
\*-------------------------------------------------*/
|
||||
else
|
||||
{
|
||||
zones[zone_idx].leds_min = zone_at_idx->leds_min;
|
||||
zones[zone_idx].leds_max = zone_at_idx->leds_max;
|
||||
bool reset_manual_zone = first_run || !(zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURABLE_SIZE);
|
||||
|
||||
if(first_run)
|
||||
if(reset_manual_zone)
|
||||
{
|
||||
zones[zone_idx].flags = ZONE_FLAG_MANUALLY_CONFIGURABLE_SIZE
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_NAME
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_TYPE
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_MATRIX_MAP
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_SEGMENTS;
|
||||
zones[zone_idx].name = zone_at_idx->name;
|
||||
zones[zone_idx].type = ZONE_TYPE_LINEAR;
|
||||
zones[zone_idx].leds_count = zone_at_idx->leds_min;
|
||||
zones[zone_idx].matrix_map.width = 0;
|
||||
zones[zone_idx].matrix_map.height = 0;
|
||||
zones[zone_idx].matrix_map.map.clear();
|
||||
zones[zone_idx].segments.clear();
|
||||
}
|
||||
|
||||
zones[zone_idx].leds_min = zone_at_idx->leds_min;
|
||||
zones[zone_idx].leds_max = zone_at_idx->leds_max;
|
||||
|
||||
if(!(zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURED_NAME))
|
||||
{
|
||||
zones[zone_idx].name = zone_at_idx->name;
|
||||
@@ -515,8 +829,29 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
{
|
||||
zones[zone_idx].matrix_map.width = 0;
|
||||
zones[zone_idx].matrix_map.height = 0;
|
||||
zones[zone_idx].matrix_map.map.resize(0);
|
||||
zones[zone_idx].matrix_map.map.clear();
|
||||
}
|
||||
|
||||
if(!(zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURED_SEGMENTS))
|
||||
{
|
||||
zones[zone_idx].segments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Initialize per-zone modes |
|
||||
\*-------------------------------------------------*/
|
||||
if(zones[zone_idx].modes.empty())
|
||||
{
|
||||
for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++)
|
||||
{
|
||||
if(!(modes[mode_idx].flags & MODE_FLAG_REQUIRES_ENTIRE_DEVICE))
|
||||
{
|
||||
zones[zone_idx].modes.push_back(modes[mode_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
zones[zone_idx].active_mode = -1;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
@@ -525,8 +860,7 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
for(unsigned int led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
|
||||
new_led.name = zone_at_idx->name;
|
||||
new_led.name = zones[zone_idx].name;
|
||||
new_led.value = zone_at_idx->idx;
|
||||
|
||||
if(!fixed_zone)
|
||||
@@ -538,7 +872,7 @@ void RGBController_RGBFusion2USB::SetupZones()
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If not a fixed-size zone, set up LED sizes |
|
||||
| Restore the ARGB header LED counts |
|
||||
\*-------------------------------------------------*/
|
||||
if(!fixed_zone)
|
||||
{
|
||||
@@ -576,50 +910,67 @@ void RGBController_RGBFusion2USB::DeviceConfigureZone(int zone_idx)
|
||||
|
||||
void RGBController_RGBFusion2USB::DeviceUpdateLEDs()
|
||||
{
|
||||
int mode_value = (modes[active_mode].value);
|
||||
bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
|
||||
int mode_value = modes[active_mode].value;
|
||||
bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM;
|
||||
uint32_t* color = &null_color;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| If Wave 1-4 then use special sequence. |
|
||||
| Entire-device modes use the special wave sequence |
|
||||
\*---------------------------------------------------------*/
|
||||
if(mode_value == 6 || (mode_value >= 9 && mode_value <= 12))
|
||||
if(modes[active_mode].flags & MODE_FLAG_REQUIRES_ENTIRE_DEVICE)
|
||||
{
|
||||
controller->SetStripBuiltinEffectState(-1, true);
|
||||
controller->SetLEDEffect(-1, 1, 0, 0xFF, 0, color);
|
||||
controller->SetLEDEffect(-1, EFFECT_STATIC, 0, 0xFF, false, color);
|
||||
controller->ApplyEffect();
|
||||
controller->SetLEDEffect( 2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->SetLEDEffect(2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->ApplyEffect();
|
||||
return;
|
||||
}
|
||||
|
||||
for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++)
|
||||
{
|
||||
mode* selected_mode = &modes[active_mode];
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Use the zone-specific mode when one is selected |
|
||||
\*---------------------------------------------------------*/
|
||||
if(zones[zone_idx].active_mode >= 0)
|
||||
{
|
||||
selected_mode = &zones[zone_idx].modes[zones[zone_idx].active_mode];
|
||||
}
|
||||
|
||||
mode_value = selected_mode->value;
|
||||
random = selected_mode->color_mode == MODE_COLORS_RANDOM;
|
||||
color = &null_color;
|
||||
|
||||
if(zones[zone_idx].type == ZONE_TYPE_SINGLE)
|
||||
{
|
||||
for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++)
|
||||
{
|
||||
int led_mode_value = mode_value;
|
||||
uint32_t* led_color = color;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Motherboard LEDs always use effect mode, so use static for|
|
||||
| direct mode but get colors from zone |
|
||||
\*---------------------------------------------------------*/
|
||||
if(modes[active_mode].value == 0xFFFF)
|
||||
if(selected_mode->value == 0xFFFF)
|
||||
{
|
||||
color = &zones[zone_idx].colors[led_idx];
|
||||
mode_value = EFFECT_STATIC;
|
||||
led_color = &zones[zone_idx].colors[led_idx];
|
||||
led_mode_value = EFFECT_STATIC;
|
||||
}
|
||||
/*---------------------------------------------------------*\
|
||||
| If the mode uses mode-specific color, get color from mode |
|
||||
\*---------------------------------------------------------*/
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
else if(selected_mode->color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
color = &modes[active_mode].colors[0];
|
||||
led_color = &selected_mode->colors[0];
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply the mode and color to the zone |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SetLEDEffect(zones[zone_idx].leds[led_idx].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->SetLEDEffect(zones[zone_idx].leds[led_idx].value, led_mode_value, selected_mode->speed, selected_mode->brightness, random, led_color);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------*\
|
||||
@@ -634,7 +985,7 @@ void RGBController_RGBFusion2USB::DeviceUpdateLEDs()
|
||||
/*---------------------------------------------------------*\
|
||||
| Direct mode addresses a different register |
|
||||
\*---------------------------------------------------------*/
|
||||
if(modes[active_mode].value == 0xFFFF)
|
||||
if(selected_mode->value == 0xFFFF)
|
||||
{
|
||||
controller->SetStripBuiltinEffectState(hdr, false);
|
||||
controller->SetStripColors(hdr, zones[zone_idx].colors, zones[zone_idx].leds_count);
|
||||
@@ -648,45 +999,52 @@ void RGBController_RGBFusion2USB::DeviceUpdateLEDs()
|
||||
/*---------------------------------------------------------*\
|
||||
| If mode has mode specific color, load color from mode |
|
||||
\*---------------------------------------------------------*/
|
||||
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
if(selected_mode->color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
color = &modes[active_mode].colors[0];
|
||||
color = &selected_mode->colors[0];
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply hardware effects to LED strips |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SetStripBuiltinEffectState(hdr, true);
|
||||
controller->SetLEDEffect(hdr, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->SetLEDEffect(hdr, mode_value, selected_mode->speed, selected_mode->brightness, random, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
controller->ApplyEffect();
|
||||
}
|
||||
|
||||
void RGBController_RGBFusion2USB::DeviceUpdateZoneLEDs(int zone)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Get mode parameters |
|
||||
\*---------------------------------------------------------*/
|
||||
int mode_value = (modes[active_mode].value);
|
||||
bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
|
||||
int mode_value = modes[active_mode].value;
|
||||
bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM;
|
||||
uint32_t* color = &null_color;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| If Wave 1-4 then use special sequence. |
|
||||
| Entire-device modes cannot be updated one zone at a time |
|
||||
\*---------------------------------------------------------*/
|
||||
if(mode_value == 6 || (mode_value >= 9 && mode_value <= 12))
|
||||
if(modes[active_mode].flags & MODE_FLAG_REQUIRES_ENTIRE_DEVICE)
|
||||
{
|
||||
controller->SetStripBuiltinEffectState(-1, true);
|
||||
controller->SetLEDEffect(-1, 1, 0, 0xFF, 0, color);
|
||||
controller->ApplyEffect();
|
||||
controller->SetLEDEffect( 2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->ApplyEffect();
|
||||
DeviceUpdateLEDs();
|
||||
return;
|
||||
}
|
||||
|
||||
mode* selected_mode = &modes[active_mode];
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Use the zone-specific mode when one is selected |
|
||||
\*---------------------------------------------------------*/
|
||||
if(zones[zone].active_mode >= 0)
|
||||
{
|
||||
selected_mode = &zones[zone].modes[zones[zone].active_mode];
|
||||
}
|
||||
|
||||
mode_value = selected_mode->value;
|
||||
random = selected_mode->color_mode == MODE_COLORS_RANDOM;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Set motherboard LEDs |
|
||||
\*---------------------------------------------------------*/
|
||||
@@ -694,28 +1052,31 @@ void RGBController_RGBFusion2USB::DeviceUpdateZoneLEDs(int zone)
|
||||
{
|
||||
for(std::size_t led_idx = 0; led_idx < zones[zone].leds_count; led_idx++)
|
||||
{
|
||||
int led_mode_value = mode_value;
|
||||
uint32_t* led_color = color;
|
||||
|
||||
/*------------------------------------------------------------*\
|
||||
| Motherboard LEDs always use effect mode, so use static for |
|
||||
| direct mode but get colors from zone |
|
||||
\*------------------------------------------------------------*/
|
||||
if(mode_value == 0xFFFF)
|
||||
if(selected_mode->value == 0xFFFF)
|
||||
{
|
||||
color = &zones[zone].colors[led_idx];
|
||||
mode_value = EFFECT_STATIC;
|
||||
led_color = &zones[zone].colors[led_idx];
|
||||
led_mode_value = EFFECT_STATIC;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| If the mode uses mode-specific color, get color from mode |
|
||||
\*---------------------------------------------------------*/
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
else if(selected_mode->color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
color = &modes[active_mode].colors[0];
|
||||
led_color = &selected_mode->colors[0];
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply the mode and color to the zone |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SetLEDEffect(zones[zone].leds[led_idx].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->SetLEDEffect(zones[zone].leds[led_idx].value, led_mode_value, selected_mode->speed, selected_mode->brightness, random, led_color);
|
||||
controller->ApplyEffect();
|
||||
}
|
||||
}
|
||||
@@ -732,7 +1093,7 @@ void RGBController_RGBFusion2USB::DeviceUpdateZoneLEDs(int zone)
|
||||
/*---------------------------------------------------------*\
|
||||
| Direct mode addresses a different register |
|
||||
\*---------------------------------------------------------*/
|
||||
if(mode_value == 0xFFFF)
|
||||
if(selected_mode->value == 0xFFFF)
|
||||
{
|
||||
controller->SetStripBuiltinEffectState(hdr, false);
|
||||
controller->SetStripColors(hdr, zones[zone].colors, zones[zone].leds_count);
|
||||
@@ -746,16 +1107,16 @@ void RGBController_RGBFusion2USB::DeviceUpdateZoneLEDs(int zone)
|
||||
/*---------------------------------------------------------*\
|
||||
| If mode has mode specific color, load color from mode |
|
||||
\*---------------------------------------------------------*/
|
||||
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
if(selected_mode->color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
color = &modes[active_mode].colors[0];
|
||||
color = &selected_mode->colors[0];
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply built-in effects to LED strips |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SetStripBuiltinEffectState(hdr, true);
|
||||
controller->SetLEDEffect(hdr, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->SetLEDEffect(hdr, mode_value, selected_mode->speed, selected_mode->brightness, random, color);
|
||||
controller->ApplyEffect();
|
||||
}
|
||||
}
|
||||
@@ -764,26 +1125,38 @@ void RGBController_RGBFusion2USB::DeviceUpdateZoneLEDs(int zone)
|
||||
|
||||
void RGBController_RGBFusion2USB::DeviceUpdateSingleLED(int led)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Get mode parameters |
|
||||
\*---------------------------------------------------------*/
|
||||
int mode_value = (modes[active_mode].value);
|
||||
bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
|
||||
int mode_value = modes[active_mode].value;
|
||||
bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM;
|
||||
uint32_t* color = &null_color;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| If Wave 1-4 then use special sequence. |
|
||||
| Entire-device modes cannot update an individual LED |
|
||||
\*---------------------------------------------------------*/
|
||||
if(mode_value == 6 || (mode_value >= 9 && mode_value <= 12))
|
||||
if(modes[active_mode].flags & MODE_FLAG_REQUIRES_ENTIRE_DEVICE)
|
||||
{
|
||||
controller->SetStripBuiltinEffectState(-1, true);
|
||||
controller->SetLEDEffect(-1, 1, 0, 0xFF, 0, color);
|
||||
controller->ApplyEffect();
|
||||
controller->SetLEDEffect( 2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->ApplyEffect();
|
||||
DeviceUpdateLEDs();
|
||||
return;
|
||||
}
|
||||
unsigned int zone_idx = GetLED_Zone(led);
|
||||
|
||||
int zone_idx = GetLED_Zone(led);
|
||||
|
||||
if(zone_idx < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mode* selected_mode = &modes[active_mode];
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Use the zone-specific mode when one is selected |
|
||||
\*---------------------------------------------------------*/
|
||||
if(zones[zone_idx].active_mode >= 0)
|
||||
{
|
||||
selected_mode = &zones[zone_idx].modes[zones[zone_idx].active_mode];
|
||||
}
|
||||
|
||||
mode_value = selected_mode->value;
|
||||
random = selected_mode->color_mode == MODE_COLORS_RANDOM;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Set motherboard LEDs |
|
||||
@@ -794,7 +1167,7 @@ void RGBController_RGBFusion2USB::DeviceUpdateSingleLED(int led)
|
||||
| Motherboard LEDs always use effect mode, so use static for|
|
||||
| direct mode but get colors from zone |
|
||||
\*---------------------------------------------------------*/
|
||||
if(mode_value == 0xFFFF)
|
||||
if(selected_mode->value == 0xFFFF)
|
||||
{
|
||||
color = &colors[led];
|
||||
mode_value = EFFECT_STATIC;
|
||||
@@ -803,12 +1176,12 @@ void RGBController_RGBFusion2USB::DeviceUpdateSingleLED(int led)
|
||||
/*---------------------------------------------------------*\
|
||||
| If the mode uses mode-specific color, get color from mode |
|
||||
\*---------------------------------------------------------*/
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
else if(selected_mode->color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
color = &modes[active_mode].colors[0];
|
||||
color = &selected_mode->colors[0];
|
||||
}
|
||||
|
||||
controller->SetLEDEffect(leds[led].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color);
|
||||
controller->SetLEDEffect(leds[led].value, mode_value, selected_mode->speed, selected_mode->brightness, random, color);
|
||||
controller->ApplyEffect();
|
||||
}
|
||||
|
||||
@@ -826,6 +1199,11 @@ void RGBController_RGBFusion2USB::DeviceUpdateMode()
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RGBFusion2USB::DeviceUpdateZoneMode(int zone)
|
||||
{
|
||||
DeviceUpdateZoneLEDs(zone);
|
||||
}
|
||||
|
||||
int RGBController_RGBFusion2USB::GetLED_Zone(int led_idx)
|
||||
{
|
||||
for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++)
|
||||
@@ -845,6 +1223,11 @@ int RGBController_RGBFusion2USB::GetLED_Zone(int led_idx)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void RGBController_RGBFusion2USB::DeviceSaveMode()
|
||||
{
|
||||
controller->SaveLEDState(true);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Convert calibration data to JSON |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
void DeviceUpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
void DeviceUpdateZoneMode(int zone);
|
||||
void DeviceSaveMode() override;
|
||||
|
||||
private:
|
||||
std::string detector_name;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HoltekA070ControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Holtek A070 Mouse |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HoltekA070Controller.h"
|
||||
#include "RGBController_HoltekA070.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Holtek Semiconductor Inc. vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_VID 0x04D9
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Mouse product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_A070_PID 0xA070
|
||||
|
||||
DetectedControllers DetectHoltekA070Controllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HoltekA070Controller* controller = new HoltekA070Controller(dev, info->path, name);
|
||||
RGBController_HoltekA070* rgb_controller = new RGBController_HoltekA070(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Holtek USB Gaming Mouse", DetectHoltekA070Controllers, HOLTEK_VID, HOLTEK_A070_PID, 1, 0xFF00, 2);
|
||||
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HoltekA1FAControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Holtek A1FA Mousemat |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HoltekA1FAController.h"
|
||||
#include "RGBController_HoltekA1FA.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Holtek Semiconductor Inc. vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_VID 0x04D9
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Mousemats product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_A1FA_PID 0xA1FA
|
||||
|
||||
DetectedControllers DetectHoltekA1FAControllers(hid_device_info *info, const std::string &name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HoltekA1FAController* controller = new HoltekA1FAController(dev, info->path, name);
|
||||
RGBController_HoltekA1FA* rgb_controller = new RGBController_HoltekA1FA(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Holtek Mousemat", DetectHoltekA1FAControllers, HOLTEK_VID, HOLTEK_A1FA_PID, 2, 0xFF00, 0xFF00);
|
||||
@@ -1,67 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HoltekControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Holtek devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HoltekA070Controller.h"
|
||||
#include "RGBController_HoltekA070.h"
|
||||
#include "HoltekA1FAController.h"
|
||||
#include "RGBController_HoltekA1FA.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Holtek Semiconductor Inc. vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_VID 0x04D9
|
||||
/*---------------------------------------------------------*\
|
||||
| Mouse product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_A070_PID 0xA070
|
||||
/*---------------------------------------------------------*\
|
||||
| Mousemats product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HOLTEK_A1FA_PID 0xA1FA
|
||||
|
||||
DetectedControllers DetectHoltekControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HoltekA070Controller* controller = new HoltekA070Controller(dev, info->path, name);
|
||||
RGBController_HoltekA070* rgb_controller = new RGBController_HoltekA070(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHoltekMousemats(hid_device_info *info, const std::string &name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HoltekA1FAController* controller = new HoltekA1FAController(dev, info->path, name);
|
||||
RGBController_HoltekA1FA* rgb_controller = new RGBController_HoltekA1FA(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Holtek USB Gaming Mouse", DetectHoltekControllers, HOLTEK_VID, HOLTEK_A070_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Holtek Mousemat", DetectHoltekMousemats, HOLTEK_VID, HOLTEK_A1FA_PID, 2, 0xFF00, 0xFF00);
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXAlloyElite2ControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Alloy Elite 2 keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyElite2Controller.h"
|
||||
#include "RGBController_HyperXAlloyElite2.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
#define HYPERX_ALLOY_ELITE_2_PID 0x1711
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
#define HYPERX_ALLOY_ELITE_2_HP_PID 0x058F
|
||||
|
||||
DetectedControllers DetectHyperXAlloyElite2(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyElite2Controller* controller = new HyperXAlloyElite2Controller(dev, info->path, name);
|
||||
RGBController_HyperXAlloyElite2* rgb_controller = new RGBController_HyperXAlloyElite2(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite 2", DetectHyperXAlloyElite2, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_PID, 3, 0xFF90);
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite 2 (HP)", DetectHyperXAlloyElite2, HP_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_HP_PID, 3, 0xFF90);
|
||||
#else
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Elite 2", DetectHyperXAlloyElite2, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Elite 2 (HP)", DetectHyperXAlloyElite2, HP_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_HP_PID, 0);
|
||||
#endif
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXAlloyEliteControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Alloy Elite keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyEliteController.h"
|
||||
#include "RGBController_HyperXAlloyElite.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
#define HYPERX_ALLOY_ELITE_PID 0x16BE
|
||||
|
||||
DetectedControllers DetectHyperXAlloyElite(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyEliteController* controller = new HyperXAlloyEliteController(dev, info->path, name);
|
||||
RGBController_HyperXAlloyElite* rgb_controller = new RGBController_HyperXAlloyElite(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite RGB", DetectHyperXAlloyElite, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_PID, 2, 0xFF01);
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXAlloyFPSControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Alloy FPS keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyFPSController.h"
|
||||
#include "RGBController_HyperXAlloyFPS.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
#define HYPERX_ALLOY_FPS_RGB_PID 0x16DC
|
||||
|
||||
DetectedControllers DetectHyperXAlloyFPS(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyFPSController* controller = new HyperXAlloyFPSController(dev, info->path, name);
|
||||
RGBController_HyperXAlloyFPS* rgb_controller = new RGBController_HyperXAlloyFPS(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy FPS RGB", DetectHyperXAlloyFPS, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_FPS_RGB_PID, 2, 0xFF01);
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXAlloyOrigins60and65ControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Alloy Origins 60 and 65 keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyOrigins60and65Controller.h"
|
||||
#include "RGBController_HyperXAlloyOrigins60and65.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
#define HYPERX_ALLOY_ORIGINS_60_PID 0x1734
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
#define HYPERX_ALLOY_ORIGINS_60_HP_PID 0x0C8E
|
||||
#define HYPERX_ALLOY_ORIGINS_65_HP_PID 0x038F
|
||||
|
||||
AlloyOrigins60and65MappingLayoutType GetAlloyOrigins60and65MappingLayoutType(int pid)
|
||||
{
|
||||
switch(pid)
|
||||
{
|
||||
case HYPERX_ALLOY_ORIGINS_60_PID:
|
||||
case HYPERX_ALLOY_ORIGINS_60_HP_PID:
|
||||
return ALLOY_ORIGINS_60_LAYOUT;
|
||||
|
||||
case HYPERX_ALLOY_ORIGINS_65_HP_PID:
|
||||
return ALLOY_ORIGINS_65_LAYOUT;
|
||||
|
||||
default:
|
||||
return ALLOY_ORIGINS_60_LAYOUT;
|
||||
}
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyOrigins60and65(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyOrigins60and65Controller* controller = new HyperXAlloyOrigins60and65Controller(dev, info->path, name);
|
||||
AlloyOrigins60and65MappingLayoutType layout = GetAlloyOrigins60and65MappingLayoutType(info->product_id);
|
||||
RGBController_HyperXAlloyOrigins60and65* rgb_controller = new RGBController_HyperXAlloyOrigins60and65(controller, layout);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60", DetectHyperXAlloyOrigins60and65, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 3);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_HP_PID, 3);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 65 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_65_HP_PID, 3);
|
||||
#else
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60", DetectHyperXAlloyOrigins60and65, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_HP_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 65 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_65_HP_PID, 0);
|
||||
#endif
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXAlloyOriginsControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Alloy Origins keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyOriginsController.h"
|
||||
#include "RGBController_HyperXAlloyOrigins.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
#define HYPERX_ALLOY_ORIGINS_PID 0x16E5
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
#define HYPERX_ALLOY_ORIGINS_HP_PID 0x0591
|
||||
|
||||
DetectedControllers DetectHyperXAlloyOrigins(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyOriginsController* controller = new HyperXAlloyOriginsController(dev, info->path, name);
|
||||
RGBController_HyperXAlloyOrigins* rgb_controller = new RGBController_HyperXAlloyOrigins(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 3);
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Origins (HP)", DetectHyperXAlloyOrigins, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_HP_PID, 3, 0xFF90);
|
||||
#else
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins (HP)", DetectHyperXAlloyOrigins, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_HP_PID, 0);
|
||||
#endif
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXAlloyOriginsCoreControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Alloy Origins Core keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyOriginsCoreController.h"
|
||||
#include "RGBController_HyperXAlloyOriginsCore.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
#define HYPERX_ALLOY_ORIGINS_CORE_PID 0x16E6
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
#define HYPERX_ALLOY_ORIGINS_CORE_HP_PID 0x098F
|
||||
|
||||
DetectedControllers DetectHyperXAlloyOriginsCore(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyOriginsCoreController* controller = new HyperXAlloyOriginsCoreController(dev, info, name);
|
||||
RGBController_HyperXAlloyOriginsCore* rgb_controller = new RGBController_HyperXAlloyOriginsCore(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOriginsCore, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 2);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core (HP)", DetectHyperXAlloyOriginsCore, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_HP_PID, 2);
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXEve1800ControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Eve 1800 keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXEve1800Controller.h"
|
||||
#include "RGBController_HyperXEve1800.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
#define HYPERX_EVE_1800_HP_PID 0x08C2
|
||||
|
||||
DetectedControllers DetectHyperXEve1800(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXEve1800Controller* controller = new HyperXEve1800Controller(dev, info->path, name);
|
||||
RGBController_HyperXEve1800* rgb_controller = new RGBController_HyperXEve1800(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return detected_controllers;
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_I("HyperX Eve 1800 (HP)", DetectHyperXEve1800, HP_KEYBOARD_VID, HYPERX_EVE_1800_HP_PID, 2);
|
||||
@@ -1,242 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXKeyboardControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXAlloyEliteController.h"
|
||||
#include "HyperXAlloyElite2Controller.h"
|
||||
#include "HyperXAlloyFPSController.h"
|
||||
#include "HyperXAlloyOriginsController.h"
|
||||
#include "HyperXAlloyOriginsCoreController.h"
|
||||
#include "HyperXAlloyOrigins60and65Controller.h"
|
||||
#include "HyperXEve1800Controller.h"
|
||||
#include "HyperXOrigins2_65Controller.h"
|
||||
#include "RGBController_HyperXAlloyElite.h"
|
||||
#include "RGBController_HyperXAlloyElite2.h"
|
||||
#include "RGBController_HyperXAlloyFPS.h"
|
||||
#include "RGBController_HyperXAlloyOrigins.h"
|
||||
#include "RGBController_HyperXAlloyOriginsCore.h"
|
||||
#include "RGBController_HyperXAlloyOrigins60and65.h"
|
||||
#include "RGBController_HyperXEve1800.h"
|
||||
#include "RGBController_HyperXOrigins2_65.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HYPERX_KEYBOARD_VID 0x0951
|
||||
|
||||
#define HYPERX_ALLOY_ELITE_PID 0x16BE
|
||||
#define HYPERX_ALLOY_ELITE_2_PID 0x1711
|
||||
#define HYPERX_ALLOY_FPS_RGB_PID 0x16DC
|
||||
#define HYPERX_ALLOY_ORIGINS_PID 0x16E5
|
||||
#define HYPERX_ALLOY_ORIGINS_CORE_PID 0x16E6
|
||||
#define HYPERX_ALLOY_ORIGINS_60_PID 0x1734
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
|
||||
#define HYPERX_ALLOY_ELITE_2_HP_PID 0x058F
|
||||
#define HYPERX_ALLOY_ORIGINS_60_HP_PID 0x0C8E
|
||||
#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)
|
||||
{
|
||||
switch(pid)
|
||||
{
|
||||
case HYPERX_ALLOY_ORIGINS_60_PID:
|
||||
case HYPERX_ALLOY_ORIGINS_60_HP_PID:
|
||||
return ALLOY_ORIGINS_60_LAYOUT;
|
||||
|
||||
case HYPERX_ALLOY_ORIGINS_65_HP_PID:
|
||||
return ALLOY_ORIGINS_65_LAYOUT;
|
||||
|
||||
default:
|
||||
return ALLOY_ORIGINS_60_LAYOUT;
|
||||
}
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyElite(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyEliteController* controller = new HyperXAlloyEliteController(dev, info->path, name);
|
||||
RGBController_HyperXAlloyElite* rgb_controller = new RGBController_HyperXAlloyElite(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyElite2(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyElite2Controller* controller = new HyperXAlloyElite2Controller(dev, info->path, name);
|
||||
RGBController_HyperXAlloyElite2* rgb_controller = new RGBController_HyperXAlloyElite2(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyFPS(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyFPSController* controller = new HyperXAlloyFPSController(dev, info->path, name);
|
||||
RGBController_HyperXAlloyFPS* rgb_controller = new RGBController_HyperXAlloyFPS(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyOrigins(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyOriginsController* controller = new HyperXAlloyOriginsController(dev, info->path, name);
|
||||
RGBController_HyperXAlloyOrigins* rgb_controller = new RGBController_HyperXAlloyOrigins(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyOriginsCore(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyOriginsCoreController* controller = new HyperXAlloyOriginsCoreController(dev, info, name);
|
||||
RGBController_HyperXAlloyOriginsCore* rgb_controller = new RGBController_HyperXAlloyOriginsCore(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXAlloyOrigins60and65(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXAlloyOrigins60and65Controller* controller = new HyperXAlloyOrigins60and65Controller(dev, info->path, name);
|
||||
AlloyOrigins60and65MappingLayoutType layout = GetAlloyOrigins60and65MappingLayoutType(info->product_id);
|
||||
RGBController_HyperXAlloyOrigins60and65* rgb_controller = new RGBController_HyperXAlloyOrigins60and65(controller, layout);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXOrigins2_65(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXOrigins2_65Controller* controller = new HyperXOrigins2_65Controller(dev, info->path, name);
|
||||
RGBController_HyperXOrigins2_65* rgb_controller = new RGBController_HyperXOrigins2_65(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectHyperXEve1800(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXEve1800Controller* controller = new HyperXEve1800Controller(dev, info->path, name);
|
||||
RGBController_HyperXEve1800* rgb_controller = new RGBController_HyperXEve1800(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return detected_controllers;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite 2", DetectHyperXAlloyElite2, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_PID, 3, 0xFF90);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60", DetectHyperXAlloyOrigins60and65, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 3);
|
||||
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite 2 (HP)", DetectHyperXAlloyElite2, HP_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_HP_PID, 3, 0xFF90);
|
||||
REGISTER_HID_DETECTOR_IP("HyperX Alloy Origins (HP)", DetectHyperXAlloyOrigins, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_HP_PID, 3, 0xFF90);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_HP_PID, 3);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 65 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_65_HP_PID, 3);
|
||||
#else
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Elite 2", DetectHyperXAlloyElite2, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60", DetectHyperXAlloyOrigins60and65, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 0);
|
||||
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Elite 2 (HP)", DetectHyperXAlloyElite2, HP_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_HP_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins (HP)", DetectHyperXAlloyOrigins, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_HP_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_HP_PID, 0);
|
||||
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 65 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_65_HP_PID, 0);
|
||||
#endif
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperXOrigins2_65ControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for HyperX Origins 2 65 keyboards |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "HyperXOrigins2_65Controller.h"
|
||||
#include "RGBController_HyperXOrigins2_65.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| HyperX keyboard vendor and product IDs (HP) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define HP_KEYBOARD_VID 0x03F0
|
||||
#define HYPERX_ORIGINS_2_65_HP_PID 0x0CC2
|
||||
|
||||
DetectedControllers DetectHyperXOrigins2_65(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
HyperXOrigins2_65Controller* controller = new HyperXOrigins2_65Controller(dev, info->path, name);
|
||||
RGBController_HyperXOrigins2_65* rgb_controller = new RGBController_HyperXOrigins2_65(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_I("HyperX Origins 2 65 (HP)", DetectHyperXOrigins2_65, HP_KEYBOARD_VID, HYPERX_ORIGINS_2_65_HP_PID, 3);
|
||||
+1
-1
@@ -768,7 +768,7 @@ void RGBController_LogitechHIDPP20::SetupZones()
|
||||
perkey_zone.leds_min = klm.GetKeyCount();
|
||||
perkey_zone.leds_max = klm.GetKeyCount();
|
||||
perkey_zone.leds_count = klm.GetKeyCount();
|
||||
perkey_zone.matrix_map = klm.GetKeyMap();
|
||||
perkey_zone.matrix_map = klm.GetKeyMap(KEYBOARD_MAP_FILL_TYPE_COUNT);
|
||||
zones.push_back(perkey_zone);
|
||||
|
||||
for(unsigned int i = 0; i < klm.GetKeyCount(); i++)
|
||||
|
||||
@@ -41,7 +41,7 @@ REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Gaming X Slim",
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 SUPER Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 SUPER Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 SUPER Gaming X Slim MLG", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_MLG_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 SUPER Gaming X Slim MLG", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_MLG_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_TRIO_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Gaming X Trio White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_TRIO_WHITE_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68);
|
||||
@@ -50,6 +50,7 @@ REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming X Trio White",
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_SLIM_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_X_SLIM_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming White X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming White X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_X_SLIM_WHITE_SUB_DEV_2, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_GAMING_X_TRIO_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Gaming X Trio White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_GAMING_X_TRIO_WHITE_SUB_DEV, 0x68);
|
||||
@@ -68,7 +69,7 @@ REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5070 Ti VANGUARD SOC",
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 Gaming Trio OC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_GAMING_TRIO_OC_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 VANGUARD OC SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_VANGUARD_SOC_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 SUPRIM SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_SUPRIM_SOC_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 SUPRIM LIQUID SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_SUPRIM_LIQUID_SOC_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 SUPRIM LIQUID SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_SUPRIM_LIQUID_SOC_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5090 Gaming Trio OC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, MSI_SUB_VEN, MSI_RTX5090_GAMING_TRIO_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5090 VANGUARD SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, MSI_SUB_VEN, MSI_RTX5090_VANGUARD_SOC_SUB_DEV, 0x68);
|
||||
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5090 SUPRIM SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, MSI_SUB_VEN, MSI_RTX5090_SUPRIM_SOC_SUB_DEV, 0x68);
|
||||
|
||||
@@ -1,18 +1,40 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| MSIMonitorController.cpp |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| Driver for MSI monitor (gaming controller) |
|
||||
| |
|
||||
| Andy Herbert 2026 June 4 |
|
||||
| Ken Sanislo 2026 July 20 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <chrono>
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include "MSIMonitorController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Feature reports are control transfers and this panel |
|
||||
| holds one outstanding for tens of milliseconds. Back |
|
||||
| to back writes pin the shared control pipe at full |
|
||||
| duty and starve other non periodic traffic: a device |
|
||||
| with no interrupt OUT endpoint writes by SET_REPORT |
|
||||
| and stops answering, while its isochronous endpoints |
|
||||
| keep running. |
|
||||
| |
|
||||
| Idle a fixed interval after each write to leave the |
|
||||
| control pipe free. |
|
||||
\*---------------------------------------------------------*/
|
||||
void MSIMonitorController::SendFeatureReport(uint8_t *data, size_t length)
|
||||
{
|
||||
hid_send_feature_report(dev, data, length);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(MSI_MONITOR_PIPE_IDLE_MS));
|
||||
}
|
||||
|
||||
MSIMonitorController::MSIMonitorController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
@@ -117,5 +139,125 @@ void MSIMonitorController::Set(uint8_t mode_value, const std::vector<RGBColor> c
|
||||
| Send the data (1 packet) |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
hid_send_feature_report(dev, data, MSI_MONITOR_PACKET_SIZE);
|
||||
SendFeatureReport(data, MSI_MONITOR_PACKET_SIZE);
|
||||
}
|
||||
|
||||
uint8_t MSIMonitorController::GetLayoutVersion()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Ask the MCU which buffer layout it speaks. Request |
|
||||
| is [0x01][opcode] zero padded, reply is [0x01][0x5A] |
|
||||
| then data with the version at byte 3. |
|
||||
\*-----------------------------------------------------*/
|
||||
uint8_t request[MSI_MONITOR_QUERY_PACKET_SIZE];
|
||||
uint8_t reply[MSI_MONITOR_QUERY_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Unimplemented opcodes never answer, so a reply left |
|
||||
| queued by an earlier exchange would be read here and |
|
||||
| parsed as this query's answer. Drain first. |
|
||||
\*-----------------------------------------------------*/
|
||||
while(hid_read_timeout(dev, reply, MSI_MONITOR_QUERY_PACKET_SIZE, 0) > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(request, 0x00, MSI_MONITOR_QUERY_PACKET_SIZE);
|
||||
|
||||
request[0] = MSI_MONITOR_QUERY_REPORT_ID;
|
||||
request[1] = MSI_MONITOR_OPCODE_GET_VERSION;
|
||||
|
||||
if(hid_write(dev, request, MSI_MONITOR_QUERY_PACKET_SIZE) < 0)
|
||||
{
|
||||
return(MSI_MONITOR_VERSION_UNKNOWN);
|
||||
}
|
||||
|
||||
memset(reply, 0x00, MSI_MONITOR_QUERY_PACKET_SIZE);
|
||||
|
||||
if(hid_read_timeout(dev, reply, MSI_MONITOR_QUERY_PACKET_SIZE, 500) <= 0)
|
||||
{
|
||||
return(MSI_MONITOR_VERSION_UNKNOWN);
|
||||
}
|
||||
|
||||
if(reply[1] != MSI_MONITOR_QUERY_ACK)
|
||||
{
|
||||
return(MSI_MONITOR_VERSION_UNKNOWN);
|
||||
}
|
||||
|
||||
return(reply[3]);
|
||||
}
|
||||
|
||||
void MSIMonitorController::SetMode72(uint8_t mode_value, uint8_t speed, uint8_t brightness, RGBColor color1, RGBColor color2, bool user_palette, bool save, const std::vector<RGBColor>& led_colors, bool fill_both_arrays)
|
||||
{
|
||||
uint8_t data[MSI_MONITOR_72_PACKET_SIZE];
|
||||
memset(data, 0x00, MSI_MONITOR_72_PACKET_SIZE);
|
||||
|
||||
data[0] = 0x72;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Identical 11 byte control blocks at index 1 and 12 |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int base = 1; base <= 12; base += 11)
|
||||
{
|
||||
data[base + 0] = mode_value;
|
||||
data[base + 1] = RGBGetRValue(color1);
|
||||
data[base + 2] = RGBGetGValue(color1);
|
||||
data[base + 3] = RGBGetBValue(color1);
|
||||
data[base + 4] = speed;
|
||||
data[base + 5] = brightness;
|
||||
data[base + 6] = RGBGetRValue(color2);
|
||||
data[base + 7] = RGBGetGValue(color2);
|
||||
data[base + 8] = RGBGetBValue(color2);
|
||||
data[base + 9] = user_palette ? 0x80 : 0x00;
|
||||
data[base + 10] = 0x00;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| The engine paints from the second inline colour array |
|
||||
| at index 95, not from Colour1 and not from the first |
|
||||
| array at index 23: on a 322URX a buffer carrying only |
|
||||
| Colour1 renders black, and walking one lit slot |
|
||||
| through the buffer only lights LEDs for the second |
|
||||
| array. That pairs with the control block at index 12 |
|
||||
| being the operative one. Built in palette modes |
|
||||
| leave the array clear so the firmware effect is not |
|
||||
| painted over. |
|
||||
| |
|
||||
| fill_both_arrays also writes the first array at index |
|
||||
| 23, for the dual block versions (11/13/15) whose two |
|
||||
| control blocks each drive their own run. On a single |
|
||||
| block layout the first array is inert, so filling it |
|
||||
| is harmless. Those versions also route colour index |
|
||||
| above 15 to a separate DragonShield emblem region not |
|
||||
| handled here - one reason they stay disabled. |
|
||||
\*-----------------------------------------------------*/
|
||||
if(user_palette)
|
||||
{
|
||||
for(unsigned int slot = 0; slot < MSI_MONITOR_72_ARRAY_SLOTS && slot < led_colors.size(); slot++)
|
||||
{
|
||||
unsigned int offset_b = MSI_MONITOR_72_ARRAY_B_INDEX + (slot * 3);
|
||||
|
||||
data[offset_b + 0] = RGBGetRValue(led_colors[slot]);
|
||||
data[offset_b + 1] = RGBGetGValue(led_colors[slot]);
|
||||
data[offset_b + 2] = RGBGetBValue(led_colors[slot]);
|
||||
|
||||
if(fill_both_arrays)
|
||||
{
|
||||
unsigned int offset_a = MSI_MONITOR_72_ARRAY_A_INDEX + (slot * 3);
|
||||
|
||||
data[offset_a + 0] = RGBGetRValue(led_colors[slot]);
|
||||
data[offset_a + 1] = RGBGetGValue(led_colors[slot]);
|
||||
data[offset_a + 2] = RGBGetBValue(led_colors[slot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Final byte is store to flash: 0x01 persists across |
|
||||
| power cycles, 0x00 applies without a flash write. |
|
||||
| Keep 0x00 for streaming to avoid flicker and wear. |
|
||||
\*-----------------------------------------------------*/
|
||||
data[MSI_MONITOR_72_STORE_INDEX] = save ? 0x01 : 0x00;
|
||||
|
||||
SendFeatureReport(data, MSI_MONITOR_72_PACKET_SIZE);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| MSIMonitorController.h |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| Driver for MSI monitor (gaming controller) |
|
||||
| |
|
||||
| Andy Herbert 2026 June 1 |
|
||||
| Ken Sanislo 2026 July 20 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
@@ -18,6 +19,51 @@
|
||||
#define MSI_MONITOR_LEDS 9
|
||||
#define MSI_MONITOR_PACKET_SIZE 78
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| This panel holds each feature report outstanding for |
|
||||
| tens of ms while its MCU applies the frame, pinning the |
|
||||
| shared control pipe. Idle briefly after each write so |
|
||||
| other non periodic traffic on the bus is not starved. |
|
||||
| See SendFeatureReport. |
|
||||
\*---------------------------------------------------------*/
|
||||
#define MSI_MONITOR_PIPE_IDLE_MS 5
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 0x72 layout (dual control block, e.g. MPG 322URX QD-OLED) |
|
||||
\*---------------------------------------------------------*/
|
||||
#define MSI_MONITOR_72_PACKET_SIZE 168
|
||||
#define MSI_MONITOR_72_STORE_INDEX 167
|
||||
#define MSI_MONITOR_72_ARRAY_A_INDEX 23
|
||||
#define MSI_MONITOR_72_ARRAY_B_INDEX 95
|
||||
#define MSI_MONITOR_72_ARRAY_SLOTS 24
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Fill order the firmware expects (vendor Direction enum). |
|
||||
| Only the physical origin differs; index 0 is that end. |
|
||||
| The controller mirrors RightToLeft into left origin so |
|
||||
| OpenRGB LED 0 is always the left/start. Circle and Ctype |
|
||||
| are non linear shapes: driven as a plain line for now, |
|
||||
| they want a custom layout once someone maps the shape. |
|
||||
\*---------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
MSI_MONITOR_72_DIR_RIGHT_TO_LEFT = 0,
|
||||
MSI_MONITOR_72_DIR_LEFT_TO_RIGHT = 1,
|
||||
MSI_MONITOR_72_DIR_UP_TO_DOWN = 2,
|
||||
MSI_MONITOR_72_DIR_CIRCLE = 3,
|
||||
MSI_MONITOR_72_DIR_CTYPE = 4,
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Layout version query rides the short report channel: |
|
||||
| write [0x01][opcode], read [0x01][0x5A][data] |
|
||||
\*---------------------------------------------------------*/
|
||||
#define MSI_MONITOR_QUERY_PACKET_SIZE 64
|
||||
#define MSI_MONITOR_QUERY_REPORT_ID 0x01
|
||||
#define MSI_MONITOR_QUERY_ACK 0x5A
|
||||
#define MSI_MONITOR_OPCODE_GET_VERSION 0xB0
|
||||
#define MSI_MONITOR_VERSION_UNKNOWN 0
|
||||
|
||||
enum
|
||||
{
|
||||
MSI_MONITOR_OFF_MODE_VALUE = 0x00,
|
||||
@@ -31,6 +77,53 @@ enum
|
||||
MSI_MONITOR_RANDOM_MODE_VALUE = 0x1F
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 0x72 layout mode values. These match the MSI Mystic |
|
||||
| Light motherboard mode enum value for value (see |
|
||||
| MSIMysticLightController/MSIMysticLightCommon.h): the |
|
||||
| monitor runs the same Nuvoton Mystic Light engine, so the |
|
||||
| effect numbering is shared with its motherboard sibling. |
|
||||
| Values 10-14 and 32 are the audio modes, not exposed |
|
||||
| here (they need the music level feed). |
|
||||
\*---------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
MSI_MONITOR_72_MODE_OFF = 0,
|
||||
MSI_MONITOR_72_MODE_STATIC = 1,
|
||||
MSI_MONITOR_72_MODE_BREATHING = 2,
|
||||
MSI_MONITOR_72_MODE_FLASHING = 3,
|
||||
MSI_MONITOR_72_MODE_DOUBLE_FLASHING = 4,
|
||||
MSI_MONITOR_72_MODE_LIGHTNING = 5,
|
||||
MSI_MONITOR_72_MODE_SCANNER = 6,
|
||||
MSI_MONITOR_72_MODE_METEOR = 7,
|
||||
MSI_MONITOR_72_MODE_WATER_DROP = 8,
|
||||
MSI_MONITOR_72_MODE_RAINBOW_MSI = 9,
|
||||
MSI_MONITOR_72_MODE_COLOR_RING = 15,
|
||||
MSI_MONITOR_72_MODE_PLANETARY = 16,
|
||||
MSI_MONITOR_72_MODE_DOUBLE_METEOR = 17,
|
||||
MSI_MONITOR_72_MODE_ENERGY = 18,
|
||||
MSI_MONITOR_72_MODE_BLINK = 19,
|
||||
MSI_MONITOR_72_MODE_CLOCK = 20,
|
||||
MSI_MONITOR_72_MODE_COLOR_PULSE = 21,
|
||||
MSI_MONITOR_72_MODE_COLOR_SHIFT = 22,
|
||||
MSI_MONITOR_72_MODE_COLOR_WAVE = 23,
|
||||
MSI_MONITOR_72_MODE_MARQUEE = 24,
|
||||
MSI_MONITOR_72_MODE_RAINBOW = 25,
|
||||
MSI_MONITOR_72_MODE_RAINBOW_WAVE = 26,
|
||||
MSI_MONITOR_72_MODE_VISOR = 27,
|
||||
MSI_MONITOR_72_MODE_JRAINBOW = 28,
|
||||
MSI_MONITOR_72_MODE_RAINBOW_FLASH = 29,
|
||||
MSI_MONITOR_72_MODE_RAINBOW_DBLFLASH = 30,
|
||||
MSI_MONITOR_72_MODE_RAINBOW_LINE = 33,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MSI_MONITOR_72_SPEED_LOW = 0,
|
||||
MSI_MONITOR_72_SPEED_MEDIUM = 1,
|
||||
MSI_MONITOR_72_SPEED_HIGH = 2,
|
||||
};
|
||||
|
||||
class MSIMonitorController
|
||||
{
|
||||
public:
|
||||
@@ -44,7 +137,12 @@ public:
|
||||
|
||||
void Set(uint8_t mode_value, const std::vector<RGBColor> colors, uint8_t last_bit);
|
||||
|
||||
uint8_t GetLayoutVersion();
|
||||
void SetMode72(uint8_t mode_value, uint8_t speed, uint8_t brightness, RGBColor color1, RGBColor color2, bool user_palette, bool save, const std::vector<RGBColor>& led_colors, bool fill_both_arrays);
|
||||
|
||||
private:
|
||||
void SendFeatureReport(uint8_t *data, size_t length);
|
||||
|
||||
hid_device *dev;
|
||||
std::string description;
|
||||
std::string location;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| MSIKeyboardControllerDetect.cpp |
|
||||
| MSIMonitorControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for MSI monitor (MSI Gaming Controller) |
|
||||
| |
|
||||
@@ -10,10 +10,107 @@
|
||||
#include "DetectionManager.h"
|
||||
#include "MSIMonitorController.h"
|
||||
#include "RGBController_MSIMonitor.h"
|
||||
#include "RGBController_MSIMonitor72.h"
|
||||
|
||||
#define MSI_USB_VID 0x1462
|
||||
#define MSI_USB_PID 0x3FA4
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Vendor layout table (from the version -> layout map). |
|
||||
| The firmware reports its version to the 0xB0 query but |
|
||||
| not a LED count, so count/direction/block-count come |
|
||||
| from here. Fields: version, LED count, fill direction |
|
||||
| (MSI_MONITOR_72_DIR_*), dual_block. |
|
||||
| |
|
||||
| Every entry here is a single linear run driven through |
|
||||
| the 168 byte 0x72 buffer. Direction mirrors the fill so |
|
||||
| OpenRGB LED 0 is the left/start on every model. Circle |
|
||||
| and Ctype have no simple line mapping - they are driven |
|
||||
| as a plain line here and should get a custom per model |
|
||||
| layout once an owner maps the physical shape. |
|
||||
| |
|
||||
| Only version 34 is hardware verified (MPG 322URX). The |
|
||||
| rest are derived from the vendor table: same buffer, LED |
|
||||
| count and direction are the only differences, so effect |
|
||||
| and single colour modes are correct by construction. |
|
||||
| |
|
||||
| Left out on purpose: |
|
||||
| - dual_block versions 11/13/15 are stubbed but disabled |
|
||||
| (see the commented block); their two control blocks |
|
||||
| drive two runs and the per LED split is unconfirmed. |
|
||||
| - Advanced/0x82 versions 31/47 need the 0x30 bulk report |
|
||||
| this controller does not implement. |
|
||||
| A version not matched here falls through to the legacy |
|
||||
| 0x71 controller, home of the MAG272 class. |
|
||||
\*---------------------------------------------------------*/
|
||||
struct MSIMonitor72Layout
|
||||
{
|
||||
uint8_t version;
|
||||
unsigned int leds;
|
||||
unsigned int direction;
|
||||
bool dual_block;
|
||||
};
|
||||
|
||||
static const MSIMonitor72Layout msi_monitor_72_layouts[] =
|
||||
{
|
||||
{ 34, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG271QRXQD_OLED (MPG 322URX reports this) - verified */
|
||||
{ 5, 12, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG272R */
|
||||
{ 8, 24, MSI_MONITOR_72_DIR_CIRCLE, false }, /* MAG301CR - Circle, wants custom layout */
|
||||
{ 10, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG273R */
|
||||
{ 12, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG271VCR */
|
||||
{ 14, 14, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* NXG253R */
|
||||
{ 17, 8, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG2x5R */
|
||||
{ 20, 12, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG301RF */
|
||||
{ 21, 18, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG341QR */
|
||||
{ 22, 24, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG321QRF */
|
||||
{ 24, 12, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG321QR */
|
||||
{ 25, 24, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG321UR */
|
||||
{ 28, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG273CQR */
|
||||
{ 29, 24, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG401QR */
|
||||
{ 30, 21, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG325CQRF */
|
||||
{ 32, 7, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG274QRF */
|
||||
{ 33, 7, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG274URFQD */
|
||||
{ 36, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG275CQRXF */
|
||||
{ 37, 22, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG345CQRD */
|
||||
{ 38, 20, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG325CQRFQDE2 */
|
||||
{ 39, 8, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MPG321CURX_QD_OLED */
|
||||
{ 40, 12, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG322URDFE16 */
|
||||
{ 41, 14, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MPG242RX60N */
|
||||
{ 42, 22, MSI_MONITOR_72_DIR_CTYPE, false }, /* MPG274URDFWE16 - Ctype, wants custom layout */
|
||||
{ 43, 21, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG346CQRFX24 */
|
||||
{ 44, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG271QRQD_OLEDX50 */
|
||||
{ 46, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG341CQRQD_OLEDX36 */
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Dual block - stubbed but DISABLED. The dual_block path fills |
|
||||
| both colour arrays so uniform colour modes are correct, but each |
|
||||
| block drives its own run and the per LED split is unconfirmed, so |
|
||||
| Direct is a guess. These versions also map colour index above 15 |
|
||||
| to a separate DragonShield emblem region (unhandled). An owner |
|
||||
| should enable, test, and ideally give it a custom layout: |
|
||||
| { 11, 16, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, true }, MPG273CQR |
|
||||
| { 13, 21, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, true }, MPG343CQR |
|
||||
| { 15, 18, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, true }, MPG323CQR |
|
||||
| |
|
||||
| Advanced/0x82 - not addable here, need the 0x30 bulk report: |
|
||||
| version 31, 40 LEDs, MEG342CQD_OLED |
|
||||
| version 47, 83 LEDs, 4 areas, MEG_X |
|
||||
\*-----------------------------------------------------------------*/
|
||||
};
|
||||
|
||||
static const MSIMonitor72Layout* MSIMonitorLayout(uint8_t version)
|
||||
{
|
||||
for(unsigned int i = 0; i < (sizeof(msi_monitor_72_layouts) / sizeof(msi_monitor_72_layouts[0])); i++)
|
||||
{
|
||||
if(msi_monitor_72_layouts[i].version == version)
|
||||
{
|
||||
return(&msi_monitor_72_layouts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return(nullptr);
|
||||
}
|
||||
|
||||
DetectedControllers DetectMSIMonitorController(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
@@ -23,10 +120,41 @@ DetectedControllers DetectMSIMonitorController(hid_device_info* info, const std:
|
||||
|
||||
if(dev)
|
||||
{
|
||||
MSIMonitorController* controller = new MSIMonitorController(dev, *info, name);
|
||||
RGBController_MSIMonitor* rgb_controller = new RGBController_MSIMonitor(controller);
|
||||
/*-------------------------------------------------*\
|
||||
| One VID/PID covers several buffer layouts, so ask |
|
||||
| the MCU which one it speaks. A version in the |
|
||||
| 0x72 table selects the 168 byte layout and its |
|
||||
| LED count; anything else keeps the legacy 0x71 |
|
||||
| path, which is what the older monitors answer to. |
|
||||
\*-------------------------------------------------*/
|
||||
MSIMonitorController* controller = new MSIMonitorController(dev, *info, name);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
uint8_t version = controller->GetLayoutVersion();
|
||||
const MSIMonitor72Layout* layout = MSIMonitorLayout(version);
|
||||
|
||||
if(layout != nullptr)
|
||||
{
|
||||
detected_controllers.push_back(new RGBController_MSIMonitor72(controller, layout->leds, layout->direction, layout->dual_block));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| 0x71 family (78 byte buffer), handled by the |
|
||||
| legacy controller as a plain line. For an owner |
|
||||
| who wants to bring one onto this controller: same |
|
||||
| operative block 12, but the second colour array |
|
||||
| is at index 50 (not 95) and store-flash at 77. |
|
||||
| RightToLeft mirroring applies. version, LEDs, |
|
||||
| direction: |
|
||||
| 1, 9, RightToLeft (early/generic) |
|
||||
| 2, 7, LeftToRight (malformed stub, skip) |
|
||||
| 3, 9, RightToLeft (early/generic) |
|
||||
| 4, 9, LeftToRight (early/generic) |
|
||||
| 6, 9, UpToDown MAG270CR |
|
||||
| 7, 7, LeftToRight MAG251RX |
|
||||
\*-------------------------------------------------*/
|
||||
detected_controllers.push_back(new RGBController_MSIMonitor(controller));
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
|
||||
@@ -9,12 +9,8 @@
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "RGBController_MSIMonitor.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name MSIMonitor
|
||||
@category Accessory
|
||||
@@ -112,10 +108,6 @@ RGBController_MSIMonitor::RGBController_MSIMonitor(MSIMonitorController* control
|
||||
|
||||
RGBController_MSIMonitor::~RGBController_MSIMonitor()
|
||||
{
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
|
||||
Shutdown();
|
||||
|
||||
delete controller;
|
||||
@@ -145,7 +137,6 @@ void RGBController_MSIMonitor::SetupZones()
|
||||
|
||||
void RGBController_MSIMonitor::DeviceUpdateLEDs()
|
||||
{
|
||||
last_update_time = std::chrono::steady_clock::now();
|
||||
controller->Set(modes[active_mode].value, colors, active_mode == 0 ? 0x00 : 0x01);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor.cpp |
|
||||
| RGBController_MSIMonitor.h |
|
||||
| |
|
||||
| RGBController for MSI monitor (gaming controller) |
|
||||
| |
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "RGBController.h"
|
||||
#include "MSIMonitorController.h"
|
||||
|
||||
@@ -31,9 +30,4 @@ public:
|
||||
|
||||
private:
|
||||
MSIMonitorController* controller;
|
||||
std::thread* keepalive_thread;
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
|
||||
|
||||
void KeepaliveThread();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,570 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor72.cpp |
|
||||
| |
|
||||
| RGBController for MSI monitors using the 0x72 dual |
|
||||
| control block layout (MPG 322URX QD-OLED) |
|
||||
| |
|
||||
| Ken Sanislo 19 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "RGBController_MSIMonitor72.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name MSIMonitor72
|
||||
@category Accessory
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectMSIMonitorController
|
||||
@comment Developed with MSI MPG 322URX QD-OLED
|
||||
\*-------------------------------------------------------------------*/
|
||||
RGBController_MSIMonitor72::RGBController_MSIMonitor72(MSIMonitorController* controller_ptr, unsigned int count, unsigned int direction, bool dual)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
led_count = count;
|
||||
reverse_order = (direction == MSI_MONITOR_72_DIR_RIGHT_TO_LEFT);
|
||||
dual_block = dual;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "MSI";
|
||||
type = DEVICE_TYPE_MONITOR;
|
||||
description = "MSI Monitor (Gaming Controller)";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| This layout has no Advanced mode, so Direct is Static |
|
||||
| driven from the inline per LED colour arrays. |
|
||||
\*-----------------------------------------------------*/
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = MSI_MONITOR_72_MODE_STATIC;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Direct.brightness_min = 0;
|
||||
Direct.brightness_max = 100;
|
||||
Direct.brightness = 100;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = MSI_MONITOR_72_MODE_STATIC;
|
||||
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Static.colors_min = 1;
|
||||
Static.colors_max = 1;
|
||||
Static.colors.resize(1);
|
||||
Static.brightness_min = 0;
|
||||
Static.brightness_max = 100;
|
||||
Static.brightness = 100;
|
||||
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = MSI_MONITOR_72_MODE_BREATHING;
|
||||
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Breathing.colors_min = 1;
|
||||
Breathing.colors_max = 1;
|
||||
Breathing.colors.resize(1);
|
||||
Breathing.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Breathing.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Breathing.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Breathing.brightness_min = 0;
|
||||
Breathing.brightness_max = 100;
|
||||
Breathing.brightness = 100;
|
||||
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Flashing;
|
||||
Flashing.name = "Flashing";
|
||||
Flashing.value = MSI_MONITOR_72_MODE_FLASHING;
|
||||
Flashing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Flashing.colors_min = 2;
|
||||
Flashing.colors_max = 2;
|
||||
Flashing.colors.resize(2);
|
||||
Flashing.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Flashing.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Flashing.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Flashing.brightness_min = 0;
|
||||
Flashing.brightness_max = 100;
|
||||
Flashing.brightness = 100;
|
||||
Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Flashing);
|
||||
|
||||
mode DoubleFlashing;
|
||||
DoubleFlashing.name = "Double Flashing";
|
||||
DoubleFlashing.value = MSI_MONITOR_72_MODE_DOUBLE_FLASHING;
|
||||
DoubleFlashing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
DoubleFlashing.colors_min = 2;
|
||||
DoubleFlashing.colors_max = 2;
|
||||
DoubleFlashing.colors.resize(2);
|
||||
DoubleFlashing.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
DoubleFlashing.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
DoubleFlashing.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
DoubleFlashing.brightness_min = 0;
|
||||
DoubleFlashing.brightness_max = 100;
|
||||
DoubleFlashing.brightness = 100;
|
||||
DoubleFlashing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(DoubleFlashing);
|
||||
|
||||
mode Lightning;
|
||||
Lightning.name = "Lightning";
|
||||
Lightning.value = MSI_MONITOR_72_MODE_LIGHTNING;
|
||||
Lightning.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Lightning.colors_min = 1;
|
||||
Lightning.colors_max = 1;
|
||||
Lightning.colors.resize(1);
|
||||
Lightning.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Lightning.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Lightning.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Lightning.brightness_min = 0;
|
||||
Lightning.brightness_max = 100;
|
||||
Lightning.brightness = 100;
|
||||
Lightning.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Lightning);
|
||||
|
||||
mode Scanner;
|
||||
Scanner.name = "Scanner";
|
||||
Scanner.value = MSI_MONITOR_72_MODE_SCANNER;
|
||||
Scanner.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Scanner.colors_min = 1;
|
||||
Scanner.colors_max = 1;
|
||||
Scanner.colors.resize(1);
|
||||
Scanner.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Scanner.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Scanner.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Scanner.brightness_min = 0;
|
||||
Scanner.brightness_max = 100;
|
||||
Scanner.brightness = 100;
|
||||
Scanner.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Scanner);
|
||||
|
||||
mode Meteor;
|
||||
Meteor.name = "Meteor";
|
||||
Meteor.value = MSI_MONITOR_72_MODE_METEOR;
|
||||
Meteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Meteor.colors_min = 1;
|
||||
Meteor.colors_max = 1;
|
||||
Meteor.colors.resize(1);
|
||||
Meteor.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Meteor.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Meteor.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Meteor.brightness_min = 0;
|
||||
Meteor.brightness_max = 100;
|
||||
Meteor.brightness = 100;
|
||||
Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Meteor);
|
||||
|
||||
mode WaterDrop;
|
||||
WaterDrop.name = "Water Drop";
|
||||
WaterDrop.value = MSI_MONITOR_72_MODE_WATER_DROP;
|
||||
WaterDrop.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
WaterDrop.colors_min = 1;
|
||||
WaterDrop.colors_max = 1;
|
||||
WaterDrop.colors.resize(1);
|
||||
WaterDrop.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
WaterDrop.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
WaterDrop.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
WaterDrop.brightness_min = 0;
|
||||
WaterDrop.brightness_max = 100;
|
||||
WaterDrop.brightness = 100;
|
||||
WaterDrop.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(WaterDrop);
|
||||
|
||||
mode RainbowMSI;
|
||||
RainbowMSI.name = "Rainbow";
|
||||
RainbowMSI.value = MSI_MONITOR_72_MODE_RAINBOW_MSI;
|
||||
RainbowMSI.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
RainbowMSI.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
RainbowMSI.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
RainbowMSI.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
RainbowMSI.brightness_min = 0;
|
||||
RainbowMSI.brightness_max = 100;
|
||||
RainbowMSI.brightness = 100;
|
||||
RainbowMSI.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(RainbowMSI);
|
||||
|
||||
mode ColorRing;
|
||||
ColorRing.name = "Color Ring";
|
||||
ColorRing.value = MSI_MONITOR_72_MODE_COLOR_RING;
|
||||
ColorRing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorRing.colors_min = 1;
|
||||
ColorRing.colors_max = 1;
|
||||
ColorRing.colors.resize(1);
|
||||
ColorRing.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
ColorRing.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
ColorRing.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
ColorRing.brightness_min = 0;
|
||||
ColorRing.brightness_max = 100;
|
||||
ColorRing.brightness = 100;
|
||||
ColorRing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(ColorRing);
|
||||
|
||||
mode Planetary;
|
||||
Planetary.name = "Planetary";
|
||||
Planetary.value = MSI_MONITOR_72_MODE_PLANETARY;
|
||||
Planetary.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Planetary.colors_min = 1;
|
||||
Planetary.colors_max = 1;
|
||||
Planetary.colors.resize(1);
|
||||
Planetary.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Planetary.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Planetary.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Planetary.brightness_min = 0;
|
||||
Planetary.brightness_max = 100;
|
||||
Planetary.brightness = 100;
|
||||
Planetary.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Planetary);
|
||||
|
||||
mode DoubleMeteor;
|
||||
DoubleMeteor.name = "Double Meteor";
|
||||
DoubleMeteor.value = MSI_MONITOR_72_MODE_DOUBLE_METEOR;
|
||||
DoubleMeteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
DoubleMeteor.colors_min = 1;
|
||||
DoubleMeteor.colors_max = 1;
|
||||
DoubleMeteor.colors.resize(1);
|
||||
DoubleMeteor.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
DoubleMeteor.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
DoubleMeteor.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
DoubleMeteor.brightness_min = 0;
|
||||
DoubleMeteor.brightness_max = 100;
|
||||
DoubleMeteor.brightness = 100;
|
||||
DoubleMeteor.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(DoubleMeteor);
|
||||
|
||||
mode Energy;
|
||||
Energy.name = "Energy";
|
||||
Energy.value = MSI_MONITOR_72_MODE_ENERGY;
|
||||
Energy.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Energy.colors_min = 1;
|
||||
Energy.colors_max = 1;
|
||||
Energy.colors.resize(1);
|
||||
Energy.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Energy.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Energy.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Energy.brightness_min = 0;
|
||||
Energy.brightness_max = 100;
|
||||
Energy.brightness = 100;
|
||||
Energy.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Energy);
|
||||
|
||||
mode Blink;
|
||||
Blink.name = "Blink";
|
||||
Blink.value = MSI_MONITOR_72_MODE_BLINK;
|
||||
Blink.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Blink.colors_min = 1;
|
||||
Blink.colors_max = 1;
|
||||
Blink.colors.resize(1);
|
||||
Blink.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Blink.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Blink.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Blink.brightness_min = 0;
|
||||
Blink.brightness_max = 100;
|
||||
Blink.brightness = 100;
|
||||
Blink.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Blink);
|
||||
|
||||
mode Clock;
|
||||
Clock.name = "Clock";
|
||||
Clock.value = MSI_MONITOR_72_MODE_CLOCK;
|
||||
Clock.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Clock.colors_min = 1;
|
||||
Clock.colors_max = 1;
|
||||
Clock.colors.resize(1);
|
||||
Clock.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Clock.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Clock.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Clock.brightness_min = 0;
|
||||
Clock.brightness_max = 100;
|
||||
Clock.brightness = 100;
|
||||
Clock.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Clock);
|
||||
|
||||
mode ColorPulse;
|
||||
ColorPulse.name = "Color Pulse";
|
||||
ColorPulse.value = MSI_MONITOR_72_MODE_COLOR_PULSE;
|
||||
ColorPulse.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorPulse.colors_min = 1;
|
||||
ColorPulse.colors_max = 1;
|
||||
ColorPulse.colors.resize(1);
|
||||
ColorPulse.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
ColorPulse.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
ColorPulse.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
ColorPulse.brightness_min = 0;
|
||||
ColorPulse.brightness_max = 100;
|
||||
ColorPulse.brightness = 100;
|
||||
ColorPulse.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(ColorPulse);
|
||||
|
||||
mode ColorShift;
|
||||
ColorShift.name = "Color Shift";
|
||||
ColorShift.value = MSI_MONITOR_72_MODE_COLOR_SHIFT;
|
||||
ColorShift.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorShift.colors_min = 2;
|
||||
ColorShift.colors_max = 2;
|
||||
ColorShift.colors.resize(2);
|
||||
ColorShift.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
ColorShift.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
ColorShift.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
ColorShift.brightness_min = 0;
|
||||
ColorShift.brightness_max = 100;
|
||||
ColorShift.brightness = 100;
|
||||
ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(ColorShift);
|
||||
|
||||
mode ColorWave;
|
||||
ColorWave.name = "Color Wave";
|
||||
ColorWave.value = MSI_MONITOR_72_MODE_COLOR_WAVE;
|
||||
ColorWave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorWave.colors_min = 2;
|
||||
ColorWave.colors_max = 2;
|
||||
ColorWave.colors.resize(2);
|
||||
ColorWave.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
ColorWave.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
ColorWave.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
ColorWave.brightness_min = 0;
|
||||
ColorWave.brightness_max = 100;
|
||||
ColorWave.brightness = 100;
|
||||
ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(ColorWave);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Mode 24 marquee behaviour is model dependent. On the |
|
||||
| dual block / richer boards it wants the marker bytes |
|
||||
| plus a per LED array of separate colours (a user |
|
||||
| defined marquee). The vendor app does not even offer |
|
||||
| it for version 34, but the firmware still runs it as |
|
||||
| a one colour rolling band, so we expose that. |
|
||||
\*-----------------------------------------------------*/
|
||||
mode Marquee;
|
||||
Marquee.name = "Marquee";
|
||||
Marquee.value = MSI_MONITOR_72_MODE_MARQUEE;
|
||||
Marquee.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Marquee.colors_min = 1;
|
||||
Marquee.colors_max = 1;
|
||||
Marquee.colors.resize(1);
|
||||
Marquee.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Marquee.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Marquee.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Marquee.brightness_min = 0;
|
||||
Marquee.brightness_max = 100;
|
||||
Marquee.brightness = 100;
|
||||
Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Marquee);
|
||||
|
||||
mode SpectrumCycle;
|
||||
SpectrumCycle.name = "Spectrum Cycle";
|
||||
SpectrumCycle.value = MSI_MONITOR_72_MODE_RAINBOW;
|
||||
SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
SpectrumCycle.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
SpectrumCycle.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
SpectrumCycle.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
SpectrumCycle.brightness_min = 0;
|
||||
SpectrumCycle.brightness_max = 100;
|
||||
SpectrumCycle.brightness = 100;
|
||||
SpectrumCycle.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(SpectrumCycle);
|
||||
|
||||
mode RainbowWave;
|
||||
RainbowWave.name = "Rainbow Wave";
|
||||
RainbowWave.value = MSI_MONITOR_72_MODE_RAINBOW_WAVE;
|
||||
RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
RainbowWave.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
RainbowWave.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
RainbowWave.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
RainbowWave.brightness_min = 0;
|
||||
RainbowWave.brightness_max = 100;
|
||||
RainbowWave.brightness = 100;
|
||||
RainbowWave.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(RainbowWave);
|
||||
|
||||
mode Visor;
|
||||
Visor.name = "Visor";
|
||||
Visor.value = MSI_MONITOR_72_MODE_VISOR;
|
||||
Visor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
Visor.colors_min = 1;
|
||||
Visor.colors_max = 1;
|
||||
Visor.colors.resize(1);
|
||||
Visor.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
Visor.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
Visor.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
Visor.brightness_min = 0;
|
||||
Visor.brightness_max = 100;
|
||||
Visor.brightness = 100;
|
||||
Visor.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
modes.push_back(Visor);
|
||||
|
||||
mode JRainbow;
|
||||
JRainbow.name = "JRainbow";
|
||||
JRainbow.value = MSI_MONITOR_72_MODE_JRAINBOW;
|
||||
JRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
JRainbow.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
JRainbow.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
JRainbow.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
JRainbow.brightness_min = 0;
|
||||
JRainbow.brightness_max = 100;
|
||||
JRainbow.brightness = 100;
|
||||
JRainbow.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(JRainbow);
|
||||
|
||||
mode RainbowFlash;
|
||||
RainbowFlash.name = "Rainbow Flashing";
|
||||
RainbowFlash.value = MSI_MONITOR_72_MODE_RAINBOW_FLASH;
|
||||
RainbowFlash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
RainbowFlash.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
RainbowFlash.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
RainbowFlash.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
RainbowFlash.brightness_min = 0;
|
||||
RainbowFlash.brightness_max = 100;
|
||||
RainbowFlash.brightness = 100;
|
||||
RainbowFlash.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(RainbowFlash);
|
||||
|
||||
mode RainbowDblFlash;
|
||||
RainbowDblFlash.name = "Rainbow Double Flashing";
|
||||
RainbowDblFlash.value = MSI_MONITOR_72_MODE_RAINBOW_DBLFLASH;
|
||||
RainbowDblFlash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
RainbowDblFlash.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
RainbowDblFlash.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
RainbowDblFlash.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
RainbowDblFlash.brightness_min = 0;
|
||||
RainbowDblFlash.brightness_max = 100;
|
||||
RainbowDblFlash.brightness = 100;
|
||||
RainbowDblFlash.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(RainbowDblFlash);
|
||||
|
||||
mode RainbowLine;
|
||||
RainbowLine.name = "Rainbow Line";
|
||||
RainbowLine.value = MSI_MONITOR_72_MODE_RAINBOW_LINE;
|
||||
RainbowLine.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
|
||||
RainbowLine.speed_min = MSI_MONITOR_72_SPEED_LOW;
|
||||
RainbowLine.speed_max = MSI_MONITOR_72_SPEED_HIGH;
|
||||
RainbowLine.speed = MSI_MONITOR_72_SPEED_MEDIUM;
|
||||
RainbowLine.brightness_min = 0;
|
||||
RainbowLine.brightness_max = 100;
|
||||
RainbowLine.brightness = 100;
|
||||
RainbowLine.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(RainbowLine);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = MSI_MONITOR_72_MODE_OFF;
|
||||
Off.flags = MODE_FLAG_MANUAL_SAVE;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_MSIMonitor72::~RGBController_MSIMonitor72()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
|
||||
new_zone.name = "Rear";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = led_count;
|
||||
new_zone.leds_max = led_count;
|
||||
new_zone.leds_count = led_count;
|
||||
|
||||
zones.emplace_back(new_zone);
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "LED " + std::to_string(led_idx + 1);
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::DeviceUpdateLEDs()
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::DeviceUpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::DeviceUpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::ApplyMode(bool save)
|
||||
{
|
||||
const mode& active = modes[active_mode];
|
||||
|
||||
RGBColor color1 = 0;
|
||||
RGBColor color2 = 0;
|
||||
bool user_palette = false;
|
||||
std::vector<RGBColor> led_colors;
|
||||
|
||||
if(active.color_mode == MODE_COLORS_PER_LED)
|
||||
{
|
||||
user_palette = true;
|
||||
led_colors = colors;
|
||||
|
||||
if(led_colors.size() > 0)
|
||||
{
|
||||
color1 = led_colors[0];
|
||||
}
|
||||
}
|
||||
else if(active.color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
user_palette = true;
|
||||
|
||||
if(active.colors.size() > 0)
|
||||
{
|
||||
color1 = active.colors[0];
|
||||
|
||||
if(active.colors.size() > 1)
|
||||
{
|
||||
color2 = active.colors[1];
|
||||
}
|
||||
}
|
||||
|
||||
led_colors.assign(led_count, color1);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| RightToLeft layouts start at the right end, so mirror |
|
||||
| the per LED order to keep OpenRGB LED 0 on the left. |
|
||||
| Uniform colour modes are unaffected by the order. |
|
||||
\*-----------------------------------------------------*/
|
||||
if(reverse_order)
|
||||
{
|
||||
std::reverse(led_colors.begin(), led_colors.end());
|
||||
}
|
||||
|
||||
controller->SetMode72((uint8_t)active.value, (uint8_t)active.speed, (uint8_t)active.brightness, color1, color2, user_palette, save, led_colors, dual_block);
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::DeviceUpdateMode()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Updates are volatile. Persisting to flash is the |
|
||||
| Save To Device button (DeviceSaveMode), so live edits |
|
||||
| do not burn flash write cycles. |
|
||||
\*-----------------------------------------------------*/
|
||||
ApplyMode(false);
|
||||
}
|
||||
|
||||
void RGBController_MSIMonitor72::DeviceSaveMode()
|
||||
{
|
||||
ApplyMode(true);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_MSIMonitor72.h |
|
||||
| |
|
||||
| RGBController for MSI monitors using the 0x72 dual |
|
||||
| control block layout (MPG 322URX QD-OLED) |
|
||||
| |
|
||||
| Ken Sanislo 19 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "MSIMonitorController.h"
|
||||
|
||||
class RGBController_MSIMonitor72 : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_MSIMonitor72(MSIMonitorController* controller_ptr, unsigned int count, unsigned int direction, bool dual);
|
||||
~RGBController_MSIMonitor72();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void DeviceUpdateZoneLEDs(int zone);
|
||||
void DeviceUpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
void DeviceSaveMode();
|
||||
|
||||
private:
|
||||
void ApplyMode(bool save);
|
||||
|
||||
MSIMonitorController* controller;
|
||||
unsigned int led_count;
|
||||
bool reverse_order;
|
||||
bool dual_block;
|
||||
};
|
||||
+4
@@ -73,6 +73,8 @@ static const std::string board_names[] =
|
||||
"MSI MEG Z890 UNIFY-X (MS-7E20)",
|
||||
"MSI PRO X870E-S EVO WIFI (MS-7E86)",
|
||||
"MSI PRO Z890-P WIFI (MS-7E34)",
|
||||
"MSI B850 GAMING PLUS WIFI PZ (MS-7E75)",
|
||||
"MSI MAG X870E TOMAHAWK MAX WIFI PZ (MS-7E84)",
|
||||
};
|
||||
|
||||
static const mystic_light_761_config board_configs[] =
|
||||
@@ -103,6 +105,8 @@ static const mystic_light_761_config board_configs[] =
|
||||
{ &(board_names[23]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MEG Z890 UNIFY-X (MS-7E20)
|
||||
{ &(board_names[24]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO X870E-S EVO WIFI (MS-7E86)
|
||||
{ &(board_names[25]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO Z890-P WIFI (MS-7E34)
|
||||
{ &(board_names[26]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI B850 GAMING PLUS WIFI PZ (MS-7E75)
|
||||
{ &(board_names[27]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG X870E TOMAHAWK MAX WIFI PZ (MS-7E84)
|
||||
};
|
||||
|
||||
enum MSI_ZONE setup_map [] =
|
||||
|
||||
+4
-4
@@ -132,10 +132,10 @@ void RGBController_MSIMysticLight761::SetupZones()
|
||||
/*-------------------------------------------------*\
|
||||
| This is a fixed size zone |
|
||||
\*-------------------------------------------------*/
|
||||
if(((zd->zone_type != MSI_ZONE_J_RAINBOW_1)
|
||||
&& (zd->zone_type != MSI_ZONE_J_RAINBOW_2)
|
||||
&& (zd->zone_type != MSI_ZONE_J_RAINBOW_3)
|
||||
&& (zd->zone_type != MSI_ZONE_J_CORSAIR)))
|
||||
if(((zd->zone_type != MSI_ZONE_JAF)
|
||||
&& (zd->zone_type != MSI_ZONE_JARGB_1)
|
||||
&& (zd->zone_type != MSI_ZONE_JARGB_2)
|
||||
&& (zd->zone_type != MSI_ZONE_JARGB_3)))
|
||||
{
|
||||
zones[zone_idx].name = zd->name;
|
||||
zones[zone_idx].type = ZONE_TYPE_SINGLE;
|
||||
|
||||
+3
-2
@@ -50,6 +50,7 @@ static const nv_gpu_pci_device device_list[] =
|
||||
{NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 SUPER FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 Ti FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080TI_FE_CP2077_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 Ti Cyberpunk 2077" },
|
||||
{NVIDIA_VEN, NVIDIA_TITANRTX_DEV, NVIDIA_SUB_VEN, NVIDIA_TITANRTX_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA TITAN RTX" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX3050_DEV, NVIDIA_SUB_VEN, GAINWARD_RTX3050_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3050 LHR" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3060 Pegasus" },
|
||||
@@ -76,8 +77,8 @@ static const nv_gpu_pci_device device_list[] =
|
||||
{NVIDIA_VEN, NVIDIA_RTX4080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 SUPER FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4090 FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4090_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4090 FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX5080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5080 FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX5090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5090 FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX5080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5080 FE" },
|
||||
{NVIDIA_VEN, NVIDIA_RTX5090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5090 FE" },
|
||||
};
|
||||
|
||||
DetectedControllers DetectNVIDIAIllumGPUs()
|
||||
|
||||
@@ -77,3 +77,4 @@ REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX6900XT", DetectPowerC
|
||||
REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX6900XT Ultimate", DetectPowerColorRedDevilGPUControllersV1, AMD_GPU_VEN, AMD_NAVI21_DEV2, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX6900XT_ULTIMATE_SUB_DEV, 0x22);
|
||||
|
||||
REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX9070XT", DetectPowerColorRedDevilGPUControllersV2, AMD_GPU_VEN, AMD_NAVI48_DEV, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX9070XT_SUB_DEV, 0x22);
|
||||
REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX9070", DetectPowerColorRedDevilGPUControllersV2, AMD_GPU_VEN, AMD_NAVI48_DEV, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX9070_SUB_DEV, 0x22);
|
||||
|
||||
@@ -19,7 +19,115 @@
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
QMKKeychronController::QMKKeychronController(hid_device* dev_handle, const char *path)
|
||||
/*---------------------------------------------------------*\
|
||||
| Keychron Patch Types |
|
||||
| The Keychron protocol does not provide RGB matrix X/Y |
|
||||
| coordinates, only the position in the wiring matrix. |
|
||||
| For most Keychron keyboards, the wiring matrix mostly |
|
||||
| matches the physical position, but there are often a |
|
||||
| few misplaced LEDs. Implement a matrix patching system |
|
||||
| to apply keyboard-specific patches for these misplaced |
|
||||
| LEDs. |
|
||||
\*---------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int led_idx;
|
||||
unsigned int row;
|
||||
unsigned int col;
|
||||
} keychron_patch_entry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short pid;
|
||||
unsigned int num_entries;
|
||||
const keychron_patch_entry* patch;
|
||||
} keychron_patch;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keychron K5 V2 ANSI Encoder |
|
||||
\*---------------------------------------------------------*/
|
||||
#define KEYCHRON_K5_V2_ANSI_RGB_PATCH_ENTRIES_COUNT \
|
||||
(sizeof(keychron_k5_v2_ansi_rgb_patch_entries) / sizeof(keychron_patch_entry))
|
||||
|
||||
static const keychron_patch_entry keychron_k5_v2_ansi_rgb_patch_entries[] =
|
||||
{
|
||||
{ 18, 0, 19 },
|
||||
{ 19, 0, 20 },
|
||||
{ 39, 1, 19 },
|
||||
{ 40, 1, 20 },
|
||||
{ 60, 2, 19 },
|
||||
{ 61, 2, 20 },
|
||||
{ 74, 3, 12 },
|
||||
{ 77, 3, 19 },
|
||||
{ 89, 4, 12 },
|
||||
{ 93, 4, 19 },
|
||||
{ 107, 5, 19 },
|
||||
{ 94, 5, 20 },
|
||||
};
|
||||
|
||||
static const keychron_patch keychron_k5_v2_ansi_rgb_patch =
|
||||
{
|
||||
KEYCHRON_K5_V2_ANSI_RGB_PID,
|
||||
KEYCHRON_K5_V2_ANSI_RGB_PATCH_ENTRIES_COUNT,
|
||||
keychron_k5_v2_ansi_rgb_patch_entries
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keychron Q2 ANSI Encoder |
|
||||
\*---------------------------------------------------------*/
|
||||
#define KEYCHRON_Q2_ANSI_ENCODER_PATCH_ENTRIES_COUNT (sizeof(keychron_q2_ansi_encoder_patch_entries) / sizeof(keychron_patch_entry))
|
||||
|
||||
static const keychron_patch_entry keychron_q2_ansi_encoder_patch_entries[] =
|
||||
{
|
||||
{ 60, 4, 9 },
|
||||
{ 61, 4, 10 },
|
||||
{ 62, 4, 11 },
|
||||
{ 63, 4, 12 },
|
||||
{ 54, 3, 12 },
|
||||
{ 55, 3, 13 },
|
||||
{ 64, 4, 13 },
|
||||
};
|
||||
|
||||
static const keychron_patch keychron_q2_ansi_encoder_patch =
|
||||
{
|
||||
KEYCHRON_Q2_ANSI_ENCODER_PID,
|
||||
KEYCHRON_Q2_ANSI_ENCODER_PATCH_ENTRIES_COUNT,
|
||||
keychron_q2_ansi_encoder_patch_entries
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keychron Q6 ANSI Encoder |
|
||||
\*---------------------------------------------------------*/
|
||||
#define KEYCHRON_Q6_ULTRA_8K_ANSI_PATCH_ENTRIES_COUNT (sizeof(keychron_q6_ultra_8k_ansi_patch_entries) / sizeof(keychron_patch_entry))
|
||||
|
||||
static const keychron_patch_entry keychron_q6_ultra_8k_ansi_patch_entries[] =
|
||||
{
|
||||
{ 19, 0, 20 },
|
||||
{ 40, 1, 20 },
|
||||
{ 77, 3, 20 },
|
||||
{ 107, 5, 20 },
|
||||
};
|
||||
|
||||
static const keychron_patch keychron_q6_ultra_8k_ansi_patch =
|
||||
{
|
||||
KEYCHRON_Q6_ULTRA_8K_ANSI_PID,
|
||||
KEYCHRON_Q6_ULTRA_8K_ANSI_PATCH_ENTRIES_COUNT,
|
||||
keychron_q6_ultra_8k_ansi_patch_entries
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| List of all Keychron patches |
|
||||
\*---------------------------------------------------------*/
|
||||
#define KEYCHRON_PATCH_COUNT (sizeof(keychron_patches) / sizeof(keychron_patch*))
|
||||
|
||||
static const keychron_patch* keychron_patches[] =
|
||||
{
|
||||
&keychron_q2_ansi_encoder_patch,
|
||||
&keychron_q6_ultra_8k_ansi_patch,
|
||||
&keychron_k5_v2_ansi_rgb_patch,
|
||||
};
|
||||
|
||||
QMKKeychronController::QMKKeychronController(hid_device* dev_handle, const char *path, unsigned short dev_pid)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Initialize controller fields |
|
||||
@@ -27,6 +135,7 @@ QMKKeychronController::QMKKeychronController(hid_device* dev_handle, const char
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
kc_protocol_version = 0;
|
||||
pid = dev_pid;
|
||||
supported_features = 0;
|
||||
via_protocol_version = 0;
|
||||
|
||||
@@ -143,6 +252,21 @@ QMKKeychronController::QMKKeychronController(hid_device* dev_handle, const char
|
||||
{
|
||||
keycodes[led_index] = CmdGetKeycode(0, led_info[led_index].row, led_info[led_index].col);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Apply matrix corrections |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int patch_idx = 0; patch_idx < KEYCHRON_PATCH_COUNT; patch_idx++)
|
||||
{
|
||||
if(pid == keychron_patches[patch_idx]->pid)
|
||||
{
|
||||
for(unsigned int patch_entry_idx = 0; patch_entry_idx < keychron_patches[patch_idx]->num_entries; patch_entry_idx++)
|
||||
{
|
||||
led_info[keychron_patches[patch_idx]->patch[patch_entry_idx].led_idx].row = keychron_patches[patch_idx]->patch[patch_entry_idx].row;
|
||||
led_info[keychron_patches[patch_idx]->patch[patch_entry_idx].led_idx].col = keychron_patches[patch_idx]->patch[patch_entry_idx].col;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMKKeychronController::~QMKKeychronController()
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
#define KEYCHRON_K17_MAX_ISO_ENCODER_RGB_PID 0x0A01
|
||||
#define KEYCHRON_K17_MAX_JIS_ENCODER_RGB_PID 0x0A02
|
||||
#define KEYCHRON_Q0_BASE_PID 0x0130
|
||||
#define KEYCHRON_Q0_HE_PID 0x0B00
|
||||
#define KEYCHRON_Q0_PLUS_PID 0x0131
|
||||
#define KEYCHRON_Q0_MAX_ENCODER_PID 0x0800
|
||||
#define KEYCHRON_Q1_HE_ANSI_ENCODER_PID 0x0B10
|
||||
@@ -389,7 +390,7 @@ enum KeychronVIABacklightValueID
|
||||
class QMKKeychronController
|
||||
{
|
||||
public:
|
||||
QMKKeychronController(hid_device* dev_handle, const char *path);
|
||||
QMKKeychronController(hid_device* dev_handle, const char *path, unsigned short dev_pid);
|
||||
~QMKKeychronController();
|
||||
|
||||
std::string GetLocation();
|
||||
@@ -419,6 +420,7 @@ private:
|
||||
std::string location;
|
||||
std::string name;
|
||||
unsigned short number_leds;
|
||||
unsigned short pid;
|
||||
std::string serial;
|
||||
unsigned short supported_features;
|
||||
std::string vendor;
|
||||
|
||||
@@ -23,7 +23,7 @@ DetectedControllers DetectQMKKeychronControllers(hid_device_info* info, const st
|
||||
|
||||
if(dev)
|
||||
{
|
||||
QMKKeychronController* controller = new QMKKeychronController(dev, info->path);
|
||||
QMKKeychronController* controller = new QMKKeychronController(dev, info->path, info->product_id);
|
||||
|
||||
if(controller->GetSupported())
|
||||
{
|
||||
@@ -129,6 +129,7 @@ REGISTER_HID_DETECTOR_IPU("Keychron K17 Max", DetectQMKKeychronControllers
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron K17 Max", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_K17_MAX_ISO_ENCODER_RGB_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron K17 Max", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_K17_MAX_JIS_ENCODER_RGB_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron Q0", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_Q0_BASE_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron Q0 HE", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_Q0_HE_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron Q0 Plus", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_Q0_PLUS_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron Q0 Max", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_Q0_MAX_ENCODER_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
REGISTER_HID_DETECTOR_IPU("Keychron Q1 HE", DetectQMKKeychronControllers, KEYCHRON_VID, KEYCHRON_Q1_HE_ANSI_ENCODER_PID, 1, KEYCHRON_QMK_USAGE_PAGE, KEYCHRON_QMK_USAGE);
|
||||
|
||||
@@ -12,22 +12,18 @@
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "RedSquareKeyroxController.h"
|
||||
#include "RedSquareKeyroxTKLClassicController.h"
|
||||
#include "RGBController_RedSquareKeyrox.h"
|
||||
#include "RGBController_RedSquareKeyroxTKLClassic.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Red Square vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define RED_SQUARE_VID 0x1A2C
|
||||
#define RED_SQUARE_KEYROX_TKL_CLASSIC_VID 0x0416
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Red Square product ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define RED_SQUARE_KEYROX_TKL_PID 0x1511
|
||||
#define RED_SQUARE_KEYROX_TKL_V2_PID 0x2511
|
||||
#define RED_SQUARE_KEYROX_TKL_CLASSIC_PID 0xC345
|
||||
|
||||
DetectedControllers DetectRedSquareKeyroxTKL(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
@@ -47,24 +43,5 @@ DetectedControllers DetectRedSquareKeyroxTKL(hid_device_info* info, const std::s
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectRedSquareKeyroxTKLClassic(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RedSquareKeyroxTKLClassicController* controller = new RedSquareKeyroxTKLClassicController(dev, *info, name);
|
||||
RGBController_RedSquareKeyroxTKLClassic* rgb_controller = new RGBController_RedSquareKeyroxTKLClassic(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Red Square Keyrox TKL", DetectRedSquareKeyroxTKL, RED_SQUARE_VID, RED_SQUARE_KEYROX_TKL_PID, 3, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Red Square Keyrox TKL V2", DetectRedSquareKeyroxTKL, RED_SQUARE_VID, RED_SQUARE_KEYROX_TKL_V2_PID, 3, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_I( "Red Square Keyrox TKL Classic", DetectRedSquareKeyroxTKLClassic, RED_SQUARE_KEYROX_TKL_CLASSIC_VID, RED_SQUARE_KEYROX_TKL_CLASSIC_PID, 2);
|
||||
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RedSquareKeyroxTKLClassicController.cpp |
|
||||
| |
|
||||
| Driver for Red Square Keyrox TKL Classic |
|
||||
| |
|
||||
| vlack 03 May 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "LogManager.h"
|
||||
#include "RedSquareKeyroxTKLClassicController.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
RedSquareKeyroxTKLClassicController::RedSquareKeyroxTKLClassicController(hid_device *dev_handle, const hid_device_info &info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
RedSquareKeyroxTKLClassicController::~RedSquareKeyroxTKLClassicController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RedSquareKeyroxTKLClassicController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RedSquareKeyroxTKLClassicController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RedSquareKeyroxTKLClassicController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_wchar[128];
|
||||
hid_get_serial_number_string(dev, serial_wchar, 128);
|
||||
std::wstring serial_wstring(serial_wchar);
|
||||
|
||||
std::string serial_string;
|
||||
std::transform(serial_wstring.begin(), serial_wstring.end(), std::back_inserter(serial_string), [] (wchar_t i)
|
||||
{
|
||||
return (char)i;
|
||||
});
|
||||
|
||||
return serial_string;
|
||||
}
|
||||
|
||||
int RedSquareKeyroxTKLClassicController::GetDirection(int direction)
|
||||
{
|
||||
switch(direction)
|
||||
{
|
||||
case MODE_DIRECTION_LEFT:
|
||||
return 0x00;
|
||||
case MODE_DIRECTION_RIGHT:
|
||||
return 0x01;
|
||||
case MODE_DIRECTION_UP:
|
||||
return 0x02;
|
||||
case MODE_DIRECTION_DOWN:
|
||||
return 0x03;
|
||||
case MODE_DIRECTION_HORIZONTAL: // actually direction out
|
||||
return 0x04;
|
||||
case MODE_DIRECTION_VERTICAL: // actually direction in
|
||||
return 0x05;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
int RedSquareKeyroxTKLClassicController::GetDirectionRound(int direction)
|
||||
{
|
||||
switch(direction)
|
||||
{
|
||||
case MODE_DIRECTION_LEFT: // actually anticlockwise
|
||||
return 0x07;
|
||||
case MODE_DIRECTION_RIGHT: // actually clockwise
|
||||
return 0x06;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
void RedSquareKeyroxTKLClassicController::SetMode(mode m)
|
||||
{
|
||||
/*---------------------------------------------*\
|
||||
| Mode set command |
|
||||
\*---------------------------------------------*/
|
||||
|
||||
unsigned char usb_buf[CLASSIC_PACKET_DATA_LENGTH];
|
||||
memset(usb_buf, 0x00, CLASSIC_PACKET_DATA_LENGTH);
|
||||
|
||||
usb_buf[0] = 0x01;
|
||||
usb_buf[1] = 0x07;
|
||||
usb_buf[6] = m.value;
|
||||
usb_buf[7] = m.brightness; // brightness
|
||||
usb_buf[8] = m.speed; // speed
|
||||
|
||||
if(m.colors_max == 1 || m.colors_max == 2)
|
||||
{
|
||||
usb_buf[9] = RGBGetRValue(m.colors[0]); // front R
|
||||
usb_buf[10] = RGBGetGValue(m.colors[0]); // front G
|
||||
usb_buf[11] = RGBGetBValue(m.colors[0]); // front B
|
||||
}
|
||||
|
||||
if(m.colors_max == 2 && m.color_mode != MODE_COLORS_RANDOM)
|
||||
{
|
||||
usb_buf[12] = RGBGetRValue(m.colors[1]); // back R
|
||||
usb_buf[13] = RGBGetGValue(m.colors[1]); // back G
|
||||
usb_buf[14] = RGBGetBValue(m.colors[1]); // back B
|
||||
}
|
||||
|
||||
if(m.value == CLASSIC_RADAR_MODE_VALUE || m.value == CLASSIC_RUNNING_LINE_MODE_VALUE)
|
||||
{
|
||||
usb_buf[15] = GetDirectionRound(m.direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_buf[15] = GetDirection(m.direction);
|
||||
}
|
||||
|
||||
usb_buf[16] = m.color_mode == MODE_COLORS_RANDOM;
|
||||
|
||||
hid_write(dev, usb_buf, CLASSIC_PACKET_DATA_LENGTH);
|
||||
// sleep is necessary
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
|
||||
void RedSquareKeyroxTKLClassicController::SetLEDsData(std::vector<RGBColor> colors, std::vector<led> leds)
|
||||
{
|
||||
/*---------------------------------------------*\
|
||||
| LEDs data set command |
|
||||
\*---------------------------------------------*/
|
||||
|
||||
unsigned char usb_buf[CLASSIC_PACKET_DATA_LENGTH * 8];
|
||||
memset(usb_buf, 0x00, CLASSIC_PACKET_DATA_LENGTH * 8);
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
int offset = leds[i].value;
|
||||
usb_buf[offset - 1] = RGBGetRValue(colors[i]);
|
||||
usb_buf[offset] = RGBGetGValue(colors[i]);
|
||||
usb_buf[offset + 1] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char packet[CLASSIC_PACKET_DATA_LENGTH];
|
||||
memset(packet, 0x00, CLASSIC_PACKET_DATA_LENGTH);
|
||||
|
||||
packet[0] = 0x01;
|
||||
packet[1] = 0x0F;
|
||||
packet[4] = i; // package number
|
||||
packet[5] = i == 7 ? 0x12 : 0x36; // package size
|
||||
|
||||
for (int x = 6; x < CLASSIC_PACKET_DATA_LENGTH; x++)
|
||||
{
|
||||
packet[x] = usb_buf[CLASSIC_PACKET_DATA_LENGTH * i + x];
|
||||
}
|
||||
hid_write(dev, packet, CLASSIC_PACKET_DATA_LENGTH);
|
||||
}
|
||||
|
||||
// sleep is necessary
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RedSquareKeyroxTKLClassicController.h |
|
||||
| |
|
||||
| Driver for Red Square Keyrox TKL Classic |
|
||||
| |
|
||||
| vlack 03 May 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define CLASSIC_PACKET_DATA_LENGTH 64
|
||||
|
||||
/*---------------------------------------*\
|
||||
| Modes |
|
||||
\*---------------------------------------*/
|
||||
enum
|
||||
{
|
||||
CLASSIC_CONST_MODE_VALUE = 0x00, // static
|
||||
CLASSIC_BREATHE_MODE_VALUE = 0x01, // breath
|
||||
CLASSIC_WAVE_MODE_VALUE = 0x02, // wave
|
||||
CLASSIC_FADE_MODE_VALUE = 0x03, // neon
|
||||
CLASSIC_RADAR_MODE_VALUE = 0x04, // radar
|
||||
CLASSIC_STAR_MODE_VALUE = 0x06, // интерактив
|
||||
CLASSIC_LINE_MODE_VALUE = 0x07, // сияние
|
||||
CLASSIC_RIPPLE_MODE_VALUE = 0x08, // рябь интерактив
|
||||
CLASSIC_STARS_MODE_VALUE = 0x09, // мерцание
|
||||
CLASSIC_CUSTOM_MODE_VALUE = 0x0A,
|
||||
CLASSIC_CROSS_MODE_VALUE = 0x0B, // скрещивание
|
||||
CLASSIC_WTF_MODE_VALUE = 0x0C, // быстрый отклик
|
||||
CLASSIC_RIPPLE_RANDOM_MODE_VALUE = 0x0E, // рябь
|
||||
CLASSIC_RUNNING_LINE_MODE_VALUE = 0x0F, // бегущая строка
|
||||
CLASSIC_FIREWORK_MODE_VALUE = 0x10, // firework
|
||||
};
|
||||
|
||||
/*-----------------------------*\
|
||||
| Other settings |
|
||||
\*-----------------------------*/
|
||||
enum
|
||||
{
|
||||
CLASSIC_KEYROX_BRIGHTNESS_MIN = 0x00,
|
||||
CLASSIC_KEYROX_BRIGHTNESS_MAX = 0x04,
|
||||
CLASSIC_KEYROX_SPEED_MIN = 0x00,
|
||||
CLASSIC_KEYROX_SPEED_MAX = 0x04,
|
||||
};
|
||||
|
||||
|
||||
class RedSquareKeyroxTKLClassicController
|
||||
{
|
||||
public:
|
||||
RedSquareKeyroxTKLClassicController(hid_device *dev_handle, const hid_device_info &info, std::string dev_name);
|
||||
~RedSquareKeyroxTKLClassicController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
int GetDirection(int direction);
|
||||
int GetDirectionRound(int direction);
|
||||
|
||||
void SetMode(mode m);
|
||||
void SetLEDsData(std::vector<RGBColor> colors, std::vector<led> leds);
|
||||
|
||||
protected:
|
||||
hid_device* dev;
|
||||
|
||||
private:
|
||||
std::string location;
|
||||
std::string name;
|
||||
std::string serial_number;
|
||||
std::vector<unsigned int> led_sequence_positions;
|
||||
};
|
||||
+10
-1
@@ -151,6 +151,9 @@ void RGBController_RoccatVulcanKeyboard::SetupZones()
|
||||
case ROCCAT_VULCAN_LAYOUT_FR:
|
||||
layout = ROCCAT_VULCAN_LAYOUT_UK;
|
||||
break;
|
||||
case ROCCAT_VULCAN_LAYOUT_JP:
|
||||
layout = ROCCAT_VULCAN_LAYOUT_JP;
|
||||
break;
|
||||
case ROCCAT_VULCAN_LAYOUT_US:
|
||||
default:
|
||||
layout = ROCCAT_VULCAN_LAYOUT_US;
|
||||
@@ -167,7 +170,13 @@ void RGBController_RoccatVulcanKeyboard::SetupZones()
|
||||
|
||||
if(pid == ROCCAT_VULCAN_II_MAX_PID)
|
||||
{
|
||||
keyboard_size = 108;
|
||||
/*---------------------------------------------------------*\
|
||||
| Dynamically calculate the main keyboard zone size by |
|
||||
| subtracting the 40 secondary/palm rest LEDs from the |
|
||||
| total layout size. This prevents JIS keys from overflow. |
|
||||
\*---------------------------------------------------------*/
|
||||
keyboard_size = keyboard[layout].size - 40;
|
||||
|
||||
}
|
||||
|
||||
zone keyboard_zone;
|
||||
|
||||
+19
-4
@@ -84,6 +84,10 @@ device_info RoccatVulcanKeyboardController::InitDeviceInfo()
|
||||
memset(buf, 0x00, packet_length);
|
||||
|
||||
buf[0] = report_id;
|
||||
/*-------------------------------------------------------------*\
|
||||
| Store the actual read bytes to verify data availability |
|
||||
\*-------------------------------------------------------------*/
|
||||
int res = hid_get_feature_report(dev_ctrl, buf, packet_length);
|
||||
hid_get_feature_report(dev_ctrl, buf, packet_length);
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
@@ -107,11 +111,22 @@ device_info RoccatVulcanKeyboardController::InitDeviceInfo()
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_info.layout_type = buf[6];
|
||||
/*---------------------------------------------------------*\
|
||||
| Safe check for reported buffer length before accessing |
|
||||
| buf[6] to prevent out-of-bounds array access. |
|
||||
| Vulcan II Max (JP) returns 0x06 at buf[6] for JIS layout. |
|
||||
\*---------------------------------------------------------*/
|
||||
if(res >= 7)
|
||||
{
|
||||
dev_info.layout_type = buf[6];
|
||||
LOG_DEBUG("[Roccat Vulcan Keyboard]: Detected layout '0x%02X'", buf[6]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_info.layout_type = ROCCAT_VULCAN_LAYOUT_US;
|
||||
LOG_DEBUG("[Roccat Vulcan Keyboard]: Failed to detect layout, falling back to US");
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("[Roccat Vulcan Keyboard]: Detected layout '0x%02X'", buf[6]);
|
||||
|
||||
delete[] buf;
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
+224
-1
@@ -22,6 +22,7 @@ enum
|
||||
ROCCAT_VULCAN_LAYOUT_DE = 1,
|
||||
ROCCAT_VULCAN_LAYOUT_UK = 2,
|
||||
ROCCAT_VULCAN_LAYOUT_FR = 3,
|
||||
ROCCAT_VULCAN_LAYOUT_JP = 6, /* Updated based on Vulcan II Max JIS firmware report value */
|
||||
};
|
||||
|
||||
#define NA 0xFFFFFFFF
|
||||
@@ -815,6 +816,16 @@ static unsigned int ROCCAT_VULCAN_II_MAX_LAYOUT_KEYS_ANSI[6][24] =
|
||||
{ 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, 74, NA, NA, 78, 83, 87, NA, 92, NA, 101, NA }
|
||||
};
|
||||
|
||||
static unsigned int ROCCAT_VULCAN_II_MAX_LAYOUT_KEYS_JIS[6][24] =
|
||||
{
|
||||
{ 0, NA, 7, 13, 19, 25, NA, 35, 40, 45, 51, 57, 63, 69, 73, NA, 78, 82, 87, NA, 108, 109, 110, NA },
|
||||
{ 1, 6, 8, 14, 20, 26, 30, 36, 41, 46, 52, 58, 64, 70, 74, NA, 79, 83, 88, NA, 91, 96, 100, 105 },
|
||||
{ 2, NA, 9, 15, 21, 27, 31, 37, 42, 47, 53, 59, 65, 71, 75, NA, 80, 84, 89, NA, 92, 97, 101, 106 },
|
||||
{ 3, NA, 10, 16, 22, 28, 32, 38, 43, 48, 54, 60, 66, 72, NA, NA, NA, NA, NA, NA, 93, 98, 102, NA },
|
||||
{ 4, NA, 11, 17, 23, 29, 33, 39, 44, 49, 55, 61, 67, NA, 76, NA, NA, 85, NA, NA, 94, 99, 103, 107 },
|
||||
{ 5, NA, 12, 18, 24, NA, 34, NA, NA, 50, 56, 62, 68, NA, 77, NA, 81, 86, 90, NA, 95, NA, 104, NA }
|
||||
};
|
||||
|
||||
static std::map<int, layout_info> RoccatVulcanIIMaxLayouts =
|
||||
{
|
||||
{
|
||||
@@ -1005,7 +1016,219 @@ static std::map<int, layout_info> RoccatVulcanIIMaxLayouts =
|
||||
{ "Key: Left Windows LED 2", 0x83 },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Palm Rest LEDs (order approximate - needs verification) |
|
||||
| Palm Rest LEDs (order approximate - needs verification) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Palm Rest LED 1", 0x96 },
|
||||
{ "Palm Rest LED 2", 0xAD },
|
||||
{ "Palm Rest LED 3", 0xA7 },
|
||||
{ "Palm Rest LED 4", 0xA1 },
|
||||
{ "Palm Rest LED 5", 0x9B },
|
||||
{ "Palm Rest LED 6", 0x95 },
|
||||
{ "Palm Rest LED 7", 0xAC },
|
||||
{ "Palm Rest LED 8", 0xA6 },
|
||||
{ "Palm Rest LED 9", 0xA0 },
|
||||
{ "Palm Rest LED 10", 0x9A },
|
||||
{ "Palm Rest LED 11", 0x94 },
|
||||
{ "Palm Rest LED 12", 0xAB },
|
||||
{ "Palm Rest LED 13", 0xA5 },
|
||||
{ "Palm Rest LED 14", 0x9F },
|
||||
{ "Palm Rest LED 15", 0x99 },
|
||||
{ "Palm Rest LED 16", 0x93 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
ROCCAT_VULCAN_LAYOUT_JP,
|
||||
{
|
||||
*ROCCAT_VULCAN_II_MAX_LAYOUT_KEYS_JIS,
|
||||
151,
|
||||
6,
|
||||
24,
|
||||
{
|
||||
{ KEY_EN_ESCAPE, 0x02 },
|
||||
{ KEY_JP_EJ, 0x03 },
|
||||
{ KEY_EN_TAB, 0x04 },
|
||||
{ KEY_EN_CAPS_LOCK, 0x05 },
|
||||
{ KEY_EN_LEFT_SHIFT, 0x00 },
|
||||
{ KEY_EN_LEFT_CONTROL, 0x01 },
|
||||
|
||||
{ KEY_EN_1, 0x08 },
|
||||
|
||||
{ KEY_EN_F1, 0x0D },
|
||||
{ KEY_EN_2, 0x0E },
|
||||
{ KEY_EN_Q, 0x09 },
|
||||
{ KEY_EN_A, 0x0A },
|
||||
{ KEY_EN_Z, 0x0B },
|
||||
{ KEY_EN_LEFT_WINDOWS, 0x07 },
|
||||
|
||||
{ KEY_EN_F2, 0x14 },
|
||||
{ KEY_EN_3, 0x15 },
|
||||
{ KEY_EN_W, 0x0F },
|
||||
{ KEY_EN_S, 0x10 },
|
||||
{ KEY_EN_X, 0x11 },
|
||||
{ KEY_EN_LEFT_ALT, 0x0C },
|
||||
|
||||
{ KEY_EN_F3, 0x19 },
|
||||
{ KEY_EN_4, 0x1A },
|
||||
{ KEY_EN_E, 0x16 },
|
||||
{ KEY_EN_D, 0x17 },
|
||||
{ KEY_EN_C, 0x18 },
|
||||
{ KEY_JP_MUHENKAN, 0x12 },
|
||||
|
||||
{ KEY_EN_F4, 0x1F },
|
||||
{ KEY_EN_5, 0x1E },
|
||||
{ KEY_EN_R, 0x1B },
|
||||
{ KEY_EN_F, 0x1C },
|
||||
{ KEY_EN_V, 0x21 },
|
||||
|
||||
{ KEY_EN_6, 0x24 },
|
||||
{ KEY_EN_T, 0x20 },
|
||||
{ KEY_EN_G, 0x1D },
|
||||
{ KEY_EN_B, 0x22 },
|
||||
{ KEY_EN_SPACE, 0x28 },
|
||||
|
||||
{ KEY_EN_F5, 0x23 },
|
||||
{ KEY_EN_7, 0x29 },
|
||||
{ KEY_EN_Y, 0x25 },
|
||||
{ KEY_EN_H, 0x26 },
|
||||
{ KEY_EN_N, 0x27 },
|
||||
|
||||
{ KEY_EN_F6, 0x2F },
|
||||
{ KEY_EN_8, 0x30 },
|
||||
{ KEY_EN_U, 0x3D },
|
||||
{ KEY_EN_J, 0x2B },
|
||||
{ KEY_EN_M, 0x2C },
|
||||
|
||||
{ KEY_EN_F7, 0x35 },
|
||||
{ KEY_EN_9, 0x36 },
|
||||
{ KEY_EN_I, 0x31 },
|
||||
{ KEY_EN_K, 0x32 },
|
||||
{ KEY_EN_COMMA, 0x33 },
|
||||
{ KEY_JP_HENKAN, 0x2D },
|
||||
|
||||
{ KEY_EN_F8, 0x3B },
|
||||
{ KEY_EN_0, 0x3C },
|
||||
{ KEY_EN_O, 0x37 },
|
||||
{ KEY_EN_L, 0x38 },
|
||||
{ KEY_EN_PERIOD, 0x39 },
|
||||
{ KEY_JP_KANA, 0x34 },
|
||||
|
||||
{ KEY_EN_F9, 0x41 },
|
||||
{ KEY_EN_MINUS, 0x42 },
|
||||
{ KEY_EN_P, 0x2A },
|
||||
{ KEY_EN_SEMICOLON, 0x3E },
|
||||
{ KEY_EN_FORWARD_SLASH, 0x3F },
|
||||
{ KEY_EN_RIGHT_FUNCTION, 0x40 },
|
||||
|
||||
{ KEY_EN_F10, 0x47 },
|
||||
{ KEY_JP_CHEVRON, 0x48 },
|
||||
{ KEY_JP_AT, 0x43 },
|
||||
{ KEY_JP_COLON, 0x44 },
|
||||
{ KEY_EN_BACK_SLASH, 0x45 },
|
||||
{ KEY_EN_MENU, 0x46 },
|
||||
|
||||
{ KEY_EN_F11, 0x4D },
|
||||
{ KEY_JP_YEN, 0x4E },
|
||||
{ KEY_EN_LEFT_BRACKET, 0x49 },
|
||||
{ KEY_EN_RIGHT_BRACKET, 0x4A },
|
||||
|
||||
{ KEY_EN_F12, 0x4F },
|
||||
{ KEY_EN_BACKSPACE, 0x50 },
|
||||
{ KEY_EN_ISO_ENTER, 0x52 },
|
||||
{ KEY_EN_RIGHT_SHIFT, 0x4B },
|
||||
{ KEY_EN_RIGHT_CONTROL, 0x4C },
|
||||
|
||||
{ KEY_EN_PRINT_SCREEN, 0x53 },
|
||||
{ KEY_EN_INSERT, 0x54 },
|
||||
{ KEY_EN_DELETE, 0x55 },
|
||||
{ KEY_EN_LEFT_ARROW, 0x56 },
|
||||
|
||||
{ KEY_EN_SCROLL_LOCK, 0x57 },
|
||||
{ KEY_EN_HOME, 0x58 },
|
||||
{ KEY_EN_END, 0x59 },
|
||||
{ KEY_EN_UP_ARROW, 0x5A },
|
||||
{ KEY_EN_DOWN_ARROW, 0x5B },
|
||||
|
||||
{ KEY_EN_PAUSE_BREAK, 0x5C },
|
||||
{ KEY_EN_PAGE_UP, 0x5D },
|
||||
{ KEY_EN_PAGE_DOWN, 0x5E },
|
||||
{ KEY_EN_RIGHT_ARROW, 0x5F },
|
||||
|
||||
{ KEY_EN_NUMPAD_LOCK, 0x60 },
|
||||
{ KEY_EN_NUMPAD_7, 0x61 },
|
||||
{ KEY_EN_NUMPAD_4, 0x62 },
|
||||
{ KEY_EN_NUMPAD_1, 0x6C },
|
||||
{ KEY_EN_NUMPAD_0, 0x64 },
|
||||
|
||||
{ KEY_EN_NUMPAD_DIVIDE, 0x65 },
|
||||
{ KEY_EN_NUMPAD_8, 0x66 },
|
||||
{ KEY_EN_NUMPAD_5, 0x67 },
|
||||
{ KEY_EN_NUMPAD_2, 0x68 },
|
||||
|
||||
{ KEY_EN_NUMPAD_TIMES, 0x69 },
|
||||
{ KEY_EN_NUMPAD_9, 0x6A },
|
||||
{ KEY_EN_NUMPAD_6, 0x6B },
|
||||
{ KEY_EN_NUMPAD_3, 0x63 },
|
||||
{ KEY_EN_NUMPAD_PERIOD, 0x6D },
|
||||
|
||||
{ KEY_EN_NUMPAD_MINUS, 0x6E },
|
||||
{ KEY_EN_NUMPAD_PLUS, 0x6F },
|
||||
{ KEY_EN_NUMPAD_ENTER, 0x71 },
|
||||
|
||||
{ KEY_EN_MEDIA_PREVIOUS, 0x72 },
|
||||
{ KEY_EN_MEDIA_PLAY_PAUSE, 0x73 },
|
||||
{ KEY_EN_MEDIA_NEXT, 0x74 },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| F-Key Indicators (secondary LEDs) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Key: F1 LED 2", 0x89 },
|
||||
{ "Key: F2 LED 2", 0x7B },
|
||||
{ "Key: F3 LED 2", 0x81 },
|
||||
{ "Key: F4 LED 2", 0x87 },
|
||||
{ "Key: F5 LED 2", 0x8D },
|
||||
{ "Key: F6 LED 2", 0x76 },
|
||||
{ "Key: F7 LED 2", 0x7C },
|
||||
{ "Key: F8 LED 2", 0x82 },
|
||||
{ "Key: F9 LED 2", 0x88 },
|
||||
{ "Key: F10 LED 2", 0x8E },
|
||||
{ "Key: F11 LED 2", 0x7A },
|
||||
{ "Key: F12 LED 2", 0x80 },
|
||||
{ "Key: Print Screen LED 2", 0x86 },
|
||||
{ "Key: Scroll Lock LED 2", 0x8C },
|
||||
{ "Key: Pause/Break LED 2", 0x92 },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Nav Cluster Indicators (secondary LEDs) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Key: Insert LED 2", 0x75 },
|
||||
{ "Key: Home LED 2", 0x7E },
|
||||
{ "Key: Page Up LED 2", 0x84 },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Num Lock Indicator (secondary LED) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Key: Num Lock LED 2", 0x8B },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Nav Cluster Indicators 2 (secondary LEDs) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Key: Delete LED 2", 0x78 },
|
||||
{ "Key: End LED 2", 0x90 },
|
||||
{ "Key: Page Down LED 2", 0x8A },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Caps Lock Indicator (secondary LED) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Key: Caps Lock LED 2", 0x7D },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Win Key Indicator (secondary LED) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Key: Left Windows LED 2", 0x83 },
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| Palm Rest LEDs (order approximate - needs verification) |
|
||||
\*-------------------------------------------------------------*/
|
||||
{ "Palm Rest LED 1", 0x96 },
|
||||
{ "Palm Rest LED 2", 0xAD },
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_SkydimoHID.cpp |
|
||||
| |
|
||||
| RGBController for Skydimo HID devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 09 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_SkydimoHID.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Skydimo SK0902
|
||||
@category HeadsetStand
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectSkydimoHIDControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
static const unsigned int skydimo_hid_led_positions[SKYDIMO_HID_LED_COUNT][2] =
|
||||
{
|
||||
{0, 6}, {0, 5}, {0, 4}, {0, 3}, {0, 2}, {0, 1}, {0, 0},
|
||||
{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6},
|
||||
{2, 6}, {2, 5}, {2, 4}, {2, 3}, {2, 2}, {2, 1}, {2, 0},
|
||||
{3, 0}, {3, 1}, {3, 2}, {3, 3}, {3, 4}, {3, 5}, {3, 6},
|
||||
{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0},
|
||||
{5, 0}, {5, 1}, {5, 2}, {5, 3}, {5, 4}, {5, 5}, {5, 6},
|
||||
{6, 6}, {6, 5}, {6, 4}, {6, 3}, {6, 2}, {6, 1}, {6, 0}
|
||||
};
|
||||
|
||||
RGBController_SkydimoHID::RGBController_SkydimoHID(SkydimoHIDController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetDeviceName();
|
||||
vendor = "Skydimo";
|
||||
type = DEVICE_TYPE_HEADSET_STAND;
|
||||
description = "Skydimo HID Device";
|
||||
serial = controller->GetSerial();
|
||||
location = controller->GetLocation();
|
||||
|
||||
mode direct_mode;
|
||||
direct_mode.name = "Direct";
|
||||
direct_mode.value = 0;
|
||||
direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
direct_mode.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(direct_mode);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_SkydimoHID::~RGBController_SkydimoHID()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_SkydimoHID::SetupZones()
|
||||
{
|
||||
zone led_zone;
|
||||
led_zone.name = "Matrix";
|
||||
led_zone.type = ZONE_TYPE_MATRIX;
|
||||
led_zone.leds_min = SKYDIMO_HID_LED_COUNT;
|
||||
led_zone.leds_max = SKYDIMO_HID_LED_COUNT;
|
||||
led_zone.leds_count = SKYDIMO_HID_LED_COUNT;
|
||||
|
||||
led_zone.matrix_map.height = SKYDIMO_HID_MATRIX_SIZE;
|
||||
led_zone.matrix_map.width = SKYDIMO_HID_MATRIX_SIZE;
|
||||
led_zone.matrix_map.map.assign(SKYDIMO_HID_MATRIX_SIZE * SKYDIMO_HID_MATRIX_SIZE, SKYDIMO_HID_MATRIX_NA);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Construct the matrix map |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int led_idx = 0; led_idx < SKYDIMO_HID_LED_COUNT; led_idx++)
|
||||
{
|
||||
unsigned int column = skydimo_hid_led_positions[led_idx][0];
|
||||
unsigned int row = skydimo_hid_led_positions[led_idx][1];
|
||||
|
||||
led_zone.matrix_map.map[(row * SKYDIMO_HID_MATRIX_SIZE) + column] = led_idx;
|
||||
}
|
||||
|
||||
zones.push_back(led_zone);
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < SKYDIMO_HID_LED_COUNT; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "LED " + std::to_string(led_idx + 1);
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_SkydimoHID::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->SetLEDs(colors);
|
||||
}
|
||||
|
||||
void RGBController_SkydimoHID::DeviceUpdateZoneLEDs(int)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_SkydimoHID::DeviceUpdateSingleLED(int)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_SkydimoHID::DeviceUpdateMode()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_SkydimoHID.h |
|
||||
| |
|
||||
| RGBController for Skydimo HID devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 09 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "SkydimoHIDController.h"
|
||||
|
||||
class RGBController_SkydimoHID : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_SkydimoHID(SkydimoHIDController* controller_ptr);
|
||||
~RGBController_SkydimoHID();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void DeviceUpdateZoneLEDs(int zone);
|
||||
void DeviceUpdateSingleLED(int led);
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
SkydimoHIDController* controller;
|
||||
};
|
||||
@@ -0,0 +1,195 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SkydimoHIDController.cpp |
|
||||
| |
|
||||
| Driver for Skydimo HID devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 09 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "LogManager.h"
|
||||
#include "SkydimoHIDController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
static unsigned char CalculateCRC8(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
unsigned char crc = 0x00;
|
||||
|
||||
for(unsigned int byte_idx = 0; byte_idx < length; byte_idx++)
|
||||
{
|
||||
crc ^= data[byte_idx];
|
||||
|
||||
for(unsigned int bit_idx = 0; bit_idx < SKYDIMO_HID_CRC_BIT_COUNT; bit_idx++)
|
||||
{
|
||||
if(crc & SKYDIMO_HID_CRC_HIGH_BIT)
|
||||
{
|
||||
crc = (unsigned char)((crc << 1) ^ SKYDIMO_HID_CRC_POLYNOMIAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
crc = (unsigned char)(crc << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
SkydimoHIDController::SkydimoHIDController(hid_device* dev_handle, const char* path)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
|
||||
wchar_t name_string[SKYDIMO_HID_NAME_BUFFER_SIZE];
|
||||
int result;
|
||||
|
||||
result = hid_get_manufacturer_string(dev, name_string, SKYDIMO_HID_NAME_BUFFER_SIZE);
|
||||
if(result == 0)
|
||||
{
|
||||
device_name = StringUtils::wstring_to_string(name_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
device_name = "Skydimo";
|
||||
LOG_WARNING("[SkydimoHIDController] Failed to read manufacturer string for %s", path);
|
||||
}
|
||||
|
||||
result = hid_get_product_string(dev, name_string, SKYDIMO_HID_NAME_BUFFER_SIZE);
|
||||
if(result == 0)
|
||||
{
|
||||
device_name.append(" ").append(StringUtils::wstring_to_string(name_string));
|
||||
}
|
||||
else
|
||||
{
|
||||
device_name.append(" HID Device");
|
||||
LOG_WARNING("[SkydimoHIDController] Failed to read product string for %s", path);
|
||||
}
|
||||
|
||||
wchar_t serial_string[SKYDIMO_HID_SERIAL_BUFFER_SIZE];
|
||||
result = hid_get_serial_number_string(dev, serial_string, SKYDIMO_HID_SERIAL_BUFFER_SIZE);
|
||||
if(result == 0)
|
||||
{
|
||||
serial = StringUtils::wstring_to_string(serial_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
serial = "";
|
||||
LOG_DEBUG("[SkydimoHIDController] No serial number available for %s", path);
|
||||
}
|
||||
}
|
||||
|
||||
SkydimoHIDController::~SkydimoHIDController()
|
||||
{
|
||||
if(dev)
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
}
|
||||
|
||||
std::string SkydimoHIDController::GetDeviceName() const
|
||||
{
|
||||
return(device_name);
|
||||
}
|
||||
|
||||
std::string SkydimoHIDController::GetSerial() const
|
||||
{
|
||||
return(serial);
|
||||
}
|
||||
|
||||
std::string SkydimoHIDController::GetLocation() const
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
bool SkydimoHIDController::SendPacket(unsigned char start_led, const unsigned char* chunk, unsigned int chunk_length)
|
||||
{
|
||||
unsigned char packet[SKYDIMO_HID_PACKET_SIZE];
|
||||
memset(packet, 0x00, sizeof(packet));
|
||||
|
||||
packet[0] = SKYDIMO_HID_REPORT_ID;
|
||||
packet[SKYDIMO_HID_PACKET_START_LED_INDEX] = start_led;
|
||||
packet[SKYDIMO_HID_PACKET_RESERVED_INDEX] = 0x00;
|
||||
|
||||
if(chunk_length > SKYDIMO_HID_PACKET_DATA_SIZE)
|
||||
{
|
||||
chunk_length = SKYDIMO_HID_PACKET_DATA_SIZE;
|
||||
}
|
||||
|
||||
memcpy(&packet[SKYDIMO_HID_PACKET_DATA_OFFSET], chunk, chunk_length);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Calculate CRC8 over all bytes before the checksum |
|
||||
\*-----------------------------------------------------*/
|
||||
packet[SKYDIMO_HID_PACKET_SIZE - 1] = CalculateCRC8(packet, SKYDIMO_HID_PACKET_SIZE - 1);
|
||||
|
||||
int bytes_written = hid_write(dev, packet, SKYDIMO_HID_PACKET_SIZE);
|
||||
|
||||
if(bytes_written != SKYDIMO_HID_PACKET_SIZE)
|
||||
{
|
||||
LOG_ERROR("[SkydimoHIDController] Failed to write RGB packet at LED %u (%d/%u bytes): %ls",
|
||||
(unsigned int)start_led, bytes_written, (unsigned int)SKYDIMO_HID_PACKET_SIZE, hid_error(dev));
|
||||
return(false);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void SkydimoHIDController::SetLEDs(const std::vector<RGBColor>& colors)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(device_mutex);
|
||||
|
||||
unsigned char frame_data[SKYDIMO_HID_FRAME_SIZE];
|
||||
memset(frame_data, 0, sizeof(frame_data));
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Convert colors to GRB format |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int led_idx = 0; (led_idx < colors.size()) && (led_idx < SKYDIMO_HID_LED_COUNT); led_idx++)
|
||||
{
|
||||
unsigned int color_offset = led_idx * SKYDIMO_HID_BYTES_PER_LED;
|
||||
|
||||
frame_data[color_offset + 0] = RGBGetGValue(colors[led_idx]);
|
||||
frame_data[color_offset + 1] = RGBGetRValue(colors[led_idx]);
|
||||
frame_data[color_offset + 2] = RGBGetBValue(colors[led_idx]);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send the frame in packet-sized chunks |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int frame_offset = 0; frame_offset < SKYDIMO_HID_FRAME_SIZE; frame_offset += SKYDIMO_HID_PACKET_DATA_SIZE)
|
||||
{
|
||||
unsigned int bytes_remaining = SKYDIMO_HID_FRAME_SIZE - frame_offset;
|
||||
unsigned int chunk_length = (bytes_remaining < SKYDIMO_HID_PACKET_DATA_SIZE)
|
||||
? bytes_remaining
|
||||
: SKYDIMO_HID_PACKET_DATA_SIZE;
|
||||
unsigned char start_led = (unsigned char)(frame_offset / SKYDIMO_HID_BYTES_PER_LED);
|
||||
|
||||
if(!SendPacket(start_led, &frame_data[frame_offset], chunk_length))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send the frame-end packet |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned char end_packet[SKYDIMO_HID_PACKET_SIZE];
|
||||
memset(end_packet, 0x00, sizeof(end_packet));
|
||||
|
||||
end_packet[0] = SKYDIMO_HID_REPORT_ID;
|
||||
end_packet[SKYDIMO_HID_END_COMMAND_INDEX] = SKYDIMO_HID_END_COMMAND_VALUE;
|
||||
end_packet[SKYDIMO_HID_END_SUBCOMMAND_INDEX] = SKYDIMO_HID_END_SUBCOMMAND_VALUE;
|
||||
end_packet[SKYDIMO_HID_END_LED_COUNT_INDEX] = SKYDIMO_HID_LED_COUNT;
|
||||
end_packet[SKYDIMO_HID_END_MARKER_INDEX] = SKYDIMO_HID_END_MARKER_VALUE;
|
||||
|
||||
int bytes_written = hid_write(dev, end_packet, SKYDIMO_HID_PACKET_SIZE);
|
||||
|
||||
if(bytes_written != SKYDIMO_HID_PACKET_SIZE)
|
||||
{
|
||||
LOG_ERROR("[SkydimoHIDController] Failed to write frame-end packet (%d/%u bytes): %ls",
|
||||
bytes_written, (unsigned int)SKYDIMO_HID_PACKET_SIZE, hid_error(dev));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SkydimoHIDController.h |
|
||||
| |
|
||||
| Driver for Skydimo HID devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 09 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <hidapi.h>
|
||||
#include "RGBControllerInterface.h"
|
||||
|
||||
#define SKYDIMO_HID_LED_COUNT 49
|
||||
#define SKYDIMO_HID_MATRIX_SIZE 7
|
||||
#define SKYDIMO_HID_BYTES_PER_LED 3
|
||||
#define SKYDIMO_HID_FRAME_SIZE (SKYDIMO_HID_LED_COUNT * SKYDIMO_HID_BYTES_PER_LED)
|
||||
#define SKYDIMO_HID_PACKET_SIZE 64
|
||||
#define SKYDIMO_HID_PACKET_DATA_SIZE 60
|
||||
#define SKYDIMO_HID_PACKET_DATA_OFFSET 3
|
||||
#define SKYDIMO_HID_REPORT_ID 0x01
|
||||
#define SKYDIMO_HID_PACKET_START_LED_INDEX 1
|
||||
#define SKYDIMO_HID_PACKET_RESERVED_INDEX 2
|
||||
#define SKYDIMO_HID_MATRIX_NA 0xFFFFFFFF
|
||||
#define SKYDIMO_HID_CRC_POLYNOMIAL 0x07
|
||||
#define SKYDIMO_HID_CRC_HIGH_BIT 0x80
|
||||
#define SKYDIMO_HID_CRC_BIT_COUNT 8
|
||||
#define SKYDIMO_HID_NAME_BUFFER_SIZE 255
|
||||
#define SKYDIMO_HID_SERIAL_BUFFER_SIZE 128
|
||||
#define SKYDIMO_HID_END_MARKER_INDEX 60
|
||||
#define SKYDIMO_HID_END_MARKER_VALUE 0x1E
|
||||
#define SKYDIMO_HID_END_COMMAND_INDEX 1
|
||||
#define SKYDIMO_HID_END_COMMAND_VALUE 0xFF
|
||||
#define SKYDIMO_HID_END_SUBCOMMAND_INDEX 2
|
||||
#define SKYDIMO_HID_END_SUBCOMMAND_VALUE 0xFF
|
||||
#define SKYDIMO_HID_END_LED_COUNT_INDEX 3
|
||||
|
||||
class SkydimoHIDController
|
||||
{
|
||||
public:
|
||||
SkydimoHIDController(hid_device* dev_handle, const char* path);
|
||||
~SkydimoHIDController();
|
||||
|
||||
std::string GetDeviceName() const;
|
||||
std::string GetSerial() const;
|
||||
std::string GetLocation() const;
|
||||
|
||||
void SetLEDs(const std::vector<RGBColor>& colors);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string device_name;
|
||||
std::string serial;
|
||||
std::string location;
|
||||
std::mutex device_mutex;
|
||||
|
||||
bool SendPacket(unsigned char start_led, const unsigned char* chunk, unsigned int chunk_length);
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SkydimoHIDControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Skydimo HID devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 09 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "LogManager.h"
|
||||
#include "RGBController_SkydimoHID.h"
|
||||
#include "SkydimoHIDController.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Skydimo HID vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define SKYDIMO_VID 0x1A86
|
||||
#define SKYDIMO_SK0902_PID 0xE316
|
||||
#define SKYDIMO_SK0902_INTERFACE 0
|
||||
#define SKYDIMO_SK0902_USAGE_PAGE 0xFF00
|
||||
#define SKYDIMO_SK0902_USAGE 0x01
|
||||
|
||||
DetectedControllers DetectSkydimoHIDControllers(hid_device_info* info, const std::string&)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
SkydimoHIDController* controller = new SkydimoHIDController(dev, info->path);
|
||||
RGBController_SkydimoHID* rgb_controller = new RGBController_SkydimoHID(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
LOG_INFO("[SkydimoHIDControllerDetect] Detected Skydimo SK0902 at %s", info->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("[SkydimoHIDControllerDetect] Failed to open Skydimo SK0902 at %s", info->path);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Skydimo SK0902", DetectSkydimoHIDControllers, SKYDIMO_VID, SKYDIMO_SK0902_PID, SKYDIMO_SK0902_INTERFACE, SKYDIMO_SK0902_USAGE_PAGE, SKYDIMO_SK0902_USAGE);
|
||||
@@ -0,0 +1,147 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_SkydimoSerial.cpp |
|
||||
| |
|
||||
| RGBController for Skydimo serial devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 30 Jun 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_SkydimoSerial.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Skydimo Serial
|
||||
@category LEDStrip
|
||||
@type Serial
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectSkydimoSerialControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_SkydimoSerial::RGBController_SkydimoSerial(SkydimoSerialController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "Skydimo";
|
||||
type = DEVICE_TYPE_LEDSTRIP;
|
||||
description = "Skydimo Serial Device";
|
||||
serial = controller->GetSerial();
|
||||
location = controller->GetLocation();
|
||||
|
||||
mode direct_mode;
|
||||
direct_mode.name = "Direct";
|
||||
direct_mode.value = 0;
|
||||
direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
direct_mode.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(direct_mode);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_SkydimoSerial::~RGBController_SkydimoSerial()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
controller->SetBlack();
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_SkydimoSerial::SetupZones()
|
||||
{
|
||||
bool first_run = zones.empty();
|
||||
|
||||
leds.clear();
|
||||
colors.clear();
|
||||
zones.resize(1);
|
||||
|
||||
zones[0].leds_min = controller->GetMinLEDCount();
|
||||
zones[0].leds_max = controller->GetMaxLEDCount();
|
||||
|
||||
if(first_run)
|
||||
{
|
||||
if(controller->IsResizable())
|
||||
{
|
||||
zones[0].flags = ZONE_FLAG_MANUALLY_CONFIGURABLE_SIZE
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_NAME
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_TYPE
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_MATRIX_MAP
|
||||
| ZONE_FLAG_MANUALLY_CONFIGURABLE_SEGMENTS;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(zones[0].flags & ZONE_FLAG_MANUALLY_CONFIGURED_NAME))
|
||||
{
|
||||
zones[0].name = "Output 1";
|
||||
}
|
||||
|
||||
if(!(zones[0].flags & ZONE_FLAG_MANUALLY_CONFIGURED_SIZE))
|
||||
{
|
||||
zones[0].leds_count = controller->GetLEDCount();
|
||||
}
|
||||
|
||||
if(!(zones[0].flags & ZONE_FLAG_MANUALLY_CONFIGURED_TYPE))
|
||||
{
|
||||
zones[0].type = controller->GetMatrixMap().empty() ? ZONE_TYPE_LINEAR : ZONE_TYPE_MATRIX;
|
||||
}
|
||||
|
||||
if(!(zones[0].flags & ZONE_FLAG_MANUALLY_CONFIGURED_MATRIX_MAP))
|
||||
{
|
||||
zones[0].matrix_map.height = controller->GetMatrixHeight();
|
||||
zones[0].matrix_map.width = controller->GetMatrixWidth();
|
||||
zones[0].matrix_map.map = controller->GetMatrixMap();
|
||||
}
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = zones[0].name + ", LED " + std::to_string(led_idx + 1);
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_SkydimoSerial::DeviceConfigureZone(int zone_idx)
|
||||
{
|
||||
unsigned int zone_index = (unsigned int)zone_idx;
|
||||
|
||||
if(zone_index < zones.size())
|
||||
{
|
||||
if(zones[zone_index].flags & ZONE_FLAG_MANUALLY_CONFIGURED_SIZE)
|
||||
{
|
||||
controller->SetLEDCount(zones[zone_index].leds_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller->SetLEDCount(controller->GetMinLEDCount());
|
||||
}
|
||||
|
||||
zones[zone_index].leds_count = controller->GetLEDCount();
|
||||
SetupZones();
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_SkydimoSerial::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->SetLEDs(colors);
|
||||
}
|
||||
|
||||
void RGBController_SkydimoSerial::DeviceUpdateZoneLEDs(int)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_SkydimoSerial::DeviceUpdateSingleLED(int)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_SkydimoSerial::DeviceUpdateMode()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_SkydimoSerial.h |
|
||||
| |
|
||||
| RGBController for Skydimo serial devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 30 Jun 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "SkydimoSerialController.h"
|
||||
|
||||
class RGBController_SkydimoSerial : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_SkydimoSerial(SkydimoSerialController* controller_ptr);
|
||||
~RGBController_SkydimoSerial();
|
||||
|
||||
void SetupZones();
|
||||
void DeviceConfigureZone(int zone_idx);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void DeviceUpdateZoneLEDs(int zone);
|
||||
void DeviceUpdateSingleLED(int led);
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
SkydimoSerialController* controller;
|
||||
};
|
||||
@@ -0,0 +1,548 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SkydimoSerialController.cpp |
|
||||
| |
|
||||
| Driver for Skydimo serial devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 30 Jun 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include "LogManager.h"
|
||||
#include "SkydimoSerialController.h"
|
||||
|
||||
enum SkydimoLayoutKind
|
||||
{
|
||||
SKYDIMO_LAYOUT_NONE,
|
||||
SKYDIMO_LAYOUT_STRIP_1,
|
||||
SKYDIMO_LAYOUT_PERIMETER_3,
|
||||
SKYDIMO_LAYOUT_PERIMETER_4,
|
||||
SKYDIMO_LAYOUT_SIDES_2
|
||||
};
|
||||
|
||||
struct SkydimoModelEntry
|
||||
{
|
||||
const char* model;
|
||||
SkydimoLayoutKind layout;
|
||||
unsigned int zone_leds[4];
|
||||
unsigned int total_leds;
|
||||
unsigned int max_leds;
|
||||
};
|
||||
|
||||
static const SkydimoModelEntry skydimo_model_entries[] =
|
||||
{
|
||||
{ "SK0121", SKYDIMO_LAYOUT_PERIMETER_3, { 13, 25, 13, 0 }, 51, 0 },
|
||||
{ "SK0124", SKYDIMO_LAYOUT_PERIMETER_3, { 14, 26, 14, 0 }, 54, 0 },
|
||||
{ "SK0127", SKYDIMO_LAYOUT_PERIMETER_3, { 17, 31, 17, 0 }, 65, 0 },
|
||||
{ "SK0132", SKYDIMO_LAYOUT_PERIMETER_3, { 20, 37, 20, 0 }, 77, 0 },
|
||||
{ "SK0134", SKYDIMO_LAYOUT_PERIMETER_3, { 15, 41, 15, 0 }, 71, 0 },
|
||||
{ "SK0149", SKYDIMO_LAYOUT_PERIMETER_3, { 19, 69, 19, 0 }, 107, 0 },
|
||||
{ "SK0201", SKYDIMO_LAYOUT_SIDES_2, { 20, 20, 0, 0 }, 40, 0 },
|
||||
{ "SK0202", SKYDIMO_LAYOUT_SIDES_2, { 30, 30, 0, 0 }, 60, 0 },
|
||||
{ "SK0204", SKYDIMO_LAYOUT_SIDES_2, { 25, 25, 0, 0 }, 50, 0 },
|
||||
{ "SK0402", SKYDIMO_LAYOUT_STRIP_1, { 72, 0, 0, 0 }, 72, 0 },
|
||||
{ "SK0403", SKYDIMO_LAYOUT_STRIP_1, { 96, 0, 0, 0 }, 96, 0 },
|
||||
{ "SK0404", SKYDIMO_LAYOUT_STRIP_1, { 144, 0, 0, 0 }, 144, 0 },
|
||||
{ "SK0410", SKYDIMO_LAYOUT_NONE, { 0, 0, 0, 0 }, 0, 300 },
|
||||
{ "SK0801", SKYDIMO_LAYOUT_STRIP_1, { 2, 0, 0, 0 }, 2, 0 },
|
||||
{ "SK0802", SKYDIMO_LAYOUT_STRIP_1, { 18, 0, 0, 0 }, 18, 0 },
|
||||
{ "SK0803", SKYDIMO_LAYOUT_STRIP_1, { 10, 0, 0, 0 }, 10, 0 },
|
||||
{ "SK0901", SKYDIMO_LAYOUT_STRIP_1, { 14, 0, 0, 0 }, 14, 0 },
|
||||
{ "SK0E01", SKYDIMO_LAYOUT_STRIP_1, { 16, 0, 0, 0 }, 16, 0 },
|
||||
{ "SK0F01", SKYDIMO_LAYOUT_SIDES_2, { 29, 29, 0, 0 }, 58, 0 },
|
||||
{ "SK0F02", SKYDIMO_LAYOUT_SIDES_2, { 25, 25, 0, 0 }, 50, 0 },
|
||||
{ "SK0H01", SKYDIMO_LAYOUT_STRIP_1, { 2, 0, 0, 0 }, 2, 0 },
|
||||
{ "SK0H02", SKYDIMO_LAYOUT_STRIP_1, { 4, 0, 0, 0 }, 4, 0 },
|
||||
{ "SK0K01", SKYDIMO_LAYOUT_STRIP_1, { 120, 0, 0, 0 }, 120, 0 },
|
||||
{ "SK0K02", SKYDIMO_LAYOUT_STRIP_1, { 15, 0, 0, 0 }, 15, 0 },
|
||||
{ "SK0L21", SKYDIMO_LAYOUT_PERIMETER_4, { 13, 25, 13, 25 }, 76, 0 },
|
||||
{ "SK0L24", SKYDIMO_LAYOUT_PERIMETER_4, { 14, 26, 14, 26 }, 80, 0 },
|
||||
{ "SK0L27", SKYDIMO_LAYOUT_PERIMETER_4, { 17, 31, 17, 31 }, 96, 0 },
|
||||
{ "SK0L32", SKYDIMO_LAYOUT_PERIMETER_4, { 20, 37, 20, 37 }, 114, 0 },
|
||||
{ "SK0L34", SKYDIMO_LAYOUT_PERIMETER_4, { 15, 41, 15, 41 }, 112, 0 },
|
||||
{ "SK0M01", SKYDIMO_LAYOUT_STRIP_1, { 24, 0, 0, 0 }, 24, 0 },
|
||||
{ "SK0N01", SKYDIMO_LAYOUT_STRIP_1, { 256, 0, 0, 0 }, 256, 0 },
|
||||
{ "SK0N02", SKYDIMO_LAYOUT_STRIP_1, { 1024, 0, 0, 0 }, 1024, 0 },
|
||||
{ "SK0N03", SKYDIMO_LAYOUT_STRIP_1, { 253, 0, 0, 0 }, 253, 0 },
|
||||
{ "SK0S01", SKYDIMO_LAYOUT_STRIP_1, { 32, 0, 0, 0 }, 32, 0 },
|
||||
{ "SKA124", SKYDIMO_LAYOUT_PERIMETER_3, { 18, 34, 18, 0 }, 70, 0 },
|
||||
{ "SKA127", SKYDIMO_LAYOUT_PERIMETER_3, { 20, 41, 20, 0 }, 81, 0 },
|
||||
{ "SKA132", SKYDIMO_LAYOUT_PERIMETER_3, { 25, 45, 25, 0 }, 95, 0 },
|
||||
{ "SKA134", SKYDIMO_LAYOUT_PERIMETER_3, { 21, 51, 21, 0 }, 93, 0 },
|
||||
{ "SKB124", SKYDIMO_LAYOUT_PERIMETER_4, { 18, 34, 18, 34 }, 104, 0 },
|
||||
{ "SKB127", SKYDIMO_LAYOUT_PERIMETER_4, { 20, 41, 20, 41 }, 122, 0 },
|
||||
{ "SKB132", SKYDIMO_LAYOUT_PERIMETER_4, { 25, 44, 25, 44 }, 138, 0 },
|
||||
{ "SKB134", SKYDIMO_LAYOUT_PERIMETER_4, { 21, 50, 21, 50 }, 142, 0 }
|
||||
};
|
||||
|
||||
#define SKYDIMO_MODEL_ENTRY_COUNT (sizeof(skydimo_model_entries) / sizeof(skydimo_model_entries[0]))
|
||||
|
||||
static const unsigned char skydimo_serial_frame_header[] =
|
||||
{
|
||||
0x41, 0x64, 0x61, 0x00
|
||||
};
|
||||
|
||||
static std::string StringToUpper(const std::string& value)
|
||||
{
|
||||
std::string result = value;
|
||||
|
||||
for(unsigned int char_idx = 0; char_idx < result.size(); char_idx++)
|
||||
{
|
||||
result[char_idx] = (char)std::toupper((unsigned char)result[char_idx]);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static const SkydimoModelEntry* FindModelEntry(const std::string& model)
|
||||
{
|
||||
for(unsigned int entry_idx = 0; entry_idx < SKYDIMO_MODEL_ENTRY_COUNT; entry_idx++)
|
||||
{
|
||||
if(model == skydimo_model_entries[entry_idx].model)
|
||||
{
|
||||
return(&skydimo_model_entries[entry_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
return(nullptr);
|
||||
}
|
||||
|
||||
static std::string BytesToHex(const std::vector<unsigned char>& bytes, unsigned int offset)
|
||||
{
|
||||
static const char hex[] = "0123456789ABCDEF";
|
||||
std::string result;
|
||||
|
||||
result.reserve((bytes.size() - offset) * 2);
|
||||
|
||||
for(unsigned int byte_idx = offset; byte_idx < bytes.size(); byte_idx++)
|
||||
{
|
||||
result.push_back(hex[(bytes[byte_idx] >> 4) & 0x0F]);
|
||||
result.push_back(hex[bytes[byte_idx] & 0x0F]);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
SkydimoSerialController::SkydimoSerialController(const std::string& port_name_arg)
|
||||
{
|
||||
port_name = port_name_arg;
|
||||
model_name = "Skydimo UNKNOWN";
|
||||
model_id = "UNKNOWN";
|
||||
serial_id = "000000";
|
||||
port_open = serial_port_interface.serial_open(port_name.c_str(), SKYDIMO_SERIAL_BAUD_RATE);
|
||||
present = false;
|
||||
resizable = true;
|
||||
leds_count = SKYDIMO_SERIAL_DEFAULT_LED_COUNT;
|
||||
leds_min = SKYDIMO_SERIAL_DEFAULT_LED_COUNT;
|
||||
leds_max = SKYDIMO_SERIAL_DEFAULT_MAX_LED_COUNT;
|
||||
matrix_width = 0;
|
||||
matrix_height = 0;
|
||||
|
||||
if(!port_open)
|
||||
{
|
||||
LOG_DEBUG("[SkydimoSerialController] Failed to open serial port %s", port_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
SkydimoSerialController::~SkydimoSerialController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool SkydimoSerialController::IsPresent()
|
||||
{
|
||||
if(present)
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
present = QueryInfo();
|
||||
return(present);
|
||||
}
|
||||
|
||||
bool SkydimoSerialController::QueryInfo()
|
||||
{
|
||||
if(!port_open)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
serial_port_interface.serial_flush_rx();
|
||||
|
||||
char query[] = SKYDIMO_SERIAL_QUERY;
|
||||
int bytes_written = serial_port_interface.serial_write(query, SKYDIMO_SERIAL_QUERY_LENGTH);
|
||||
|
||||
if(bytes_written != SKYDIMO_SERIAL_QUERY_LENGTH)
|
||||
{
|
||||
LOG_DEBUG("[SkydimoSerialController] Failed to send identification query to %s (%d/%u bytes)",
|
||||
port_name.c_str(), bytes_written, (unsigned int)SKYDIMO_SERIAL_QUERY_LENGTH);
|
||||
return(false);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> response;
|
||||
|
||||
for(unsigned int attempt = 0; attempt < SKYDIMO_SERIAL_QUERY_ATTEMPTS; attempt++)
|
||||
{
|
||||
char buffer[SKYDIMO_SERIAL_READ_BUFFER_SIZE];
|
||||
int bytes_read = serial_port_interface.serial_read(buffer, SKYDIMO_SERIAL_READ_BUFFER_SIZE);
|
||||
|
||||
if(bytes_read < 0)
|
||||
{
|
||||
LOG_DEBUG("[SkydimoSerialController] Failed to read identification response from %s", port_name.c_str());
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(bytes_read > 0)
|
||||
{
|
||||
response.insert(response.end(), buffer, buffer + bytes_read);
|
||||
}
|
||||
|
||||
if(response.size() >= SKYDIMO_SERIAL_MAX_RESPONSE_SIZE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(!response.empty())
|
||||
{
|
||||
unsigned char last = response[response.size() - 1];
|
||||
unsigned char prev = response.size() >= 2 ? response[response.size() - 2] : 0;
|
||||
|
||||
if((last == '\r') || (last == '\n') || (prev == '\r'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(!response.empty() && ((response.back() == '\r') || (response.back() == '\n')))
|
||||
{
|
||||
response.pop_back();
|
||||
}
|
||||
|
||||
if(response.size() < SKYDIMO_SERIAL_MODEL_ID_LENGTH)
|
||||
{
|
||||
LOG_TRACE("[SkydimoSerialController] No Skydimo identification response from %s", port_name.c_str());
|
||||
return(false);
|
||||
}
|
||||
|
||||
if((std::toupper(response[0]) != 'S') || (std::toupper(response[1]) != 'K'))
|
||||
{
|
||||
LOG_TRACE("[SkydimoSerialController] Ignoring non-Skydimo serial device at %s", port_name.c_str());
|
||||
return(false);
|
||||
}
|
||||
|
||||
model_id = StringToUpper(std::string(response.begin(), response.begin() + SKYDIMO_SERIAL_MODEL_ID_LENGTH));
|
||||
model_name = "Skydimo " + model_id;
|
||||
serial_id = "000000";
|
||||
|
||||
unsigned int comma_offset = (unsigned int)response.size();
|
||||
|
||||
for(unsigned int byte_idx = 0; byte_idx < response.size(); byte_idx++)
|
||||
{
|
||||
if(response[byte_idx] == ',')
|
||||
{
|
||||
comma_offset = byte_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(comma_offset < response.size())
|
||||
{
|
||||
if(comma_offset < SKYDIMO_SERIAL_MODEL_ID_LENGTH)
|
||||
{
|
||||
LOG_DEBUG("[SkydimoSerialController] Invalid identification response from %s", port_name.c_str());
|
||||
return(false);
|
||||
}
|
||||
|
||||
if((comma_offset + 1) < response.size())
|
||||
{
|
||||
serial_id = BytesToHex(response, comma_offset + 1);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigureOutput();
|
||||
return(true);
|
||||
}
|
||||
|
||||
void SkydimoSerialController::ConfigureOutput()
|
||||
{
|
||||
const SkydimoModelEntry* entry = FindModelEntry(model_id);
|
||||
|
||||
resizable = true;
|
||||
leds_count = SKYDIMO_SERIAL_DEFAULT_LED_COUNT;
|
||||
leds_min = SKYDIMO_SERIAL_DEFAULT_LED_COUNT;
|
||||
leds_max = SKYDIMO_SERIAL_DEFAULT_MAX_LED_COUNT;
|
||||
matrix_width = 0;
|
||||
matrix_height = 0;
|
||||
matrix_map.clear();
|
||||
|
||||
if((entry != nullptr) && (entry->max_leds != 0))
|
||||
{
|
||||
leds_max = entry->max_leds;
|
||||
}
|
||||
|
||||
if((entry == nullptr) || (entry->layout == SKYDIMO_LAYOUT_NONE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
resizable = false;
|
||||
leds_count = entry->total_leds;
|
||||
leds_min = entry->total_leds;
|
||||
leds_max = entry->total_leds;
|
||||
|
||||
if(entry->layout == SKYDIMO_LAYOUT_STRIP_1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int zone_1_leds = entry->zone_leds[0];
|
||||
const unsigned int zone_2_leds = entry->zone_leds[1];
|
||||
const unsigned int zone_3_leds = entry->zone_leds[2];
|
||||
const unsigned int zone_4_leds = entry->zone_leds[3];
|
||||
|
||||
if(entry->layout == SKYDIMO_LAYOUT_PERIMETER_4)
|
||||
{
|
||||
matrix_height = std::max(zone_1_leds, zone_3_leds) + 2;
|
||||
matrix_width = std::max(zone_2_leds, zone_4_leds) + 2;
|
||||
}
|
||||
else if(entry->layout == SKYDIMO_LAYOUT_PERIMETER_3)
|
||||
{
|
||||
matrix_height = std::max(zone_1_leds, zone_3_leds) + 1;
|
||||
matrix_width = zone_2_leds + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix_height = std::max(zone_1_leds, zone_2_leds) + 2;
|
||||
matrix_width = std::max(3U, ((16 * matrix_height) + 4) / 9);
|
||||
}
|
||||
|
||||
matrix_map.assign(matrix_width * matrix_height, SKYDIMO_SERIAL_MATRIX_NA);
|
||||
|
||||
unsigned int led_index = 0;
|
||||
|
||||
if(entry->layout == SKYDIMO_LAYOUT_SIDES_2)
|
||||
{
|
||||
unsigned int placed = 0;
|
||||
int y = (int)matrix_height - 2;
|
||||
|
||||
while((placed < zone_1_leds) && (y >= 1))
|
||||
{
|
||||
SetMatrixCell((unsigned int)y, 0, led_index);
|
||||
placed++;
|
||||
y--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int placed = 0;
|
||||
int y = entry->layout == SKYDIMO_LAYOUT_PERIMETER_3 ? (int)matrix_height - 1
|
||||
: (int)matrix_height - 2;
|
||||
|
||||
while((placed < zone_1_leds) && (y >= 1))
|
||||
{
|
||||
SetMatrixCell((unsigned int)y, matrix_width - 1, led_index);
|
||||
placed++;
|
||||
y--;
|
||||
}
|
||||
}
|
||||
|
||||
if((entry->layout == SKYDIMO_LAYOUT_PERIMETER_3) || (entry->layout == SKYDIMO_LAYOUT_PERIMETER_4))
|
||||
{
|
||||
unsigned int placed = 0;
|
||||
int x = (int)matrix_width - 2;
|
||||
|
||||
while((placed < zone_2_leds) && (x >= 1))
|
||||
{
|
||||
SetMatrixCell(0, (unsigned int)x, led_index);
|
||||
placed++;
|
||||
x--;
|
||||
}
|
||||
}
|
||||
else if(entry->layout == SKYDIMO_LAYOUT_SIDES_2)
|
||||
{
|
||||
unsigned int placed = 0;
|
||||
unsigned int y = 1;
|
||||
|
||||
while((placed < zone_2_leds) && (y <= (matrix_height - 2)))
|
||||
{
|
||||
SetMatrixCell(y, matrix_width - 1, led_index);
|
||||
placed++;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int end_y = entry->layout == SKYDIMO_LAYOUT_PERIMETER_3 ? matrix_height - 1 : matrix_height - 2;
|
||||
unsigned int placed = 0;
|
||||
unsigned int y = 1;
|
||||
|
||||
while((placed < zone_3_leds) && (y <= end_y))
|
||||
{
|
||||
SetMatrixCell(y, 0, led_index);
|
||||
placed++;
|
||||
y++;
|
||||
}
|
||||
|
||||
if(entry->layout == SKYDIMO_LAYOUT_PERIMETER_4)
|
||||
{
|
||||
placed = 0;
|
||||
unsigned int x = 1;
|
||||
|
||||
while((placed < zone_4_leds) && (x <= (matrix_width - 2)))
|
||||
{
|
||||
SetMatrixCell(matrix_height - 1, x, led_index);
|
||||
placed++;
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
if(led_index != entry->total_leds)
|
||||
{
|
||||
LOG_ERROR("[SkydimoSerialController] Invalid matrix map for %s (%u/%u LEDs placed)",
|
||||
model_id.c_str(), led_index, entry->total_leds);
|
||||
}
|
||||
}
|
||||
|
||||
void SkydimoSerialController::SetMatrixCell(unsigned int y, unsigned int x, unsigned int& led_index)
|
||||
{
|
||||
if((y < matrix_height) && (x < matrix_width))
|
||||
{
|
||||
matrix_map[(y * matrix_width) + x] = led_index++;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkydimoSerialController::WriteFrame(const std::vector<RGBColor>& colors, unsigned int count)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(device_mutex);
|
||||
|
||||
if(!port_open)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(count > colors.size())
|
||||
{
|
||||
count = (unsigned int)colors.size();
|
||||
}
|
||||
|
||||
std::vector<unsigned char> packet;
|
||||
packet.reserve(sizeof(skydimo_serial_frame_header) + SKYDIMO_SERIAL_FRAME_COUNT_SIZE + (count * SKYDIMO_SERIAL_BYTES_PER_LED));
|
||||
|
||||
for(unsigned int header_idx = 0; header_idx < sizeof(skydimo_serial_frame_header); header_idx++)
|
||||
{
|
||||
packet.push_back(skydimo_serial_frame_header[header_idx]);
|
||||
}
|
||||
|
||||
packet.push_back((unsigned char)((count >> 8) & 0xFF));
|
||||
packet.push_back((unsigned char)(count & 0xFF));
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < count; led_idx++)
|
||||
{
|
||||
packet.push_back(RGBGetRValue(colors[led_idx]));
|
||||
packet.push_back(RGBGetGValue(colors[led_idx]));
|
||||
packet.push_back(RGBGetBValue(colors[led_idx]));
|
||||
}
|
||||
|
||||
int packet_size = (int)packet.size();
|
||||
int total_bytes_written = 0;
|
||||
|
||||
while(total_bytes_written < packet_size)
|
||||
{
|
||||
int bytes_written = serial_port_interface.serial_write((char*)packet.data() + total_bytes_written,
|
||||
packet_size - total_bytes_written);
|
||||
|
||||
if(bytes_written <= 0)
|
||||
{
|
||||
LOG_ERROR("[SkydimoSerialController] Failed to write RGB frame to %s (%d/%d bytes)",
|
||||
port_name.c_str(), total_bytes_written, packet_size);
|
||||
return(false);
|
||||
}
|
||||
|
||||
total_bytes_written += bytes_written;
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void SkydimoSerialController::SetLEDs(const std::vector<RGBColor>& colors)
|
||||
{
|
||||
WriteFrame(colors, leds_count);
|
||||
}
|
||||
|
||||
void SkydimoSerialController::SetBlack()
|
||||
{
|
||||
std::vector<RGBColor> black_colors;
|
||||
|
||||
black_colors.resize(leds_count, ToRGBColor(0, 0, 0));
|
||||
WriteFrame(black_colors, leds_count);
|
||||
}
|
||||
|
||||
void SkydimoSerialController::SetLEDCount(unsigned int led_count)
|
||||
{
|
||||
if(!resizable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if((led_count < leds_min) || (led_count > leds_max))
|
||||
{
|
||||
LOG_WARNING("[SkydimoSerialController] Ignoring invalid LED count %u for %s (valid range %u-%u)",
|
||||
led_count, model_id.c_str(), leds_min, leds_max);
|
||||
return;
|
||||
}
|
||||
|
||||
leds_count = led_count;
|
||||
}
|
||||
|
||||
std::string SkydimoSerialController::GetName() const
|
||||
{
|
||||
return(model_name);
|
||||
}
|
||||
|
||||
std::string SkydimoSerialController::GetSerial() const
|
||||
{
|
||||
return(serial_id);
|
||||
}
|
||||
|
||||
std::string SkydimoSerialController::GetLocation() const
|
||||
{
|
||||
return("Serial: " + port_name);
|
||||
}
|
||||
|
||||
bool SkydimoSerialController::IsResizable() const
|
||||
{
|
||||
return(resizable);
|
||||
}
|
||||
|
||||
unsigned int SkydimoSerialController::GetLEDCount() const
|
||||
{
|
||||
return(leds_count);
|
||||
}
|
||||
|
||||
unsigned int SkydimoSerialController::GetMinLEDCount() const
|
||||
{
|
||||
return(leds_min);
|
||||
}
|
||||
|
||||
unsigned int SkydimoSerialController::GetMaxLEDCount() const
|
||||
{
|
||||
return(leds_max);
|
||||
}
|
||||
|
||||
unsigned int SkydimoSerialController::GetMatrixWidth() const
|
||||
{
|
||||
return(matrix_width);
|
||||
}
|
||||
|
||||
unsigned int SkydimoSerialController::GetMatrixHeight() const
|
||||
{
|
||||
return(matrix_height);
|
||||
}
|
||||
|
||||
const std::vector<unsigned int>& SkydimoSerialController::GetMatrixMap() const
|
||||
{
|
||||
return(matrix_map);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SkydimoSerialController.h |
|
||||
| |
|
||||
| Driver for Skydimo serial devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 30 Jun 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "RGBController.h"
|
||||
#include "serial_port.h"
|
||||
|
||||
#define SKYDIMO_SERIAL_BAUD_RATE 115200
|
||||
#define SKYDIMO_SERIAL_QUERY "Moni-A"
|
||||
#define SKYDIMO_SERIAL_QUERY_LENGTH 6
|
||||
#define SKYDIMO_SERIAL_MODEL_ID_LENGTH 6
|
||||
#define SKYDIMO_SERIAL_READ_BUFFER_SIZE 64
|
||||
#define SKYDIMO_SERIAL_MAX_RESPONSE_SIZE 63
|
||||
#define SKYDIMO_SERIAL_QUERY_ATTEMPTS 10
|
||||
#define SKYDIMO_SERIAL_DEFAULT_LED_COUNT 0
|
||||
#define SKYDIMO_SERIAL_DEFAULT_MAX_LED_COUNT 150
|
||||
#define SKYDIMO_SERIAL_BYTES_PER_LED 3
|
||||
#define SKYDIMO_SERIAL_FRAME_COUNT_SIZE 2
|
||||
#define SKYDIMO_SERIAL_MATRIX_NA 0xFFFFFFFF
|
||||
|
||||
class SkydimoSerialController
|
||||
{
|
||||
public:
|
||||
SkydimoSerialController(const std::string& port_name_arg);
|
||||
~SkydimoSerialController();
|
||||
|
||||
bool IsPresent();
|
||||
|
||||
void SetLEDs(const std::vector<RGBColor>& colors);
|
||||
void SetBlack();
|
||||
void SetLEDCount(unsigned int led_count);
|
||||
|
||||
std::string GetName() const;
|
||||
std::string GetSerial() const;
|
||||
std::string GetLocation() const;
|
||||
|
||||
bool IsResizable() const;
|
||||
unsigned int GetLEDCount() const;
|
||||
unsigned int GetMinLEDCount() const;
|
||||
unsigned int GetMaxLEDCount() const;
|
||||
|
||||
unsigned int GetMatrixWidth() const;
|
||||
unsigned int GetMatrixHeight() const;
|
||||
const std::vector<unsigned int>& GetMatrixMap() const;
|
||||
|
||||
private:
|
||||
bool QueryInfo();
|
||||
void ConfigureOutput();
|
||||
void SetMatrixCell(unsigned int y, unsigned int x, unsigned int& led_index);
|
||||
bool WriteFrame(const std::vector<RGBColor>& colors, unsigned int count);
|
||||
|
||||
std::string port_name;
|
||||
std::string model_name;
|
||||
std::string model_id;
|
||||
std::string serial_id;
|
||||
|
||||
bool port_open;
|
||||
bool present;
|
||||
bool resizable;
|
||||
|
||||
unsigned int leds_count;
|
||||
unsigned int leds_min;
|
||||
unsigned int leds_max;
|
||||
unsigned int matrix_width;
|
||||
unsigned int matrix_height;
|
||||
|
||||
std::vector<unsigned int> matrix_map;
|
||||
serial_port serial_port_interface;
|
||||
std::mutex device_mutex;
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SkydimoSerialControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Skydimo serial devices |
|
||||
| |
|
||||
| Bartholomew Ho <qiangqiang101@hotmail.com> 30 Jun 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <vector>
|
||||
#include "DetectionManager.h"
|
||||
#include "LogManager.h"
|
||||
#include "RGBController_SkydimoSerial.h"
|
||||
#include "SkydimoSerialController.h"
|
||||
#include "find_usb_serial_port.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Skydimo serial vendor and product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define SKYDIMO_SERIAL_VID 0x1A86
|
||||
#define SKYDIMO_SERIAL_PID 0x7523
|
||||
|
||||
DetectedControllers DetectSkydimoSerialControllers()
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
std::vector<std::string> ports = find_usb_serial_port(SKYDIMO_SERIAL_VID, SKYDIMO_SERIAL_PID);
|
||||
|
||||
for(unsigned int port_idx = 0; port_idx < ports.size(); port_idx++)
|
||||
{
|
||||
SkydimoSerialController* controller = new SkydimoSerialController(ports[port_idx]);
|
||||
|
||||
if(controller->IsPresent())
|
||||
{
|
||||
RGBController_SkydimoSerial* rgb_controller = new RGBController_SkydimoSerial(controller);
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
LOG_INFO("[SkydimoSerialControllerDetect] Detected %s at %s",
|
||||
controller->GetName().c_str(), ports[port_idx].c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_DETECTOR("Skydimo Serial", DetectSkydimoSerialControllers);
|
||||
/*---------------------------------------------------------------------------------------------------------*\
|
||||
| Entries for dynamic UDEV rules |
|
||||
| |
|
||||
| DUMMY_DEVICE_DETECTOR("Skydimo Serial", DetectSkydimoSerialControllers, 0x1A86, 0x7523 ) |
|
||||
\*---------------------------------------------------------------------------------------------------------*/
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesMouseController.h"
|
||||
|
||||
#define STEELSERIES_AEORX3_NAME "SteelSeries Aerox 3"
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesMouseController.h"
|
||||
|
||||
#define STEELSERIES_AEROX5_NAME "SteelSeries Aerox 5"
|
||||
|
||||
-1
@@ -11,7 +11,6 @@
|
||||
|
||||
#include "SteelSeriesAeroxWirelessController.h"
|
||||
#include "LogManager.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
|
||||
SteelSeriesAeroxWirelessController::SteelSeriesAeroxWirelessController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name)
|
||||
{
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesMouseController.h"
|
||||
|
||||
#define STEELSERIES_AEROX3_WIRELESS_NAME "SteelSeries Aerox 3 Wireless (2.4 GHz wireless mode)"
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
|
||||
#define STEELSERIES_APEX3_BRIGHTNESS_MIN 0x00
|
||||
#define STEELSERIES_APEX3_HID_TIMEOUT 100
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesApex3Controller.h"
|
||||
|
||||
#define STEELSERIES_8Z_LED_COUNT 8
|
||||
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesApex9Controller.cpp |
|
||||
| |
|
||||
| Driver for SteelSeries Apex 9 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-only |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "SteelSeriesApex9Controller.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
|
||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //40
|
||||
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, //60
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
|
||||
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x64, 0xE0, //80
|
||||
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xF0, 0x31, 0x87,
|
||||
0x88, 0x89, 0x8A, 0x8B, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, //100
|
||||
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
|
||||
0x63 };
|
||||
|
||||
SteelSeriesApex9Controller::SteelSeriesApex9Controller(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController (dev_handle, path, dev_name)
|
||||
{
|
||||
proto_type = type;
|
||||
}
|
||||
|
||||
SteelSeriesApex9Controller::~SteelSeriesApex9Controller()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
void SteelSeriesApex9Controller::SetMode(unsigned char mode /*mode*/, std::vector<RGBColor> /*colors*/ )
|
||||
{
|
||||
unsigned char mode_colors[9];
|
||||
|
||||
active_mode = mode;
|
||||
|
||||
memset(mode_colors, 0x00, sizeof(mode_colors));
|
||||
}
|
||||
|
||||
void SteelSeriesApex9Controller::SetLEDsDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char buf[APEX_9_PACKET_LENGTH];
|
||||
int num_keys = 0;
|
||||
|
||||
num_keys = sizeof(keys) / sizeof(*keys);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up Direct packet |
|
||||
\*-----------------------------------------------------*/
|
||||
buf[0x00] = 0;
|
||||
buf[0x01] = APEX_9_PACKET_ID_DIRECT;
|
||||
buf[0x02] = num_keys;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Fill in color data |
|
||||
\*-----------------------------------------------------*/
|
||||
for(int i = 0; i < num_keys; i++)
|
||||
{
|
||||
buf[(i*4)+3] = keys[i];
|
||||
buf[(i*4)+4] = RGBGetRValue(colors[i]);
|
||||
buf[(i*4)+5] = RGBGetGValue(colors[i]);
|
||||
buf[(i*4)+6] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_send_feature_report(dev, buf, APEX_9_PACKET_LENGTH);
|
||||
|
||||
}
|
||||
|
||||
std::string SteelSeriesApex9Controller::GetSerial()
|
||||
{
|
||||
std::string return_string = "";
|
||||
|
||||
switch(proto_type)
|
||||
{
|
||||
case APEX_9_TKL:
|
||||
return_string = "64847";
|
||||
break;
|
||||
case APEX_9_MINI:
|
||||
return_string = "64837";
|
||||
break;
|
||||
default:
|
||||
return_string = "Apex 9 GetSerial() error";
|
||||
}
|
||||
|
||||
return(return_string);
|
||||
}
|
||||
|
||||
std::string SteelSeriesApex9Controller::GetVersion()
|
||||
{
|
||||
std::string return_string = "Unsupported protocol";
|
||||
|
||||
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
|
||||
int result;
|
||||
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = 0x90;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
|
||||
|
||||
if(result > 0)
|
||||
{
|
||||
std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE);
|
||||
fwver = fwver.substr(2, fwver.size());
|
||||
fwver = fwver.c_str();
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| Find 2 periods in string, if found we can |
|
||||
| form a X.Y.Z revision. |
|
||||
\*---------------------------------------------*/
|
||||
std::size_t majorp = fwver.find('.');
|
||||
if(majorp != std::string::npos)
|
||||
{
|
||||
std::size_t minorp = fwver.find('.', majorp+1);
|
||||
if(minorp != std::string::npos)
|
||||
{
|
||||
std::string major = fwver.substr(0, majorp);
|
||||
std::string minor = fwver.substr(majorp+1, (minorp-majorp-1));
|
||||
std::string build = fwver.substr(minorp+1);
|
||||
return_string = "KBD: " + major + "." + minor + "." + build;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(return_string);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------*\
|
||||
| Private packet sending functions. |
|
||||
\*-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
void SteelSeriesApex9Controller::SelectProfile(unsigned char profile)
|
||||
{
|
||||
unsigned char buf[65];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer, set up packet and send |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
buf[0x00] = 0;
|
||||
buf[0x01] = 0x89;
|
||||
buf[0x02] = profile;
|
||||
hid_send_feature_report(dev, buf, 65);
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesApex9Controller.h |
|
||||
| |
|
||||
| Driver for SteelSeries Apex 9 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-only |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesApexBaseController.h"
|
||||
|
||||
enum
|
||||
{
|
||||
APEX_9_PACKET_ID_DIRECT = 0x40, /* Direct mode */
|
||||
APEX_9_PACKET_LENGTH = 513,
|
||||
};
|
||||
|
||||
class SteelSeriesApex9Controller : public SteelSeriesApexBaseController
|
||||
{
|
||||
public:
|
||||
SteelSeriesApex9Controller(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name);
|
||||
~SteelSeriesApex9Controller();
|
||||
|
||||
void SetMode(unsigned char mode, std::vector<RGBColor> colors);
|
||||
void SetLEDsDirect(std::vector<RGBColor> colors);
|
||||
|
||||
std::string GetSerial() override;
|
||||
std::string GetVersion() override;
|
||||
|
||||
private:
|
||||
void SelectProfile(unsigned char profile);
|
||||
};
|
||||
@@ -37,7 +37,7 @@ std::string SteelSeriesApexBaseController::GetName()
|
||||
/*---------------------------------------------------------*\
|
||||
| Gen 1 Apex Pro stores the unit serial number in firmware. |
|
||||
| The first 5 digits determine the region of the keyboard. |
|
||||
| This is not the case for Gen 3, call to this function |
|
||||
| This is not the case for Gen 2+, calls to this function |
|
||||
| will be ignored. |
|
||||
\*---------------------------------------------------------*/
|
||||
std::string SteelSeriesApexBaseController::GetSerial()
|
||||
@@ -51,7 +51,7 @@ std::string SteelSeriesApexBaseController::GetSerial()
|
||||
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = 0xFF;
|
||||
obuf[0x01] = APEX_GEN1_PACKET_ID_SERIAL;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
|
||||
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
|
||||
@@ -97,8 +97,8 @@ std::string SteelSeriesApexBaseController::GetVersion()
|
||||
if(proto_type == APEX)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Gen 1 & 2 Apex Pro report KBD and LED firmware |
|
||||
| Gen 3 only reports the KBD firmware, ignoring |
|
||||
| Gen 1 Apex Pro reports KBD and LED firmware |
|
||||
| Gen 2+ only reports the KBD firmware, ignoring |
|
||||
| requests to read the LED version |
|
||||
\*-------------------------------------------------*/
|
||||
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
@@ -107,7 +107,7 @@ std::string SteelSeriesApexBaseController::GetVersion()
|
||||
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = 0x90;
|
||||
obuf[0x01] = APEX_PACKET_ID_FIRMWARE;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
|
||||
|
||||
@@ -117,9 +117,9 @@ std::string SteelSeriesApexBaseController::GetVersion()
|
||||
fwver.erase(std::remove(fwver.begin(), fwver.end(), '\0'), fwver.end());
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| Apex Pro Gen 3 needs the first char dropped |
|
||||
| Apex Pro Gen 2+ needs the first char dropped |
|
||||
\*---------------------------------------------*/
|
||||
if(kbd_quirk == APEX_GEN3)
|
||||
if(ibuf[0] == APEX_PACKET_ID_FIRMWARE)
|
||||
{
|
||||
fwver.erase(0,1);
|
||||
}
|
||||
@@ -128,9 +128,9 @@ std::string SteelSeriesApexBaseController::GetVersion()
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Clear and reuse buffer |
|
||||
| Get LED firmware for Gen 1 |
|
||||
\*-------------------------------------------------*/
|
||||
if(kbd_quirk != APEX_GEN3)
|
||||
if(kbd_quirk == APEX_GEN1)
|
||||
{
|
||||
memset(ibuf, 0x00, sizeof(ibuf));
|
||||
obuf[0x02] = 0x01;
|
||||
|
||||
@@ -13,18 +13,23 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
|
||||
#define STEELSERIES_PACKET_IN_SIZE 64
|
||||
#define STEELSERIES_PACKET_OUT_SIZE STEELSERIES_PACKET_IN_SIZE + 1
|
||||
#define STEELSERIES_PACKET_IN_SIZE 64
|
||||
#define STEELSERIES_PACKET_OUT_SIZE STEELSERIES_PACKET_IN_SIZE + 1
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Gen 1: 2019-22 models (all FW) & 2023 FW < 1.19.7 |
|
||||
| Gen 2: 2023 models with FW >= 1.19.7 |
|
||||
| Gen 3: 2025+ and may feature Gen 3 in the name |
|
||||
| Protocol quirk applicability |
|
||||
| |
|
||||
| Gen 1: 2019-22 models with original case design, |
|
||||
| all FW releases. |
|
||||
| Gen 2: '2023' USB-C + Apex 9 series TKL and |
|
||||
| smaller, wired/wireless with pre-prism FW |
|
||||
| Gen 3: All models with Omnipoint 3.0 switches and |
|
||||
| Gen 2 models with prism FW update |
|
||||
\*-------------------------------------------------*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APEX_GEN1 = 0x00,
|
||||
@@ -33,6 +38,28 @@ typedef enum
|
||||
|
||||
} protocol_quirk;
|
||||
|
||||
enum
|
||||
{
|
||||
APEX_MODE_DIRECT,
|
||||
APEX_MODE_ONBOARD,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
APEX_PACKET_LENGTH = 643,
|
||||
APEX_9_PACKET_LENGTH = 513, /* Apex 9 direct report size */
|
||||
APEX_PACKET_ID_PROFILE = 0x89, /* Profile */
|
||||
APEX_PACKET_ID_FIRMWARE = 0x90, /* Firmware version */
|
||||
APEX_GEN1_PACKET_ID_DIRECT = 0x3A, /* Direct mode */
|
||||
APEX_GEN1_PACKET_ID_ONBOARD = 0x3B, /* Onboard mode */
|
||||
APEX_GEN1_PACKET_ID_SERIAL = 0xFF, /* Serial number */
|
||||
APEX_2023_PACKET_ID_DIRECT = 0x40, /* New Wired Direct mode */
|
||||
APEX_2023_PACKET_ID_DIRECT_WIRELESS = 0x61, /* New Wireless Direct mode */
|
||||
APEX_2023_PACKET_ID_INIT = 0x4B, /* New Initialization */
|
||||
APEX_2023_PACKET_ID_ONBOARD = 0x41, /* New Wired onboard mode */
|
||||
APEX_2023_PACKET_ID_REGION = 0xF5, /* Region byte */
|
||||
};
|
||||
|
||||
class SteelSeriesApexBaseController
|
||||
{
|
||||
public:
|
||||
@@ -56,4 +83,6 @@ protected:
|
||||
std::string location;
|
||||
std::string name;
|
||||
protocol_quirk kbd_quirk;
|
||||
unsigned short device_pid;
|
||||
unsigned char reset_cmd;
|
||||
};
|
||||
|
||||
+10
-3
@@ -55,11 +55,18 @@ RGBController_SteelSeriesApex::RGBController_SteelSeriesApex(SteelSeriesApexBase
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0x00;
|
||||
Direct.value = APEX_MODE_DIRECT;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Onboard;
|
||||
Onboard.name = "Onboard";
|
||||
Onboard.value = APEX_MODE_ONBOARD;
|
||||
Onboard.flags = 0;
|
||||
Onboard.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Onboard);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
@@ -97,13 +104,13 @@ void RGBController_SteelSeriesApex::SetupZones()
|
||||
new_zone.matrix_map.width = MATRIX_WIDTH;
|
||||
new_zone.matrix_map.map.resize(MATRIX_HEIGHT * MATRIX_WIDTH);
|
||||
|
||||
if((proto_type == APEX) || (proto_type == APEX_M) || (proto_type == APEX_9_TKL) || (proto_type == APEX_9_MINI))
|
||||
if((proto_type == APEX) || (proto_type == APEX_M))
|
||||
{
|
||||
SetSkuRegion(&new_zone.matrix_map, sku);
|
||||
}
|
||||
}
|
||||
|
||||
if((proto_type == APEX) || (proto_type == APEX_M) || (proto_type == APEX_9_TKL) || (proto_type == APEX_9_MINI))
|
||||
if((proto_type == APEX) || (proto_type == APEX_M))
|
||||
{
|
||||
new_zone.leds_min = zone_sizes[zone_idx];
|
||||
new_zone.leds_max = zone_sizes[zone_idx];
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include <chrono>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesApexBaseController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
|
||||
class RGBController_SteelSeriesApex : public RGBController
|
||||
{
|
||||
|
||||
+193
-174
@@ -20,81 +20,133 @@
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define FIRMWARE_REQ_LEN 645
|
||||
static unsigned int keys[] =
|
||||
{
|
||||
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
|
||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //40
|
||||
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, //60
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
|
||||
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x64, 0xE0, //80
|
||||
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xF0, 0x31, 0x87,
|
||||
0x88, 0x89, 0x8A, 0x8B, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, //100
|
||||
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
|
||||
0x63, 0xFB
|
||||
};
|
||||
|
||||
static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
|
||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //40
|
||||
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, //60
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
|
||||
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x64, 0xE0, //80
|
||||
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xF0, 0x31, 0x87,
|
||||
0x88, 0x89, 0x8A, 0x8B, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, //100
|
||||
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
|
||||
0x63, 0xFB };
|
||||
/*---------------------------------------------------------*\
|
||||
| Models whose direct lighting feature report is shorter |
|
||||
| than APEX_PACKET_LENGTH. Sending the wrong report size |
|
||||
| makes the keyboard stall the control transfer, so any |
|
||||
| model listed here would silently ignore lighting updates |
|
||||
| if the default length were used. |
|
||||
\*---------------------------------------------------------*/
|
||||
inline static const std::map<unsigned short, unsigned int> direct_packet_length_map =
|
||||
{
|
||||
{STEELSERIES_APEX_9_TKL_PID, APEX_9_PACKET_LENGTH},
|
||||
{STEELSERIES_APEX_9_MINI_PID, APEX_9_PACKET_LENGTH},
|
||||
};
|
||||
|
||||
SteelSeriesApexController::SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name)
|
||||
inline static const std::map<unsigned short, protocol_quirk> protocol_map =
|
||||
{
|
||||
{STEELSERIES_APEX_9_TKL_PID, APEX_GEN2},
|
||||
{STEELSERIES_APEX_9_MINI_PID, APEX_GEN2},
|
||||
{STEELSERIES_APEX_PRO_TKL_2023_PID, APEX_GEN2},
|
||||
{STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1, APEX_GEN3},
|
||||
{STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2, APEX_GEN3},
|
||||
{STEELSERIES_APEX_PRO_TKL_GEN3_PID, APEX_GEN3},
|
||||
{STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1, APEX_GEN3},
|
||||
{STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2, APEX_GEN3},
|
||||
};
|
||||
|
||||
SteelSeriesApexController::SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, unsigned short pid, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name)
|
||||
{
|
||||
proto_type = type;
|
||||
kbd_quirk = APEX_GEN1;
|
||||
|
||||
device_pid = pid;
|
||||
direct_packet_length = APEX_PACKET_LENGTH;
|
||||
if(protocol_map.count(device_pid) > 0)
|
||||
{
|
||||
kbd_quirk = protocol_map.at(device_pid);
|
||||
}
|
||||
if(direct_packet_length_map.count(device_pid) > 0)
|
||||
{
|
||||
direct_packet_length = direct_packet_length_map.at(device_pid);
|
||||
}
|
||||
SendInitialization();
|
||||
}
|
||||
|
||||
SteelSeriesApexController::~SteelSeriesApexController()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Gen 3 models must be explicitly cleared for on-board |
|
||||
| config selection to apply without power cycling after |
|
||||
| OpenRGB shuts down. |
|
||||
\*-----------------------------------------------------*/
|
||||
if(kbd_quirk == APEX_GEN3)
|
||||
{
|
||||
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = APEX_GEN3_PACKET_CLEAR_LIGHTING;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
}
|
||||
SendDeinitialization();
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
void SteelSeriesApexController::SetMode
|
||||
(
|
||||
unsigned char mode,
|
||||
std::vector<RGBColor> /*colors*/
|
||||
)
|
||||
/*---------------------------------------------------*\
|
||||
| OpenRGB must clear initialized keyboards during |
|
||||
| shutdown as hardware lighting profiles won't apply |
|
||||
| otherwise. Keyboards not needing initialization are |
|
||||
| also cleared, though selecting a hardware profile |
|
||||
| will override the leds unlike the former. |
|
||||
\*---------------------------------------------------*/
|
||||
void SteelSeriesApexController::SendDeinitialization()
|
||||
{
|
||||
unsigned char mode_colors[9];
|
||||
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = reset_cmd;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
}
|
||||
|
||||
void SteelSeriesApexController::SetMode(unsigned char mode, std::vector<RGBColor>)
|
||||
{
|
||||
if(active_mode != mode)
|
||||
{
|
||||
if(active_mode == APEX_MODE_ONBOARD && kbd_quirk != APEX_GEN1)
|
||||
{
|
||||
SendInitialization();
|
||||
}
|
||||
if(mode == APEX_MODE_ONBOARD)
|
||||
{
|
||||
SendDeinitialization();
|
||||
}
|
||||
}
|
||||
active_mode = mode;
|
||||
|
||||
memset(mode_colors, 0x00, sizeof(mode_colors));
|
||||
}
|
||||
|
||||
void SteelSeriesApexController::SetLEDsDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char buf[643];
|
||||
int num_keys = 0;
|
||||
unsigned char buf[APEX_PACKET_LENGTH];
|
||||
int num_keys = sizeof(keys) / sizeof(*keys);
|
||||
unsigned char packet_id = APEX_GEN1_PACKET_ID_DIRECT;
|
||||
|
||||
unsigned char packet_id = APEX_PACKET_ID_DIRECT;
|
||||
/*-----------------------------------------------------*\
|
||||
| Never write past the end of the report or past |
|
||||
| the end of the color vector |
|
||||
\*-----------------------------------------------------*/
|
||||
if((unsigned int)num_keys > colors.size())
|
||||
{
|
||||
num_keys = (int)colors.size();
|
||||
}
|
||||
|
||||
num_keys = sizeof(keys) / sizeof(*keys);
|
||||
if((unsigned int)((num_keys * 4) + 3) > direct_packet_length)
|
||||
{
|
||||
num_keys = (int)((direct_packet_length - 3) / 4);
|
||||
}
|
||||
|
||||
if(kbd_quirk >= APEX_GEN2)
|
||||
{
|
||||
struct hid_device_info* info = hid_get_device_info(dev);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Apparently Gen 3 wireless models reuse this |
|
||||
| protocol, make sure to place their PID here and |
|
||||
| protocol, make sure to place their model here and |
|
||||
| further below when developing. |
|
||||
\*-------------------------------------------------*/
|
||||
if(info && (info->product_id == 0x1630 || info->product_id == 0x1632
|
||||
|| info->product_id == 0x162C || info->product_id == 0x162D
|
||||
|| info->product_id == 0x1644 || info->product_id == 0x1646))
|
||||
if(device_pid == STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1 ||
|
||||
device_pid == STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2 ||
|
||||
device_pid == STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1 ||
|
||||
device_pid == STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2)
|
||||
{
|
||||
packet_id = APEX_2023_PACKET_ID_DIRECT_WIRELESS;
|
||||
}
|
||||
@@ -114,7 +166,7 @@ void SteelSeriesApexController::SetLEDsDirect(std::vector<RGBColor> colors)
|
||||
\*-----------------------------------------------------*/
|
||||
buf[0x00] = 0;
|
||||
buf[0x01] = packet_id;
|
||||
buf[0x02] = kbd_quirk ? (unsigned char)colors.size() : num_keys;
|
||||
buf[0x02] = (unsigned char)num_keys;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Fill in color data |
|
||||
@@ -130,189 +182,156 @@ void SteelSeriesApexController::SetLEDsDirect(std::vector<RGBColor> colors)
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_send_feature_report(dev, buf, 643);
|
||||
int result = hid_send_feature_report(dev, buf, direct_packet_length);
|
||||
|
||||
if(result < 0)
|
||||
{
|
||||
LOG_DEBUG("[%s] Direct lighting update failed, %u byte report", name.c_str(), direct_packet_length);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Private packet sending functions. |
|
||||
\*---------------------------------------------------------*/
|
||||
void SteelSeriesApexController::SelectProfile
|
||||
(
|
||||
unsigned char profile
|
||||
)
|
||||
void SteelSeriesApexController::SelectProfile(unsigned char profile)
|
||||
{
|
||||
unsigned char buf[65];
|
||||
unsigned char buf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer, set up packet and send |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
buf[0x00] = 0;
|
||||
buf[0x01] = 0x89;
|
||||
buf[0x01] = APEX_PACKET_ID_PROFILE;
|
||||
buf[0x02] = profile;
|
||||
hid_send_feature_report(dev, buf, 65);
|
||||
hid_send_feature_report(dev, buf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
}
|
||||
|
||||
void SteelSeriesApexController::SendInitialization()
|
||||
{
|
||||
unsigned char buf[FIRMWARE_REQ_LEN];
|
||||
unsigned char read_buf[65];
|
||||
int res = 0;
|
||||
char version_str[65] = "Unknown";
|
||||
|
||||
struct hid_device_info* info = hid_get_device_info(dev);
|
||||
unsigned short pid = (info) ? info->product_id : 0;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Firmware check for TKL 2023 |
|
||||
\*-----------------------------------------------------*/
|
||||
if(pid == 0x1628)
|
||||
/*---------------------------------------------------*\
|
||||
| Check models which can be Gen 3 via firmware update |
|
||||
\*---------------------------------------------------*/
|
||||
if(device_pid == STEELSERIES_APEX_PRO_TKL_PID ||
|
||||
device_pid == STEELSERIES_APEX_9_TKL_PID ||
|
||||
device_pid == STEELSERIES_APEX_9_MINI_PID)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-------------------------------------------------*/
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
buf[0x00] = 0x00;
|
||||
buf[0x01] = 0x90;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-------------------------------------------------*/
|
||||
hid_write(dev, buf, 65);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Read Response |
|
||||
\*-------------------------------------------------*/
|
||||
memset(read_buf, 0x00, sizeof(read_buf));
|
||||
res = hid_read_timeout(dev, read_buf, sizeof(read_buf), 200);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Firmware Check |
|
||||
\*-------------------------------------------------*/
|
||||
if(res > 2 && read_buf[0] == 0x90)
|
||||
std::string fwver = GetVersion();
|
||||
fwver.erase(0,4);
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
int count = sscanf(fwver.c_str(), "%d.%d.%d", &major, &minor, &patch);
|
||||
if(count == 3)
|
||||
{
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
char* fw_ptr = (char*)&read_buf[2];
|
||||
|
||||
snprintf(version_str, sizeof(version_str), "%s", fw_ptr);
|
||||
|
||||
int count = sscanf(version_str, "%d.%d.%d", &major, &minor, &patch);
|
||||
|
||||
if(count == 3)
|
||||
/*--------------------------------------------*\
|
||||
| Assume Gen 3 protocol from 1.19.7 or newer. |
|
||||
\*--------------------------------------------*/
|
||||
if(major > 1)
|
||||
{
|
||||
/*-----------------------------------------*\
|
||||
| Currently set to 1.19.7 or newer. |
|
||||
\*-----------------------------------------*/
|
||||
if(major > 1)
|
||||
kbd_quirk = APEX_GEN3;
|
||||
}
|
||||
else if(major == 1)
|
||||
{
|
||||
if(minor > 19)
|
||||
{
|
||||
kbd_quirk = APEX_GEN2;
|
||||
kbd_quirk = APEX_GEN3;
|
||||
}
|
||||
else if(major == 1)
|
||||
else if(minor == 19 && patch >= 7)
|
||||
{
|
||||
if(minor > 19)
|
||||
{
|
||||
kbd_quirk = APEX_GEN2;
|
||||
}
|
||||
else if(minor == 19 && patch >= 7)
|
||||
{
|
||||
kbd_quirk = APEX_GEN2;
|
||||
}
|
||||
kbd_quirk = APEX_GEN3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------*\
|
||||
| Apparently Gen 3 models reuse this protocol, make |
|
||||
| sure to place their PID here and further above for |
|
||||
| wireless when developing. |
|
||||
\*-----------------------------------------------------*/
|
||||
else if(pid == 0x1630 || pid == 0x1632
|
||||
|| pid == 0x162C || pid == 0x162D
|
||||
|| pid == 0x1642 || pid == 0x1644 || pid == 0x1646)
|
||||
{
|
||||
kbd_quirk = APEX_GEN3;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send Initialization packet on new protocol. |
|
||||
| Send Initialization packet for Gen 3 protocol. This |
|
||||
| seems to be required for some models and not others, |
|
||||
| regardless there is no harm in sending it. |
|
||||
\*-----------------------------------------------------*/
|
||||
if(kbd_quirk >= APEX_GEN2)
|
||||
if(kbd_quirk >= APEX_GEN3)
|
||||
{
|
||||
unsigned char buf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
buf[0x00] = 0x00;
|
||||
buf[0x01] = APEX_2023_PACKET_ID_INIT;
|
||||
hid_send_feature_report(dev, buf, APEX_2023_PACKET_LENGTH);
|
||||
|
||||
LOG_DEBUG("[%s] Using Apex 2023 protocol. FW: %s", name.c_str(), version_str);
|
||||
reset_cmd = APEX_2023_PACKET_ID_ONBOARD;
|
||||
buf[0x00] = 0x00;
|
||||
buf[0x01] = APEX_2023_PACKET_ID_INIT;
|
||||
hid_send_feature_report(dev, buf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
LOG_DEBUG("[%s] Using Apex 2023/Gen3 protocol.", name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("[%s] Using Apex Legacy protocol. FW: %s", name.c_str(), version_str);
|
||||
reset_cmd = APEX_GEN1_PACKET_ID_ONBOARD;
|
||||
LOG_DEBUG("[%s] Using Apex Legacy protocol.", name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string SteelSeriesApexController::GetSerial()
|
||||
{
|
||||
if(kbd_quirk == APEX_GEN1)
|
||||
{
|
||||
return SteelSeriesApexBaseController::GetSerial();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Gen 3 doesn't expose the serial number in |
|
||||
| Gen 2+ doesn't expose the serial number in |
|
||||
| firmware. A region code is instead set by the |
|
||||
| user and subsequently read back. This region code |
|
||||
| is used by all 5 on-board configs. |
|
||||
| For consistency with other Apex keyboards, this |
|
||||
| region code in combination with the PID is mapped |
|
||||
| region code in tandem with the model is mapped |
|
||||
| to an approximate product number as the region |
|
||||
| patch logic from that point is identical. |
|
||||
| The product number used may not be an exact match |
|
||||
| for the keyboard but should reflect the form |
|
||||
| factor, region and RGB layout |
|
||||
\*-------------------------------------------------*/
|
||||
if(kbd_quirk >= APEX_GEN2)
|
||||
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
|
||||
int result;
|
||||
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
|
||||
if(device_pid == STEELSERIES_APEX_PRO_TKL_GEN3_PID)
|
||||
{
|
||||
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
|
||||
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
|
||||
int result;
|
||||
struct hid_device_info* info = hid_get_device_info(dev);
|
||||
unsigned short pid = (info) ? info->product_id : 0;
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = APEX_2023_PACKET_ID_REGION;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
|
||||
|
||||
memset(obuf, 0x00, sizeof(obuf));
|
||||
|
||||
if(pid == 0x1642)
|
||||
if(result > 3 && ibuf[0] == APEX_2023_PACKET_ID_REGION)
|
||||
{
|
||||
obuf[0x00] = 0;
|
||||
obuf[0x01] = 0xF5;
|
||||
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
|
||||
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
|
||||
|
||||
if(result > 3 && ibuf[0] == 0xF5)
|
||||
switch(ibuf[2])
|
||||
{
|
||||
switch(ibuf[2])
|
||||
{
|
||||
case 0x1:
|
||||
return "64740";
|
||||
break;
|
||||
case 0x3:
|
||||
return "64741";
|
||||
break;
|
||||
case 0x4:
|
||||
return "64743";
|
||||
break;
|
||||
case 0x6:
|
||||
return "64744";
|
||||
break;
|
||||
case 0xA:
|
||||
return "64742";
|
||||
break;
|
||||
case 0xD:
|
||||
return "64745";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case 0x1:
|
||||
return "64740";
|
||||
break;
|
||||
case 0x3:
|
||||
return "64741";
|
||||
break;
|
||||
case 0x4:
|
||||
return "64743";
|
||||
break;
|
||||
case 0x6:
|
||||
return "64744";
|
||||
break;
|
||||
case 0xA:
|
||||
return "64742";
|
||||
break;
|
||||
case 0xD:
|
||||
return "64745";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "64865";
|
||||
}
|
||||
|
||||
return SteelSeriesApexBaseController::GetSerial();
|
||||
if(device_pid == STEELSERIES_APEX_9_TKL_PID)
|
||||
{
|
||||
return "64847";
|
||||
}
|
||||
if(device_pid == STEELSERIES_APEX_9_MINI_PID)
|
||||
{
|
||||
return "64837";
|
||||
}
|
||||
return "64865";
|
||||
}
|
||||
|
||||
+9
-29
@@ -1,5 +1,5 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesApexController.cpp |
|
||||
| SteelSeriesApexController.h |
|
||||
| |
|
||||
| Driver for SteelSeries Apex Keyboards |
|
||||
| |
|
||||
@@ -18,42 +18,22 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesApexBaseController.h"
|
||||
|
||||
enum
|
||||
{
|
||||
APEX_PACKET_ID_DIRECT = 0x3a, /* Direct mode */
|
||||
APEX_2023_PACKET_ID_DIRECT = 0x40, /* New Wired Direct mode */
|
||||
APEX_2023_PACKET_ID_DIRECT_WIRELESS = 0x61, /* New Wireless Direct mode */
|
||||
APEX_2023_PACKET_ID_INIT = 0x4B, /* New Initialization */
|
||||
APEX_2023_PACKET_LENGTH = 643,
|
||||
APEX_GEN3_PACKET_CLEAR_LIGHTING = 0x41,
|
||||
};
|
||||
|
||||
class SteelSeriesApexController : public SteelSeriesApexBaseController
|
||||
{
|
||||
public:
|
||||
SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name);
|
||||
SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, unsigned short pid, std::string dev_name);
|
||||
~SteelSeriesApexController();
|
||||
|
||||
void SetMode
|
||||
(
|
||||
unsigned char mode,
|
||||
std::vector<RGBColor> colors
|
||||
);
|
||||
|
||||
void SetLEDsDirect(std::vector<RGBColor> colors);
|
||||
|
||||
void SetMode(unsigned char mode, std::vector<RGBColor> colors) override;
|
||||
void SetLEDsDirect(std::vector<RGBColor> colors) override;
|
||||
std::string GetSerial() override;
|
||||
|
||||
private:
|
||||
void SelectProfile(unsigned char profile);
|
||||
void SendInitialization();
|
||||
void SendDeinitialization();
|
||||
|
||||
void SelectProfile
|
||||
(
|
||||
unsigned char profile
|
||||
);
|
||||
|
||||
void SendInitialization();
|
||||
|
||||
unsigned int direct_packet_length;
|
||||
};
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesApexBaseController.h"
|
||||
|
||||
class SteelSeriesApexMController : public SteelSeriesApexBaseController
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesApex3Controller.h"
|
||||
|
||||
#define STEELSERIES_TZ_LED_COUNT 10
|
||||
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_SteelSeriesArctisNova3.cpp |
|
||||
| |
|
||||
| RGBController for SteelSeries Arctis Nova 3 |
|
||||
| |
|
||||
| Tomasz Gorczyca (eldiablo123) 18 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
#include "RGBController_SteelSeriesArctisNova3.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Steelseries Arctis Nova 3
|
||||
@category Headset
|
||||
@type USB
|
||||
@save :white_check_mark:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectSteelSeriesArctisNova3
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_SteelSeriesArctisNova3::RGBController_SteelSeriesArctisNova3(SteelSeriesArctisNova3Controller* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "SteelSeries";
|
||||
type = DEVICE_TYPE_HEADSET;
|
||||
description = "SteelSeries Arctis Nova 3 Headset Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ARCTIS_NOVA3_MODE_DIRECT;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = ARCTIS_NOVA3_MODE_OFF;
|
||||
Off.flags = 0;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
|
||||
mode Breathe;
|
||||
Breathe.name = "Breathe";
|
||||
Breathe.value = ARCTIS_NOVA3_MODE_BREATHE;
|
||||
Breathe.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
|
||||
Breathe.color_mode = MODE_COLORS_PER_LED;
|
||||
Breathe.speed_min = 1;
|
||||
Breathe.speed_max = 10;
|
||||
Breathe.speed = 9;
|
||||
|
||||
mode ColorShiftRainbow;
|
||||
ColorShiftRainbow.name = "Color Shift - Rainbow";
|
||||
ColorShiftRainbow.value = ARCTIS_NOVA3_MODE_COLORSHIFT_RAINBOW;
|
||||
ColorShiftRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorShiftRainbow.color_mode = MODE_COLORS_NONE;
|
||||
ColorShiftRainbow.speed_min = 1;
|
||||
ColorShiftRainbow.speed_max = 10;
|
||||
ColorShiftRainbow.speed = 6;
|
||||
|
||||
mode ColorShiftOrange;
|
||||
ColorShiftOrange.name = "Color Shift - Heat Orange";
|
||||
ColorShiftOrange.value = ARCTIS_NOVA3_MODE_COLORSHIFT_ORANGE;
|
||||
ColorShiftOrange.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorShiftOrange.color_mode = MODE_COLORS_NONE;
|
||||
ColorShiftOrange.speed_min = 1;
|
||||
ColorShiftOrange.speed_max = 10;
|
||||
ColorShiftOrange.speed = 6;
|
||||
|
||||
mode ColorShiftBlue;
|
||||
ColorShiftBlue.name = "Color Shift - Frost Blue";
|
||||
ColorShiftBlue.value = ARCTIS_NOVA3_MODE_COLORSHIFT_BLUE;
|
||||
ColorShiftBlue.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
|
||||
ColorShiftBlue.color_mode = MODE_COLORS_NONE;
|
||||
ColorShiftBlue.speed_min = 1;
|
||||
ColorShiftBlue.speed_max = 10;
|
||||
ColorShiftBlue.speed = 6;
|
||||
|
||||
modes.push_back(Direct);
|
||||
modes.push_back(Off);
|
||||
modes.push_back(Breathe);
|
||||
modes.push_back(ColorShiftRainbow);
|
||||
modes.push_back(ColorShiftOrange);
|
||||
modes.push_back(ColorShiftBlue);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_SteelSeriesArctisNova3::~RGBController_SteelSeriesArctisNova3()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_SteelSeriesArctisNova3::SetupZones()
|
||||
{
|
||||
zone zone1;
|
||||
zone1.name = "Nova 3";
|
||||
zone1.type = ZONE_TYPE_LINEAR;
|
||||
zone1.leds_min = 2;
|
||||
zone1.leds_max = 2;
|
||||
zone1.leds_count = 2;
|
||||
zones.push_back(zone1);
|
||||
|
||||
led right_led;
|
||||
right_led.name = "Right";
|
||||
leds.push_back(right_led);
|
||||
|
||||
led left_led;
|
||||
left_led.name = "Left";
|
||||
leds.push_back(left_led);
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_SteelSeriesArctisNova3::DeviceUpdateLEDs()
|
||||
{
|
||||
for(unsigned int i = 0; i < leds.size(); i++)
|
||||
{
|
||||
DeviceUpdateSingleLED(i);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_SteelSeriesArctisNova3::DeviceUpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_SteelSeriesArctisNova3::DeviceUpdateSingleLED(int led)
|
||||
{
|
||||
unsigned char zone_id = (unsigned char)led;
|
||||
unsigned char speed = (unsigned char)modes[active_mode].speed;
|
||||
|
||||
switch(modes[active_mode].value)
|
||||
{
|
||||
case ARCTIS_NOVA3_MODE_OFF:
|
||||
controller->SetOff(zone_id);
|
||||
break;
|
||||
|
||||
case ARCTIS_NOVA3_MODE_DIRECT:
|
||||
controller->SetDirect(zone_id, colors[led]);
|
||||
break;
|
||||
|
||||
case ARCTIS_NOVA3_MODE_BREATHE:
|
||||
controller->SetBreathe(zone_id, colors[led], speed);
|
||||
break;
|
||||
|
||||
case ARCTIS_NOVA3_MODE_COLORSHIFT_RAINBOW:
|
||||
controller->SetColorShiftRainbow(zone_id, speed);
|
||||
break;
|
||||
|
||||
case ARCTIS_NOVA3_MODE_COLORSHIFT_ORANGE:
|
||||
controller->SetColorShiftOrange(zone_id, speed);
|
||||
break;
|
||||
|
||||
case ARCTIS_NOVA3_MODE_COLORSHIFT_BLUE:
|
||||
controller->SetColorShiftBlue(zone_id, speed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_SteelSeriesArctisNova3::DeviceUpdateMode()
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_SteelSeriesArctisNova3::DeviceSaveMode()
|
||||
{
|
||||
controller->Save(0);
|
||||
controller->Save(1);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_SteelSeriesArctisNova3.h |
|
||||
| |
|
||||
| RGBController for SteelSeries Arctis Nova 3 |
|
||||
| |
|
||||
| Tomasz Gorczyca (eldiablo123) 18 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "SteelSeriesArctisNova3Controller.h"
|
||||
|
||||
class RGBController_SteelSeriesArctisNova3 : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_SteelSeriesArctisNova3(SteelSeriesArctisNova3Controller* controller_ptr);
|
||||
~RGBController_SteelSeriesArctisNova3();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void DeviceUpdateZoneLEDs(int zone);
|
||||
void DeviceUpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
void DeviceSaveMode();
|
||||
|
||||
private:
|
||||
SteelSeriesArctisNova3Controller* controller;
|
||||
};
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesArctisNova3Controller.cpp |
|
||||
| |
|
||||
| Driver for SteelSeries Arctis Nova 3 |
|
||||
| |
|
||||
| Tomasz Gorczyca (eldiablo123) 18 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include "SteelSeriesArctisNova3Controller.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
SteelSeriesArctisNova3Controller::SteelSeriesArctisNova3Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
SteelSeriesArctisNova3Controller::~SteelSeriesArctisNova3Controller()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string SteelSeriesArctisNova3Controller::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string SteelSeriesArctisNova3Controller::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string SteelSeriesArctisNova3Controller::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 SteelSeriesArctisNova3Controller::SetSpeedBytes(unsigned char* usb_buf, unsigned char speed)
|
||||
{
|
||||
switch(speed)
|
||||
{
|
||||
case 1: usb_buf[0x0D] = 0x30; usb_buf[0x0E] = 0x75; break;
|
||||
case 2: usb_buf[0x0D] = 0x2E; usb_buf[0x0E] = 0x68; break;
|
||||
case 3: usb_buf[0x0D] = 0x2C; usb_buf[0x0E] = 0x5B; break;
|
||||
case 4: usb_buf[0x0D] = 0x20; usb_buf[0x0E] = 0x4E; break;
|
||||
case 5: usb_buf[0x0D] = 0x1E; usb_buf[0x0E] = 0x41; break;
|
||||
case 6: usb_buf[0x0D] = 0x1C; usb_buf[0x0E] = 0x34; break;
|
||||
case 7: usb_buf[0x0D] = 0x1A; usb_buf[0x0E] = 0x27; break;
|
||||
case 8: usb_buf[0x0D] = 0x0E; usb_buf[0x0E] = 0x1A; break;
|
||||
case 9: usb_buf[0x0D] = 0x0C; usb_buf[0x0E] = 0x0D; break;
|
||||
case 10: usb_buf[0x0D] = 0x94; usb_buf[0x0E] = 0x02; break;
|
||||
default: usb_buf[0x0D] = 0x0C; usb_buf[0x0E] = 0x0D; break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Select/enable packet (64 bytes): 06 A5 (01=left/02=right) (00/0A) |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::SelectZone(unsigned char zone_id, unsigned char state)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_APPLY_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_APPLY_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = 0xA5;
|
||||
usb_buf[0x02] = (zone_id == 0) ? 0x02 : 0x01;
|
||||
usb_buf[0x03] = state;
|
||||
|
||||
hid_write(dev, usb_buf, ARCTIS_NOVA3_APPLY_REPORT_SIZE);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Apply packet (64 bytes): 06 (A3=left/09=right) |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::ApplyZone(unsigned char zone_id)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_APPLY_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_APPLY_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = (zone_id == 0) ? 0x09 : 0xA3;
|
||||
|
||||
hid_write(dev, usb_buf, ARCTIS_NOVA3_APPLY_REPORT_SIZE);
|
||||
}
|
||||
|
||||
void SteelSeriesArctisNova3Controller::SendEffectPacket(unsigned char* usb_buf)
|
||||
{
|
||||
hid_write(dev, usb_buf, ARCTIS_NOVA3_REPORT_SIZE);
|
||||
}
|
||||
|
||||
void SteelSeriesArctisNova3Controller::SetOff(unsigned char zone_id)
|
||||
{
|
||||
SelectZone(zone_id, 0x00);
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Save |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::Save(unsigned char zone_id)
|
||||
{
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Single Color / Direct |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::SetDirect(unsigned char zone_id, RGBColor color)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = 0xAA;
|
||||
usb_buf[0x02] = (zone_id == 0) ? 0x01 : 0x00;
|
||||
|
||||
usb_buf[0x0D] = 0x98;
|
||||
usb_buf[0x0E] = 0x3A;
|
||||
|
||||
usb_buf[0x15] = 0x55;
|
||||
usb_buf[0x17] = 0x96;
|
||||
|
||||
usb_buf[0x1D] = 0x01;
|
||||
|
||||
usb_buf[0x25] = 0x02;
|
||||
|
||||
usb_buf[0x2D] = RGBGetRValue(color);
|
||||
usb_buf[0x2E] = RGBGetGValue(color);
|
||||
usb_buf[0x2F] = RGBGetBValue(color);
|
||||
usb_buf[0x30] = 0xFF;
|
||||
|
||||
SendEffectPacket(usb_buf);
|
||||
|
||||
SelectZone(zone_id, 0x0A);
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Breathe |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::SetBreathe(unsigned char zone_id, RGBColor color, unsigned char speed)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = 0xAA;
|
||||
usb_buf[0x02] = (zone_id == 0) ? 0x01 : 0x00;
|
||||
|
||||
SetSpeedBytes(usb_buf, speed);
|
||||
|
||||
usb_buf[0x15] = 0x55;
|
||||
usb_buf[0x17] = 0x96;
|
||||
|
||||
usb_buf[0x25] = 0x03;
|
||||
|
||||
usb_buf[0x29] = RGBGetRValue(color);
|
||||
usb_buf[0x2A] = RGBGetGValue(color);
|
||||
usb_buf[0x2B] = RGBGetBValue(color);
|
||||
|
||||
usb_buf[0x30] = 0x7F;
|
||||
usb_buf[0x31] = RGBGetRValue(color);
|
||||
usb_buf[0x32] = RGBGetGValue(color);
|
||||
usb_buf[0x33] = RGBGetBValue(color);
|
||||
usb_buf[0x34] = 0x7F;
|
||||
|
||||
SendEffectPacket(usb_buf);
|
||||
|
||||
SelectZone(zone_id, 0x0A);
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Color Shift - Rainbow |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::SetColorShiftRainbow(unsigned char zone_id, unsigned char speed)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = 0xAA;
|
||||
usb_buf[0x02] = (zone_id == 0) ? 0x01 : 0x00;
|
||||
|
||||
SetSpeedBytes(usb_buf, speed);
|
||||
|
||||
usb_buf[0x15] = 0x55;
|
||||
usb_buf[0x17] = 0x96;
|
||||
|
||||
usb_buf[0x25] = 0x07;
|
||||
|
||||
static const unsigned char rainbow_stops[] =
|
||||
{
|
||||
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00,
|
||||
0x2B, 0x00, 0xFF, 0x00, 0x2B, 0x00, 0xFF, 0xFF, 0x2B, 0x00,
|
||||
0x00, 0xFF, 0x2B, 0xFF, 0x00, 0xFF, 0x2B, 0xFF, 0x00, 0x00,
|
||||
0x26
|
||||
};
|
||||
|
||||
memcpy(&usb_buf[0x26], rainbow_stops, sizeof(rainbow_stops));
|
||||
|
||||
SendEffectPacket(usb_buf);
|
||||
|
||||
SelectZone(zone_id, 0x0A);
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Color Shift - Heat Orange |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::SetColorShiftOrange(unsigned char zone_id, unsigned char speed)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = 0xAA;
|
||||
usb_buf[0x02] = (zone_id == 0) ? 0x01 : 0x00;
|
||||
|
||||
SetSpeedBytes(usb_buf, speed);
|
||||
|
||||
usb_buf[0x15] = 0x55;
|
||||
usb_buf[0x17] = 0x96;
|
||||
|
||||
usb_buf[0x25] = 0x03;
|
||||
|
||||
static const unsigned char orange_stops[] =
|
||||
{
|
||||
0xFF, 0xEA, 0x00, 0xFF, 0xEA, 0x00, 0x00, 0xFF, 0x4D, 0x00,
|
||||
0x7F, 0xFF, 0xEA, 0x00, 0x7F
|
||||
};
|
||||
|
||||
memcpy(&usb_buf[0x26], orange_stops, sizeof(orange_stops));
|
||||
|
||||
SendEffectPacket(usb_buf);
|
||||
|
||||
SelectZone(zone_id, 0x0A);
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| Color Shift - Frost Blue |
|
||||
\*---------------------------------------------------------------------*/
|
||||
void SteelSeriesArctisNova3Controller::SetColorShiftBlue(unsigned char zone_id, unsigned char speed)
|
||||
{
|
||||
unsigned char usb_buf[ARCTIS_NOVA3_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ARCTIS_NOVA3_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ARCTIS_NOVA3_REPORT_ID;
|
||||
usb_buf[0x01] = 0xAA;
|
||||
usb_buf[0x02] = (zone_id == 0) ? 0x01 : 0x00;
|
||||
|
||||
SetSpeedBytes(usb_buf, speed);
|
||||
|
||||
usb_buf[0x15] = 0x55;
|
||||
usb_buf[0x17] = 0x96;
|
||||
|
||||
usb_buf[0x25] = 0x03;
|
||||
|
||||
static const unsigned char blue_stops[] =
|
||||
{
|
||||
0x8C, 0x00, 0xFF, 0x8C, 0x00, 0xFF, 0x00, 0x3B, 0xD1, 0xFF,
|
||||
0x7F, 0x8C, 0x00, 0xFF, 0x7F
|
||||
};
|
||||
|
||||
memcpy(&usb_buf[0x26], blue_stops, sizeof(blue_stops));
|
||||
|
||||
SendEffectPacket(usb_buf);
|
||||
|
||||
SelectZone(zone_id, 0x0A);
|
||||
ApplyZone(zone_id);
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesArctisNova3Controller.h |
|
||||
| |
|
||||
| Driver for SteelSeries Arctis Nova 3 |
|
||||
| |
|
||||
| Tomasz Gorczyca (eldiablo123) 18 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define ARCTIS_NOVA3_REPORT_SIZE 521
|
||||
#define ARCTIS_NOVA3_APPLY_REPORT_SIZE 64
|
||||
#define ARCTIS_NOVA3_REPORT_ID 0x06
|
||||
|
||||
enum
|
||||
{
|
||||
ARCTIS_NOVA3_MODE_OFF = 0x00,
|
||||
ARCTIS_NOVA3_MODE_DIRECT = 0x01,
|
||||
ARCTIS_NOVA3_MODE_BREATHE = 0x02,
|
||||
ARCTIS_NOVA3_MODE_COLORSHIFT_RAINBOW = 0x03,
|
||||
ARCTIS_NOVA3_MODE_COLORSHIFT_ORANGE = 0x04,
|
||||
ARCTIS_NOVA3_MODE_COLORSHIFT_BLUE = 0x05,
|
||||
};
|
||||
|
||||
class SteelSeriesArctisNova3Controller
|
||||
{
|
||||
public:
|
||||
SteelSeriesArctisNova3Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~SteelSeriesArctisNova3Controller();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SetOff(unsigned char zone_id);
|
||||
void Save(unsigned char zone_id);
|
||||
void SetDirect(unsigned char zone_id, RGBColor color);
|
||||
void SetBreathe(unsigned char zone_id, RGBColor color, unsigned char speed);
|
||||
void SetColorShiftRainbow(unsigned char zone_id, unsigned char speed);
|
||||
void SetColorShiftOrange(unsigned char zone_id, unsigned char speed);
|
||||
void SetColorShiftBlue(unsigned char zone_id, unsigned char speed);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
void SetSpeedBytes(unsigned char* usb_buf, unsigned char speed);
|
||||
void SelectZone(unsigned char zone_id, unsigned char state);
|
||||
void ApplyZone(unsigned char zone_id);
|
||||
void SendEffectPacket(unsigned char* usb_buf);
|
||||
};
|
||||
@@ -9,12 +9,12 @@
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "DetectionManager.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
#include "SteelSeriesAeroxWirelessController.h"
|
||||
#include "SteelSeriesAerox5Controller.h"
|
||||
#include "SteelSeriesArctisNova3Controller.h"
|
||||
#include "SteelSeriesArctis5Controller.h"
|
||||
#include "SteelSeriesApex8ZoneController.h"
|
||||
#include "SteelSeriesApex9Controller.h"
|
||||
#include "SteelSeriesApexController.h"
|
||||
#include "SteelSeriesApexMController.h"
|
||||
#include "SteelSeriesApexTZoneController.h"
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "SteelSeriesRival3Controller.h"
|
||||
#include "SteelSeriesSenseiController.h"
|
||||
#include "SteelSeriesSiberiaController.h"
|
||||
#include "RGBController_SteelSeriesArctisNova3.h"
|
||||
#include "RGBController_SteelSeriesArctis5.h"
|
||||
#include "RGBController_SteelSeriesApex.h"
|
||||
#include "RGBController_SteelSeriesApex3.h"
|
||||
@@ -34,99 +35,7 @@
|
||||
#include "RGBController_SteelSeriesSensei.h"
|
||||
#include "RGBController_SteelSeriesSiberia.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_VID 0x1038
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Mouse product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_AEROX_3_PID 0x1836
|
||||
#define STEELSERIES_AEROX_3_WIRELESS_PID 0x1838
|
||||
#define STEELSERIES_AEROX_3_WIRELESS_WIRED_PID 0x183A
|
||||
#define STEELSERIES_AEROX_3_CS2_WIRELESS_PID 0x1878
|
||||
#define STEELSERIES_AEROX_3_CS2_WIRELESS_WIRED_PID 0x187A
|
||||
#define STEELSERIES_AEROX_5_WIRELESS_PID 0x1852
|
||||
#define STEELSERIES_AEROX_5_WIRELESS_WIRED_PID 0x1854
|
||||
#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_PID 0x185C
|
||||
#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_WIRED_PID 0x185E
|
||||
#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_PID 0x1860
|
||||
#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_WIRED_PID 0x1862
|
||||
#define STEELSERIES_AEROX_9_WIRELESS_PID 0x1858
|
||||
#define STEELSERIES_AEROX_9_WIRELESS_WIRED_PID 0x185A
|
||||
#define STEELSERIES_AEROX_5_PID 0x1850
|
||||
#define STEELSERIES_AEROX_9_PID 0x185A
|
||||
#define STEELSERIES_RIVAL_100_PID 0x1702
|
||||
#define STEELSERIES_RIVAL_100_DOTA_PID 0x170C
|
||||
#define STEELSERIES_RIVAL_105_PID 0x1814
|
||||
#define STEELSERIES_RIVAL_106_PID 0x1816
|
||||
#define STEELSERIES_RIVAL_110_PID 0x1729
|
||||
#define STEELSERIES_RIVAL_300_PID 0x1710
|
||||
#define ACER_PREDATOR_RIVAL_300_PID 0x1714
|
||||
#define STEELSERIES_RIVAL_300_CSGO_PID 0x1394
|
||||
#define STEELSERIES_RIVAL_300_CSGO_STM32_PID 0x1716
|
||||
#define STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID 0x171A
|
||||
#define STEELSERIES_RIVAL_300_DOTA_PID 0x1392
|
||||
#define STEELSERIES_RIVAL_300_HP_PID 0x1718
|
||||
#define STEELSERIES_RIVAL_300_BLACKOPS_PID 0x1710
|
||||
#define STEELSERIES_RIVAL_310_PID 0x1720
|
||||
#define STEELSERIES_RIVAL_310_CSGO_HOWL_PID 0x171E
|
||||
#define STEELSERIES_RIVAL_310_PUBG_PID 0x1736
|
||||
#define STEELSERIES_RIVAL_600_PID 0x1724
|
||||
#define STEELSERIES_RIVAL_600_DOTA_2_PID 0x172E
|
||||
#define STEELSERIES_RIVAL_650_PID 0x172B
|
||||
#define STEELSERIES_RIVAL_650_WIRELESS_PID 0x1726
|
||||
#define STEELSERIES_RIVAL_700_PID 0x1700
|
||||
#define STEELSERIES_RIVAL_710_PID 0x1730
|
||||
#define STEELSERIES_RIVAL_3_OLD_PID 0x1824
|
||||
#define STEELSERIES_RIVAL_3_PID 0x184C
|
||||
#define STEELSERIES_SENSEI_TEN_PID 0x1832
|
||||
#define STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID 0x1834
|
||||
#define STEELSERIES_SENSEI_310_PID 0x1722
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Headset product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_SIBERIA_350_PID 0x1229
|
||||
#define STEELSERIES_ARCTIS_5_PID 0x1250
|
||||
#define STEELSERIES_ARCTIS_5_V2_PID 0x12AA
|
||||
|
||||
/*--------------------------------------------------------------------*\
|
||||
| Mousemat product IDs |
|
||||
\*--------------------------------------------------------------------*/
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_MED_PID 0x150A
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_PID 0x150D
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID 0x151E
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID 0x1514
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEO_NOIR_PID 0x151C
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_3XL_PID 0x1516
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_4XL_PID 0x1518
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_5XL_PID 0x151A
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_2_LIGHTFALL_ED_PID 0x1520
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_APEX_3_PID 0x161A
|
||||
#define STEELSERIES_APEX_3_TKL_PID 0x1622
|
||||
#define STEELSERIES_APEX_5_PID 0x161C
|
||||
#define STEELSERIES_APEX_7_PID 0x1612
|
||||
#define STEELSERIES_APEX_7_TKL_PID 0x1618
|
||||
#define STEELSERIES_APEX_9_TKL_PID 0x1634
|
||||
#define STEELSERIES_APEX_9_MINI_PID 0x1620
|
||||
#define STEELSERIES_APEX_PRO_PID 0x1610
|
||||
#define STEELSERIES_APEX_PRO_TKL_PID 0x1614
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_PID 0x1628
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1 0x1630
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2 0x1632
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_PID 0x1642
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1 0x1644
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2 0x1646
|
||||
#define STEELSERIES_APEX_M750_PID 0x0616
|
||||
#define STEELSERIES_APEX_OG_PID 0x1202
|
||||
#define STEELSERIES_APEX_350_PID 0x1206
|
||||
#define STEELSERIES_APEX_PRO3_PID 0x1640
|
||||
|
||||
DetectedControllers DetectSteelSeriesAerox3(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
@@ -277,7 +186,7 @@ DetectedControllers DetectSteelSeriesApex(hid_device_info* info, const std::stri
|
||||
|
||||
if(dev)
|
||||
{
|
||||
SteelSeriesApexController* controller = new SteelSeriesApexController(dev, APEX, info->path, name);
|
||||
SteelSeriesApexController* controller = new SteelSeriesApexController(dev, APEX, info->path, info->product_id, name);
|
||||
RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
@@ -286,34 +195,6 @@ DetectedControllers DetectSteelSeriesApex(hid_device_info* info, const std::stri
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectSteelSeriesApex9(hid_device_info* info, const std::string& name, steelseries_type proto_type)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
SteelSeriesApex9Controller* controller = new SteelSeriesApex9Controller(dev, proto_type, info->path, name);
|
||||
RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectSteelSeriesApex9TKL(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
return(DetectSteelSeriesApex9(info, name, APEX_9_TKL));
|
||||
}
|
||||
|
||||
DetectedControllers DetectSteelSeriesApex9Mini(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
return(DetectSteelSeriesApex9(info, name, APEX_9_MINI));
|
||||
}
|
||||
|
||||
DetectedControllers DetectSteelSeriesApexM(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
@@ -513,6 +394,24 @@ DetectedControllers DetectSteelSeriesSensei(hid_device_info* info, const std::st
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectSteelSeriesArctisNova3(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
hid_device* dev;
|
||||
|
||||
dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
SteelSeriesArctisNova3Controller* controller = new SteelSeriesArctisNova3Controller(dev, *info, name);
|
||||
RGBController_SteelSeriesArctisNova3* rgb_controller = new RGBController_SteelSeriesArctisNova3(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
DetectedControllers DetectSteelSeriesArctis5(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
@@ -580,6 +479,7 @@ REGISTER_HID_DETECTOR_I("SteelSeries Sensei 310",
|
||||
| Headsets |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_I("SteelSeries Siberia 350", DetectSteelSeriesHeadset, STEELSERIES_VID, STEELSERIES_SIBERIA_350_PID, 3 );
|
||||
REGISTER_HID_DETECTOR_IPU("SteelSeries Arctis Nova 3", DetectSteelSeriesArctisNova3, STEELSERIES_VID, STEELSERIES_ARCTIS_NOVA_3_PID, 4, 0xFFC0, 1);
|
||||
REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_PID, 5 );
|
||||
REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_V2_PID, 5 );
|
||||
|
||||
@@ -604,8 +504,8 @@ REGISTER_HID_DETECTOR_IPU("SteelSeries Apex 3 TKL", Dete
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 5", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_5_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7 TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_TKL_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 TKL", DetectSteelSeriesApex9TKL, STEELSERIES_VID, STEELSERIES_APEX_9_TKL_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 Mini", DetectSteelSeriesApex9Mini, STEELSERIES_VID, STEELSERIES_APEX_9_MINI_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_9_TKL_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 Mini", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_9_MINI_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_PID, 1 );
|
||||
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL 2023 Wired", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_PID, 1 );
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesDevices.h |
|
||||
| |
|
||||
| Device list for SteelSeries devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Vendor ID |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_VID 0x1038
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Mouse product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_AEROX_3_PID 0x1836
|
||||
#define STEELSERIES_AEROX_3_WIRELESS_PID 0x1838
|
||||
#define STEELSERIES_AEROX_3_WIRELESS_WIRED_PID 0x183A
|
||||
#define STEELSERIES_AEROX_3_CS2_WIRELESS_PID 0x1878
|
||||
#define STEELSERIES_AEROX_3_CS2_WIRELESS_WIRED_PID 0x187A
|
||||
#define STEELSERIES_AEROX_5_WIRELESS_PID 0x1852
|
||||
#define STEELSERIES_AEROX_5_WIRELESS_WIRED_PID 0x1854
|
||||
#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_PID 0x185C
|
||||
#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_WIRED_PID 0x185E
|
||||
#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_PID 0x1860
|
||||
#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_WIRED_PID 0x1862
|
||||
#define STEELSERIES_AEROX_9_WIRELESS_PID 0x1858
|
||||
#define STEELSERIES_AEROX_9_WIRELESS_WIRED_PID 0x185A
|
||||
#define STEELSERIES_AEROX_5_PID 0x1850
|
||||
#define STEELSERIES_AEROX_9_PID 0x185A
|
||||
#define STEELSERIES_RIVAL_100_PID 0x1702
|
||||
#define STEELSERIES_RIVAL_100_DOTA_PID 0x170C
|
||||
#define STEELSERIES_RIVAL_105_PID 0x1814
|
||||
#define STEELSERIES_RIVAL_106_PID 0x1816
|
||||
#define STEELSERIES_RIVAL_110_PID 0x1729
|
||||
#define STEELSERIES_RIVAL_300_PID 0x1710
|
||||
#define ACER_PREDATOR_RIVAL_300_PID 0x1714
|
||||
#define STEELSERIES_RIVAL_300_CSGO_PID 0x1394
|
||||
#define STEELSERIES_RIVAL_300_CSGO_STM32_PID 0x1716
|
||||
#define STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID 0x171A
|
||||
#define STEELSERIES_RIVAL_300_DOTA_PID 0x1392
|
||||
#define STEELSERIES_RIVAL_300_HP_PID 0x1718
|
||||
#define STEELSERIES_RIVAL_300_BLACKOPS_PID 0x1710
|
||||
#define STEELSERIES_RIVAL_310_PID 0x1720
|
||||
#define STEELSERIES_RIVAL_310_CSGO_HOWL_PID 0x171E
|
||||
#define STEELSERIES_RIVAL_310_PUBG_PID 0x1736
|
||||
#define STEELSERIES_RIVAL_600_PID 0x1724
|
||||
#define STEELSERIES_RIVAL_600_DOTA_2_PID 0x172E
|
||||
#define STEELSERIES_RIVAL_650_PID 0x172B
|
||||
#define STEELSERIES_RIVAL_650_WIRELESS_PID 0x1726
|
||||
#define STEELSERIES_RIVAL_700_PID 0x1700
|
||||
#define STEELSERIES_RIVAL_710_PID 0x1730
|
||||
#define STEELSERIES_RIVAL_3_OLD_PID 0x1824
|
||||
#define STEELSERIES_RIVAL_3_PID 0x184C
|
||||
#define STEELSERIES_SENSEI_TEN_PID 0x1832
|
||||
#define STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID 0x1834
|
||||
#define STEELSERIES_SENSEI_310_PID 0x1722
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Headset product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_SIBERIA_350_PID 0x1229
|
||||
#define STEELSERIES_ARCTIS_NOVA_3_PID 0x12EC
|
||||
#define STEELSERIES_ARCTIS_5_PID 0x1250
|
||||
#define STEELSERIES_ARCTIS_5_V2_PID 0x12AA
|
||||
|
||||
/*--------------------------------------------------------------------*\
|
||||
| Mousemat product IDs |
|
||||
\*--------------------------------------------------------------------*/
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_MED_PID 0x150A
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_PID 0x150D
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID 0x151E
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID 0x1514
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEO_NOIR_PID 0x151C
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_3XL_PID 0x1516
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_4XL_PID 0x1518
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_5XL_PID 0x151A
|
||||
#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_2_LIGHTFALL_ED_PID 0x1520
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Keyboard product IDs |
|
||||
\*---------------------------------------------------------*/
|
||||
#define STEELSERIES_APEX_3_PID 0x161A
|
||||
#define STEELSERIES_APEX_3_TKL_PID 0x1622
|
||||
#define STEELSERIES_APEX_5_PID 0x161C
|
||||
#define STEELSERIES_APEX_7_PID 0x1612
|
||||
#define STEELSERIES_APEX_7_TKL_PID 0x1618
|
||||
#define STEELSERIES_APEX_9_TKL_PID 0x1634
|
||||
#define STEELSERIES_APEX_9_MINI_PID 0x1620
|
||||
#define STEELSERIES_APEX_PRO_PID 0x1610
|
||||
#define STEELSERIES_APEX_PRO_TKL_PID 0x1614
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_PID 0x1628
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1 0x1630
|
||||
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2 0x1632
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_PID 0x1642
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1 0x1644
|
||||
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2 0x1646
|
||||
#define STEELSERIES_APEX_M750_PID 0x0616
|
||||
#define STEELSERIES_APEX_OG_PID 0x1202
|
||||
#define STEELSERIES_APEX_350_PID 0x1206
|
||||
#define STEELSERIES_APEX_PRO3_PID 0x1640
|
||||
|
||||
/*--------------------------------------------------------*\
|
||||
| Allows us to handle variation in the protocol. |
|
||||
| Defined in a single enum so we can keep the device_list |
|
||||
| struct the same for every possible device. |
|
||||
\*--------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
RIVAL_100 = 0x00,
|
||||
RIVAL_300 = 0x01,
|
||||
RIVAL_650 = 0x02,
|
||||
SIBERIA_350 = 0x03,
|
||||
APEX = 0x04,
|
||||
APEX_M = 0x05,
|
||||
APEX_OLD = 0x06,
|
||||
SENSEI = 0x07,
|
||||
RIVAL_600 = 0x08,
|
||||
RIVAL_3 = 0x09,
|
||||
APEX_TZONE = 0x0A,
|
||||
RIVAL_700 = 0x0B,
|
||||
AEROX_3 = 0x0C,
|
||||
APEX_8ZONE = 0x0D,
|
||||
AEROX_3_WIRELESS = 0x0E,
|
||||
AEROX_3_WIRELESS_WIRED = 0x0F,
|
||||
AEROX_5_WIRELESS = 0x10,
|
||||
AEROX_5_WIRELESS_WIRED = 0x11,
|
||||
AEROX_5_DESTINY_WIRELESS = 0x12,
|
||||
AEROX_5_DESTINY_WIRELESS_WIRED = 0x13,
|
||||
AEROX_5_DIABLO_WIRELESS = 0x14,
|
||||
AEROX_5_DIABLO_WIRELESS_WIRED = 0x15,
|
||||
AEROX_9_WIRELESS = 0x16,
|
||||
AEROX_9_WIRELESS_WIRED = 0x17,
|
||||
} steelseries_type;
|
||||
@@ -1,48 +0,0 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| SteelSeriesGeneric.h |
|
||||
| |
|
||||
| Generic file for SteelSeries devices |
|
||||
| |
|
||||
| B Horn (bahorn) 17 May 2020 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
|
||||
/* Allows us to handle variation in the protocol.
|
||||
* Defined in a single enum so we can keep the device_list struct the same
|
||||
* for every possible device. */
|
||||
typedef enum
|
||||
{
|
||||
RIVAL_100 = 0x00,
|
||||
RIVAL_300 = 0x01,
|
||||
RIVAL_650 = 0x02,
|
||||
SIBERIA_350 = 0x03,
|
||||
APEX = 0x04,
|
||||
APEX_M = 0x05,
|
||||
APEX_OLD = 0x06,
|
||||
SENSEI = 0x07,
|
||||
RIVAL_600 = 0x08,
|
||||
RIVAL_3 = 0x09,
|
||||
APEX_TZONE = 0x0A,
|
||||
RIVAL_700 = 0x0B,
|
||||
AEROX_3 = 0x0C,
|
||||
APEX_8ZONE = 0x0D,
|
||||
AEROX_3_WIRELESS = 0x0E,
|
||||
AEROX_3_WIRELESS_WIRED = 0x0F,
|
||||
AEROX_5_WIRELESS = 0x10,
|
||||
AEROX_5_WIRELESS_WIRED = 0x11,
|
||||
AEROX_5_DESTINY_WIRELESS = 0x12,
|
||||
AEROX_5_DESTINY_WIRELESS_WIRED = 0x13,
|
||||
AEROX_5_DIABLO_WIRELESS = 0x14,
|
||||
AEROX_5_DIABLO_WIRELESS_WIRED = 0x15,
|
||||
AEROX_9_WIRELESS = 0x16,
|
||||
AEROX_9_WIRELESS_WIRED = 0x17,
|
||||
APEX_9_TKL = 0x18,
|
||||
APEX_9_MINI = 0x19,
|
||||
} steelseries_type;
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <hidapi.h>
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
|
||||
#define STEELSERIES_MOUSE_BRIGHTNESS_MAX 0x64
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "color32.h"
|
||||
#include "SteelSeriesGeneric.h"
|
||||
#include "SteelSeriesDevices.h"
|
||||
|
||||
/* Mode, we then use these to set actual effect based on speed. */
|
||||
enum
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user