Compare commits

...
Author SHA1 Message Date
Adam Honse 253f74f5bd Add PowerShell implementation of build-msi for building MSI on Windows, add additional information about PawnIO and the OpenRGB system service to the installer. 2026-06-02 21:45:39 -05:00
Adam Honse b03cd94ae8 Fix incorrect firmware packet format and add timeouts to HID reads in ThermaltakeRiingController 2026-06-02 01:07:33 -05:00
Jefferson González bbf348d273 Add HyperX Eve 1800 keyboard support 2026-06-02 00:15:19 -05:00
David Glushkov dce48eb415 Add MSI Raider A18 HX A9WJG SteelSeries RGB 2026-06-02 00:05:18 -05:00
Ox HaK decf14635d Add Fnatic Streak65 support 2026-06-01 08:27:17 -05:00
Richard Harris db4f49bbba Implement Direct mode support for Roccat Vulcan TKL (non-Pro) 2026-05-31 12:38:57 -05:00
HorrorTroll 26824fcb6e Added support for Colorful iGame GeForce RTX 5060 Ultra W OC 2026-05-31 15:12:36 +07:00
Jerry Fan 8afad91b33 Add support for RealtekBridgeController 2026-05-29 07:46:22 -05:00
Adam Honse 69de0b13c4 Update PawnIO modules to 0.2.6 and enable Intel Skylake IMC SMBus module 2026-05-28 23:48:42 -05:00
alstruit 967153bc10 Add support for ASUS ROG Gladius III Core 2026-05-25 12:08:43 -05:00
JAO1988 971d9be1bd Added Colorful iGame RTX 5060TI 16GB Ultra W DUO Variant 2026-05-23 23:10:36 -05:00
Mark Willis 7a3faef886 Initial commit for ASUS TUF GeForce RTX 5070 Ti Gaming White OC 2026-05-22 12:25:59 -05:00
Purrple Kitten f67030fcc7 Add support for the Gigabyte AORUS RTX 5080 MASTER ICE 2026-05-18 07:30:37 -05:00
Alex Jawhari 7353e99449 Fix AMD GPU i2c bus PCI ID detection on Linux (sysfs path traversal) 2026-05-17 23:58:21 -05:00
JAO1988 91d9597c89 Added Support for ASUS ROG ASTRAL GeForce RTX 5080 WHITE 2026-05-17 23:47:55 -05:00
Adam Honse 2eb569912b XPGSummonerKeyboardController - Remove fake modes 2026-05-13 11:49:05 -05:00
Ken Sanislo 9410d9c066 Add support for Thrustmaster Sol series joystick RGB LEDs 2026-05-09 00:21:40 -05:00
Adam Honse 29d8788e25 Allow value 0x27 at address 0x00 for Galax GPU controllers at address 0x23 2026-05-08 20:05:40 -05:00
Elvis Pranskevichus 0304c50bc6 Add support for Gigabyte AORUS RX 7900 XTX ELITE 24G 2026-05-08 00:12:43 -05:00
Adam Honse dd22150cfe Add vertical spacer to OpenRGBDeviceInfoPage 2026-05-07 16:17:46 -05:00
Barry H 07e7feca56 Nollie 2.1 firmware for Master 2026-05-04 14:16:29 -05:00
Sha_425 a93eec8f50 Add ASUS ROG STRIX RTX 3060 Ti V2 LHR (subsystem 1043:8835) 2026-05-03 12:15:13 -05:00
w43322 88bad762e5 add MSI MEG Z890 UNIFY-X (MS-7E20) support 2026-05-02 19:19:10 -05:00
w43322 18dfe6ca8b add ASUS TUF GeForce RTX 5060 Gaming OC support 2026-05-02 19:15:16 -05:00
mangobiche 96dfa7009f Add support for Corsair Vengeance RGB DDR5 CMH32GX5M2E6000C36 2026-05-02 15:06:09 -05:00
NaifuKishi 92a9d8ad11 Initial commit for ASUS TUF Radeon RX 7900 GRE Gaming OC 2026-05-01 11:09:31 -05:00
Francesco P 2ab9094b41 Add support for MSI MAG B850 TOMAHAWK WiFi7 2026-04-29 21:54:51 -05:00
M1dDler Official f6154ccbc4 Add msi rtx 5070 gaming trio 2026-04-28 20:04:53 -05:00
Illustrious-Net-8110 0be01dde19 Add Asus Ryujin AIO Gen1 support 2026-04-24 07:35:53 -05:00
Adam Honse e113e91423 Deploy QOpenGL and QtCore5Compat frameworks used by the OpenRGB Effects Plugin 2026-04-23 23:42:36 -05:00
Adam Honse 28c63b8b9d Call macdeployqt a second time on Qt6 builds to ensure frameworks depended on by default plugins are deployed 2026-04-23 12:37:49 -05:00
Adam Honse c5aac4c44f Fix libsharpyuv macdeployqt error for Qt5 builds 2026-04-23 10:52:54 -05:00
Adam Honse 42e7f2a5c3 Ignore SDK version in Mac build 2026-04-23 03:56:07 -05:00
Adam Honse ae9ae18d31 Add build-macos.sh script for easier MacOS builds 2026-04-23 00:37:45 -05:00
ricarim f89cdac198 Initial commit for HyperX Origins 2 65 2026-04-20 23:32:49 -05:00
acehighdan e8f345ff77 Sync autostart system configuration with OpenRGB settings on startup
If the autostart system configuration is deleted (e.g. by a reinstall or
package manager) but the JSON config still has enabled=true, OpenRGB
would silently fail to start at login. Fix by calling ConfigureAutoStart()
in the settings page constructor so the system configuration is always
reconciled with the stored JSON state every time OpenRGB starts.

Commit amended to make wording more generic by Adam Honse <[email protected]>
2026-04-20 23:32:49 -05:00
Dmitry Kychanov aff0610df9 Fix default language load on start 2026-04-20 23:32:49 -05:00
JAO1988 9199d062d1 Add Support for MSI GeForce RTX 5080 SUPRIM LIQUID SOC 2026-04-20 23:32:49 -05:00
Dmitry Kychanov 0ec4aaa629 Fix losing software info upon changing language 2026-04-20 23:32:49 -05:00
Adam Honse 9fca99b4ef Reduce i2c_smbus_linux PCI log messages from warning to info, they are expected in many cases 2026-04-20 23:32:31 -05:00
Vasily Galkin 14853895f3 Add support for Gigabyte GTX 1050 G1 Gaming 2GB (1458:372B) 2026-04-20 23:32:31 -05:00
Adam Honse d79a400c8c Fix corrupted text in TabLabels when translation occurs after the constructor 2026-04-20 23:32:31 -05:00
Adam Honse f741385e43 Fix bug introduced in MSI controller merge 2026-04-20 23:32:31 -05:00
Adam Honse 840bd92afb Add AI guidelines section to CONTRIBUTING.md 2026-04-20 23:32:31 -05:00
Nameless Monarch 96e1fb0b10 Add support for MSI PRO B850M-VC WIFI6E 2026-04-20 23:32:31 -05:00
Adam Honse 388557e5f9 Ensure device view is initialized if there are no LEDs to avoid accessing out of bounds 2026-04-20 23:32:17 -05:00
Slim Amamou 3f32817272 Added support for PNY GeForce RTX 5060Ti ARGB Epic-X OC 2026-04-20 23:32:10 -05:00
Adam Honse 056b383536 Add SMBus Sleep Mode settings page 2026-04-15 00:29:54 -05:00
Adam Honse 0691f40588 Update PawnIO modules to release 0.2.4 and implement SMBus sleep mode setting 2026-04-15 00:03:38 -05:00
Adam Honse 800ca0aa7c Fix same heap buffer overflow in RGBController_MSIMysticLight761.cpp 2026-04-13 11:42:03 -05:00
kuroki-kael a91679609b Fix heap-buffer-overflow in RGBController_MSIMysticLight185::GetDeviceConfig() 2026-04-13 11:40:46 -05:00
Adam Honse 19f9408990 Fix remaining warning 2026-04-13 11:34:28 -05:00
Adam Honse 0eea0c9aca Fix warnings 2026-04-13 10:54:34 -05:00
Stella 9f95aa8271 Add support for colorful igame rtx 5070 ultraw ocv 2 2026-04-11 02:24:15 -05:00
Adam Honse 0ee04c497b Revert "Change test in ENE SMBus controller to fix a conflict where it locks up Corsair DDR5 Light Enhancement Kit sticks"
This reverts commit c4e0164479.
2026-04-11 01:29:05 -05:00
Adam Honse 2847270c97 Remove out-of-range addresses from ENE RAM address list 2026-04-10 11:52:50 -05:00
Adam Honse b98174afba Fix off-by-one error in CorsairDRAMController 2026-04-10 11:03:34 -05:00
MissingDLL 3416980849 Add MSI MPG B850 EDGE TI WIFI (MS-7E62) to 761 controller 2026-04-09 20:49:35 -05:00
Joseph E c171bfbf3b Apex Pro Gen 3 TKL wired, add media light and regional layout support 2026-04-09 18:11:52 -05:00
Eder Sánchez 583a737cb5 Fix Windows build in ZOTAC Blackwell GPU controller 2026-04-09 15:03:21 -05:00
rjc862003 d2af6289dd Roccat vulcan ii max support 2026-04-09 13:28:33 -05:00
Moh'd Khier Abualruz 44e6f455e9 Fix Apex Pro TKL 2023 Wireless (PIDs 0x1630/0x1632) RGB control 2026-04-09 13:18:38 -05:00
Eder Sánchez b3a50d669e Add support for ZOTAC GAMING GeForce RTX 5080 AMP Extreme INFINITY 2026-04-09 12:21:52 -05:00
ricarim 0092ea22e2 Fix name assignment for HyperXAlloyOrigins60and65 2026-04-09 10:14:06 -05:00
Jérôme Bauer 58fb35a9bb Fix MSI Mystic Light 185 for Common PID boards (0x0DB0:0x0076) 2026-04-09 10:09:55 -05:00
Adam Honse 9a6ff77545 Combine Corsair RAM controllers, Corsair RAM identification packet testing 2026-04-09 00:47:06 -05:00
Adam Honse c4e0164479 Change test in ENE SMBus controller to fix a conflict where it locks up Corsair DDR5 Light Enhancement Kit sticks 2026-04-08 22:24:56 -05:00
Adam Honse f872f1c591 Ignore modes out of range in VialRGB controller 2026-04-08 18:50:47 -05:00
kuroki-kael 03e64da845 Fix heap corruption in i2c_smbus_linux when sysfs files are empty 2026-04-08 15:54:38 -05:00
Frans Meulenbroeks 3150f64895 Mountain Everest 60: fix led index 2026-04-08 09:33:56 -05:00
Hugo Chabert 8b36e9c317 Add razer blackwidow v4 tenkeyless hyperspeed 2026-04-07 07:30:59 -05:00
Stella c5c5fc6c02 Add support for Colorful iGAME RTX 5060Ti 16GB Ultra W DUO V 2026-04-05 03:46:51 -05:00
Artemis Tomaras c7d9992a3d Fix SL V2 SendStartAction/SendCommitAction packet size 2026-04-05 01:52:56 -05:00
InterStella0 0d8f2c6b14 add colorful rtx 5070 ultra w ocv support 2026-04-03 18:22:49 -05:00
vitutu1 c1800f2a6f Add support for MSI RTX 4070 SUPER Gaming X Slim MLG 2026-04-03 16:46:23 +00:00
Micael Pereira d41a115a07 Add support for MSI PRO A620M-B (MS-7E28) 2026-04-03 01:31:28 -05:00
Elijah Mock 2640a3b93f Update docstring detector to match registered detector 2026-03-26 21:50:02 -05:00
Adam Honse 984c18cb11 Add Gigabyte 9070XT GAMING OC ICE 2026-03-23 16:44:30 -05:00
Adam Honse 23db15dfb9 Add support for E6K5-1114 ENE device 2026-03-23 11:46:04 -05:00
Org van Rensburg 9426f954b0 Add support for MSI MAG Z890 Tomahawk WIFI (MS-7E32) - Resolves #5438 2026-03-23 07:24:22 -05:00
asheriif 133b64778b Add support for Apex Pro TKL Gen 3 Wireless 2026-03-22 22:19:37 +01:00
Aakrisht Sharma Paudel a8a97fa38d Legion 5 gen10 2026-03-17 07:50:23 -05:00
Roy Biggins da6061bbde Add X570 AORUS XTREME zone mapping for IT8297BX 2026-03-16 10:29:38 -05:00
asheriif dfad607697 Add support for Steel Series CS2 Dragon Lore Edition 2026-03-10 21:58:47 +01:00
Yaroslav Syrytsia 5d7565bc59 Controllers/Razer: add initial support for Razer Basilisk V3 Pro 35K Phantom Green Edition 2026-03-08 23:28:27 -05:00
Anton Klimanov ab962ca98f Add support for Gigabyte Radeon RX 7900 XTX GAMING OC 24G (1458:240e) 2026-03-09 01:36:27 +03:00
Adam Honse dbbf9858f8 Fix warnings in CMARGBController 2026-03-04 22:23:20 -06:00
Adam Honse 51edb35e3f Rework CoolerMaster ARGB controller so that it doesn't create multiple devices and prepare it for per-zone mode support 2026-03-04 11:45:48 -06:00
Adam Honse 81c6ee6270 Replace usages of sprintf with snprintf 2026-03-03 11:29:19 -06:00
Adam Honse 9ad37cc98f Fix logical error from changing type to unsigned 2026-03-03 11:25:22 -06:00
Adam Honse c76864dd4b Warning fixes and cleanups 2026-03-03 11:05:11 -06:00
Marco Martinez e3889508c0 Add support for another Airgoo Fan + DRGB Controller variant 2026-03-03 07:37:45 -06:00
Adam Honse 22d908b9a3 Fix warnings in ClevoLightbarController.cpp 2026-03-02 23:18:40 -06:00
Adam Honse 13d3e09f1a Fix warnings in ClevoKeyboardController.cpp 2026-03-02 23:17:23 -06:00
Adam Honse 9ec15673d1 Fix warnings in AsusMonitorController.cpp 2026-03-02 23:15:36 -06:00
Adam Honse 3a00a803e9 Fix warnings in LianLiUniHubSLController 2026-03-02 23:08:51 -06:00
Adam Honse 4a12a0db90 Fix warnings in LianLiUniversalScreenController 2026-03-02 23:07:12 -06:00
Adam Honse b4940e3a75 Fix warning in QMKVialRGBController 2026-03-02 23:04:40 -06:00
Adam Honse ffe07bbe3b Fix warning in RazerKrakenV3Controller 2026-03-02 23:03:00 -06:00
Adam Honse 7fdb006465 Fix warning in WootingV1KeyboardController 2026-03-02 23:01:29 -06:00
Adam Honse 99da577c41 Fix warning in SPDAccessor.cpp 2026-03-02 22:54:22 -06:00
Adam Honse 0f6fdd6c3b Fix warnings in HPOmenLaptopWMI_Windows 2026-03-02 22:52:12 -06:00
Adam Honse 52ec58d67f Fix warnings in NVFC nvapi.cpp 2026-03-02 22:44:19 -06:00
Adam Honse c55fc59d18 Clean up and fix warning in SteelSeriesApexController 2026-03-02 18:07:52 -06:00
Adam Honse b68b63e8c9 Fix warning in LianLiUniHubSLController 2026-03-02 16:16:10 -06:00
Kevin Ferrare 84bb05d504 Add support for MSI PRO B850M-P WIFI (MS-7E71) 2026-02-26 22:50:46 +01:00
Frans Meulenbroeks f33a7ba870 Mountain Everest 60: fix initialisation 2026-02-22 17:19:18 -06:00
chetrez911 93830c12ee Add support for MSI MAG B850 TOMAHAWK MAX WIFI (MS-7E62) 2026-02-22 11:56:23 -06:00
Arno b8b50f6651 Initial commit for MSI PRO Z790-S WIFI 2026-02-22 11:40:25 -06:00
sebastien ayanouglou 8f331090f9 Added support to RTX 5070Ti MSI Vanguard 16G 2026-02-16 07:21:32 -06:00
gozzarda 7ec1e8ddfa PowerColor GPU: Accept V1 magic from V2 controller. 2026-02-15 14:05:32 -06:00
Adam Honse 880dc1450d PNY ARGB Epic-X GPU: Add additional modes 2026-02-13 16:27:30 -06:00
Daenney 801e655c09 Add support for MSI MPG X870E EDGE TI WiFi 2026-02-13 13:36:54 -06:00
Adam Honse 5e269dd089 Add support for the PNY Epic-X ARGB 5070, 5080, and 5090 variants 2026-02-13 11:25:42 -06:00
John360Boxer 476f81d5e8 Initial commit for Redragon K686 Eisa Pro 2026-02-09 07:39:40 -06:00
storto 66dfb5f6fd Add/Fix support for the Gigabyte AORUS 5080 MASTER GPU 2026-02-08 12:45:02 -06:00
Michał Przytarski a2f2991192 feat: support MSI GeForce RTX 4060 GAMING X NV Edition 8G 2026-02-07 14:42:15 -06:00
Adam Honse cfedcd2180 Add Razer Blackwidow V4 Pro 75% wireless mode and add missing underglow LEDs to the matrix 2026-02-07 00:14:36 -06:00
Arthur de Groot cc06c62164 Rename Setting RunZoneChecks -> run_zone_checks 2026-02-05 17:20:14 -06:00
bernibaer b4ca000402 Initial support for Corsair K70 CORE TKL Keyboard ID 1b1c:2b01. Volume knob... 2026-01-30 13:49:48 -06:00
eriosgamer b78a6f4418 Fixed incorrect PID and device name. 2026-01-29 20:18:55 -06:00
Kirill Khakimov d5693b7a08 Add PCI device ID for Palit GeForce RTX 5070 Ti GamingPro-S 2026-01-29 16:54:41 -06:00
Werner Sembach cae0670065 Add new keynames 2026-01-29 16:18:13 -06:00
Adam Honse f2d1188fdd Fix swatches not resizing properly when maximized 2026-01-28 18:35:22 -06:00
Yohan 70be81c92d Merge: Add CDC Check in JGINYUE Usb Controller #5128 2026-01-27 10:54:51 -06:00
rszyma 5d5af93401 Add support for MSI PRO X870-P WIFI (MS-7E47) motherboard 2026-01-27 01:30:11 -06:00
superstrom 74cbdcce55 New Device: Razer Kraken Kitty V2 Pro 2026-01-25 17:40:54 -06:00
John Smith 96d19a76cc Add support for Sapphire Radeon RX 9060 XT Pure 2026-01-25 12:01:23 +03:00
175 changed files with 9481 additions and 3484 deletions
+4 -16
View File
@@ -516,10 +516,7 @@ before_script:
- macos
stage: build
script:
- eval $(/opt/homebrew/bin/brew shellenv)
- /opt/homebrew/opt/qt@5/bin/qmake OpenRGB.pro
- make -j16
- /opt/homebrew/opt/qt@5/bin/macdeployqt OpenRGB.app -codesign=OpenRGB
- ./scripts/build-macos.sh qt5 arm
artifacts:
name: "${CI_PROJECT_NAME}_MacOS_ARM64_${CI_COMMIT_SHORT_SHA}"
@@ -535,10 +532,7 @@ before_script:
- macos
stage: build
script:
- eval $(/opt/homebrew/bin/brew shellenv)
- qmake OpenRGB.pro
- make -j16
- macdeployqt OpenRGB.app -codesign=OpenRGB
- ./scripts/build-macos.sh qt6 arm
artifacts:
name: "${CI_PROJECT_NAME}_MacOS_ARM64_Qt6_${CI_COMMIT_SHORT_SHA}"
@@ -554,10 +548,7 @@ before_script:
- macos
stage: build
script:
- eval $(/usr/local/bin/brew shellenv)
- arch -x86_64 /usr/local/opt/qt@5/bin/qmake OpenRGB.pro
- arch -x86_64 make -j16
- arch -x86_64 /usr/local/opt/qt@5/bin/macdeployqt OpenRGB.app -codesign=OpenRGB
- ./scripts/build-macos.sh qt5 intel
artifacts:
name: "${CI_PROJECT_NAME}_MacOS_Intel_${CI_COMMIT_SHORT_SHA}"
@@ -573,10 +564,7 @@ before_script:
- macos
stage: build
script:
- eval $(/usr/local/bin/brew shellenv)
- arch -x86_64 /usr/local/bin/qmake OpenRGB.pro
- arch -x86_64 make -j16
- arch -x86_64 /usr/local/bin/macdeployqt OpenRGB.app -codesign=OpenRGB
- ./scripts/build-macos.sh qt6 intel
artifacts:
name: "${CI_PROJECT_NAME}_MacOS_Intel_Qt6_${CI_COMMIT_SHORT_SHA}"
+1 -2
View File
@@ -22,13 +22,12 @@ CODEOWNERS @Calcprogrammer1
/Controllers/BlinkyTapeController/
/Controllers/CoolerMasterController/ @Dr_No
/Controllers/CorsairCommanderCoreController/
/Controllers/CorsairDominatorPlatinumController/
/Controllers/CorsairDRAMController/
/Controllers/CorsairHydroController/
/Controllers/CorsairHydroPlatinumController/
/Controllers/CorsairLightingNodeController/
/Controllers/CorsairPeripheralController/
/Controllers/CorsairVengeanceController/
/Controllers/CorsairVengeanceProController/
/Controllers/CorsairWirelessController/
/Controllers/CreativeController/
/Controllers/CrucialController/
+4
View File
@@ -69,3 +69,7 @@ OpenRGB is written in C++, uses the Qt framework for UI, and uses the QMake buil
Translation files are located in [`OpenRGB/qt/i18n/`](https://gitlab.com/CalcProgrammer1/OpenRGB/-/tree/master/qt/i18n), where languages are formatted using ISO 639-1 format: `OpenRGB_xx_XX.ts` — `xx_XX` representing the language code.
In order to translate a file, you need to [fork](https://gitlab.com/CalcProgrammer1/OpenRGB/-/forks/new) the project, create a new file for your language with `lupdate` (or edit an exisiting one), edit the file with `qtlinguist`, commit, push, and create a merge request.
## AI Guidelines
OpenRGB is an open source project developed by humans for humans. As a general rule, AI generated submissions are not permitted. The licensing behind AI generated code is problematic. If you choose to use AI for assistance in your development process, we can't stop you, but do not credit the AI in commits (no AI authorship/co-authorship). Ultimately, you as a human developer are responsible for the code you submit and it is expected that any code you submit you fully understand and have manually vetted before submission. Merge requests that appear to be straight from an AI output, commits with AI tool authorship or co-authorship tags, or otherwise AI generated submissions are subject to closure.
@@ -22,6 +22,7 @@
#define AURA_ROG_GLADIUS_II_WIRELESS_1_PID 0x189E
#define AURA_ROG_GLADIUS_II_WIRELESS_2_PID 0x18A0
#define AURA_ROG_GLADIUS_III_PID 0x197B
#define AURA_ROG_GLADIUS_III_CORE_PID 0x1C8D
#define AURA_ROG_GLADIUS_III_WIRELESS_USB_PID 0x197D
#define AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID 0x197F
#define AURA_ROG_GLADIUS_III_WIRELESS_BT_PID 0x1981
@@ -217,6 +218,20 @@ static std::map<int,mouse_type> aura_mouse_devices =
{ AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY }
}
},
{
AURA_ROG_GLADIUS_III_CORE_PID, // ROG Gladius III Core
{
0,
0,
0,
100,
false,
1,
false,
{ AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL },
{ AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE }
}
},
{
AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, // ROG Gladius III Wireless USB
{
@@ -19,7 +19,10 @@ AsusAuraRyuoAIOController::AsusAuraRyuoAIOController(hid_device* dev_handle, con
| Manually adding device info for now |
| TODO: Implement config table accurately |
\*-----------------------------------------------------*/
device_info.push_back({0x00, 0x00, 12, 0, AuraDeviceType::FIXED});
uint8_t leds = (dev_name.find("Ryujin") != std::string::npos) ? 5 : 12;
device_info.push_back({0x00, 0x00, leds, 0, AuraDeviceType::FIXED});
}
AsusAuraRyuoAIOController::~AsusAuraRyuoAIOController()
@@ -120,6 +120,7 @@
#define AURA_TERMINAL_PID 0x1889
#define ROG_STRIX_LC120_PID 0x879E
#define AURA_RYUO_AIO_PID 0x1887
#define AURA_RYUJIN_AIO_PID 0x18AE
#define ASUS_ROG_ALLY_PID 0x1ABE
#define ASUS_ROG_ALLY_X_PID 0x1B4C
@@ -393,6 +394,7 @@ REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin COD",
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_1_PID, 1, 0xFF13);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_2_PID, 2, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_CORE_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, 0, 0xFF01);
@@ -453,6 +455,7 @@ REGISTER_HID_DETECTOR_PU("ASUS ROG PG32UQ", DetectAs
REGISTER_HID_DETECTOR ("ASUS ROG AURA Terminal", DetectAsusAuraUSBTerminal, AURA_USB_VID, AURA_TERMINAL_PID);
REGISTER_HID_DETECTOR_PU ("ASUS ROG Strix LC", DetectAsusAuraUSBROGStrixLC, AURA_USB_VID, ROG_STRIX_LC120_PID, 0x00FF, 1);
REGISTER_HID_DETECTOR_PU ("ASUS ROG Ryuo AIO", DetectAsusAuraUSBRyuoAIO, AURA_USB_VID, AURA_RYUO_AIO_PID, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_PU ("ASUS ROG Ryujin AIO", DetectAsusAuraUSBRyuoAIO, AURA_USB_VID, AURA_RYUJIN_AIO_PID, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_I ("ASUS ROG Throne", DetectAsusAuraUSBHeadsetStand, AURA_USB_VID, AURA_ROG_THRONE_PID, 0);
REGISTER_HID_DETECTOR_I ("ASUS ROG Throne QI", DetectAsusAuraUSBHeadsetStand, AURA_USB_VID, AURA_ROG_THRONE_QI_PID, 0);
REGISTER_HID_DETECTOR_I ("ASUS ROG Throne QI GUNDAM", DetectAsusAuraUSBHeadsetStand, AURA_USB_VID, AURA_ROG_THRONE_QI_GUNDAM_PID, 0);
@@ -89,7 +89,7 @@ void AsusMonitorController::SetDirect(std::vector<RGBColor> colors)
usb_buf[0x00] = 0xEC;
usb_buf[0x01] = 0x40;
usb_buf[0x02] = 0x84;
usb_buf[0x04] = colors.size();
usb_buf[0x04] = (uint8_t)colors.size();
for(size_t i = 0; i < colors.size(); i++)
{
@@ -10,8 +10,9 @@
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ClevoKeyboardController.h"
#include <cstring>
#include "ClevoKeyboardController.h"
#include "StringUtils.h"
ClevoKeyboardController::ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info)
{
@@ -40,10 +41,7 @@ std::string ClevoKeyboardController::GetSerialString()
return("");
}
std::wstring return_wstring = serial_string;
std::string return_string(return_wstring.begin(), return_wstring.end());
return(return_string);
return(StringUtils::wstring_to_string(serial_string));
}
std::string ClevoKeyboardController::GetFirmwareVersion()
@@ -10,8 +10,9 @@
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ClevoLightbarController.h"
#include <cstring>
#include "ClevoLightbarController.h"
#include "StringUtils.h"
ClevoLightbarController::ClevoLightbarController(hid_device* dev_handle, const hid_device_info& info)
{
@@ -40,10 +41,7 @@ std::string ClevoLightbarController::GetSerialString()
return("");
}
std::wstring return_wstring = serial_string;
std::string return_string(return_wstring.begin(), return_wstring.end());
return(return_string);
return(StringUtils::wstring_to_string(serial_string));
}
std::string ClevoLightbarController::GetFirmwareVersion()
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| ColorfulGPUControllerDetect.cpp |
| |
| Detector for Colorful GPU |
@@ -48,7 +48,7 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Advanced OC 12G L-V", Detec
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA106_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060TI_ADVANCED_OC, 0x61);
@@ -72,3 +72,8 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", Detec
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060_ULTRAW_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV2, 0x61);
@@ -12,16 +12,27 @@
#include "CMARGBController.h"
#include "StringUtils.h"
CMARGBController::CMARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx, std::shared_ptr<std::mutex> cm_mutex)
/*---------------------------------------------------------*\
| Map to convert port index to port ID used in protocol |
\*---------------------------------------------------------*/
static unsigned char cm_argb_port_index_to_id[5] =
{
dev = dev_handle;
location = _path;
zone_index = _zone_idx;
mutex_ptr = cm_mutex;
CM_ARGB_PORT_ARGB_1,
CM_ARGB_PORT_ARGB_2,
CM_ARGB_PORT_ARGB_3,
CM_ARGB_PORT_ARGB_4,
CM_ARGB_PORT_RGB
};
/*---------------------------------------------------------*\
| Get device name from HID manufacturer and product strings |
\*---------------------------------------------------------*/
CMARGBController::CMARGBController(hid_device* dev_handle, char *path)
{
dev = dev_handle;
location = path;
/*-----------------------------------------------------*\
| Get device name from HID manufacturer and product |
| strings |
\*-----------------------------------------------------*/
wchar_t name_string[HID_MAX_STR];
hid_get_manufacturer_string(dev, name_string, HID_MAX_STR);
@@ -29,57 +40,11 @@ CMARGBController::CMARGBController(hid_device* dev_handle, char *_path, unsigned
hid_get_product_string(dev, name_string, HID_MAX_STR);
device_name.append(" ").append(StringUtils::wstring_to_string(name_string));
GetStatus();
}
CMARGBController::~CMARGBController()
{
if(mutex_ptr.use_count() <= 1)
{
hid_close(dev);
}
}
void CMARGBController::GetStatus()
{
unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00, 0x80, 0x0B, 0x01 };
int buffer_size = (sizeof(buffer) / sizeof(buffer[0]));
int rgb_offset = 0;
int zone;
if (argb_header_data[zone_index].digital)
{
zone = argb_header_data[zone_index].header;
buffer[CM_ARGB_COMMAND_BYTE] = 0x0B;
}
else
{
zone = 0x00;
buffer[CM_ARGB_COMMAND_BYTE] = 0x0A;
rgb_offset = 1;
}
/*---------------------------------------------*\
| Guard the writes to the controller until the |
| for loop has completed to avoid collisons |
\*---------------------------------------------*/
std::lock_guard<std::mutex> guard(*mutex_ptr);
/*---------------------------------------------------------*\
| If this is the group then just return the first status |
\*---------------------------------------------------------*/
buffer[CM_ARGB_ZONE_BYTE] = ( zone > 0x08 ) ? 0x01 : zone;
hid_write(dev, buffer, buffer_size);
hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT);
current_mode = buffer[4 - rgb_offset];
bool_random = ( buffer[5 - rgb_offset] == 0x00 );
current_speed = buffer[6 - rgb_offset];
current_brightness = buffer[7 - rgb_offset];
current_red = buffer[8 - rgb_offset];
current_green = buffer[9 - rgb_offset];
current_blue = buffer[10 - rgb_offset];
hid_close(dev);
}
std::string CMARGBController::GetDeviceName()
@@ -87,6 +52,33 @@ std::string CMARGBController::GetDeviceName()
return(device_name);
}
std::string CMARGBController::GetLocation()
{
return("HID: " + location);
}
std::string CMARGBController::GetVersion()
{
/*-----------------------------------------------------*\
| This device uses the serial value to determine the |
| version. It does not report a proper unique serial. |
\*-----------------------------------------------------*/
std::string serial_string = GetSerial();
if(serial_string == CM_ARGB_FW0023)
{
return("0023");
}
else if(serial_string == CM_ARGB_FW0028)
{
return("0028");
}
else
{
return("Unsupported");
}
}
std::string CMARGBController::GetSerial()
{
wchar_t serial_string[HID_MAX_STR];
@@ -100,118 +92,187 @@ std::string CMARGBController::GetSerial()
return(StringUtils::wstring_to_string(serial_string));
}
std::string CMARGBController::GetLocation()
void CMARGBController::GetPortStatus
(
unsigned char port_idx,
unsigned char* port_mode,
unsigned char* port_speed,
unsigned char* port_brightness,
bool* port_random,
unsigned char* port_red,
unsigned char* port_green,
unsigned char* port_blue
)
{
return("HID: " + location);
unsigned char buffer[CM_ARGB_PACKET_SIZE] = {0x00, 0x80, 0x0B, 0x01};
int buffer_size = (sizeof(buffer) / sizeof(buffer[0]));
int rgb_offset = 0;
int zone;
/*-----------------------------------------------------*\
| RGB port is handled differently from ARGB ports |
\*-----------------------------------------------------*/
if(cm_argb_port_index_to_id[port_idx] != CM_ARGB_PORT_RGB)
{
zone = cm_argb_port_index_to_id[port_idx];
buffer[CM_ARGB_COMMAND_BYTE] = 0x0B;
}
else
{
zone = 0x00;
buffer[CM_ARGB_COMMAND_BYTE] = 0x0A;
rgb_offset = 1;
}
/*-----------------------------------------------------*\
| If this is the group then just return the first |
| status |
\*-----------------------------------------------------*/
buffer[CM_ARGB_ZONE_BYTE] = ( zone > 0x08 ) ? 0x01 : zone;
/*-----------------------------------------------------*\
| Send the command and read the response |
\*-----------------------------------------------------*/
hid_write(dev, buffer, buffer_size);
hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT);
/*-----------------------------------------------------*\
| Read data out of response |
\*-----------------------------------------------------*/
*port_mode = buffer[4 - rgb_offset];
*port_random = (buffer[5 - rgb_offset] == 0x00);
*port_speed = buffer[6 - rgb_offset];
*port_brightness = buffer[7 - rgb_offset];
*port_red = buffer[8 - rgb_offset];
*port_green = buffer[9 - rgb_offset];
*port_blue = buffer[10 - rgb_offset];
}
unsigned char CMARGBController::GetZoneIndex()
void CMARGBController::SetPortLEDCount(unsigned char port_idx, unsigned char led_count)
{
return(zone_index);
}
unsigned char CMARGBController::GetMode()
{
return(current_mode);
}
unsigned char CMARGBController::GetLedRed()
{
return(current_red);
}
unsigned char CMARGBController::GetLedGreen()
{
return(current_green);
}
unsigned char CMARGBController::GetLedBlue()
{
return(current_blue);
}
unsigned char CMARGBController::GetLedSpeed()
{
return(current_speed);
}
bool CMARGBController::GetRandomColours()
{
return(bool_random);
}
void CMARGBController::SetLedCount(int zone, int led_count)
{
unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00, 0x80, 0x0D, 0x02 };
unsigned char buffer[CM_ARGB_PACKET_SIZE] = {0x00, 0x80, 0x0D, 0x02};
int buffer_size = (sizeof(buffer) / sizeof(buffer[0]));
buffer[CM_ARGB_ZONE_BYTE] = zone;
buffer[CM_ARGB_ZONE_BYTE] = cm_argb_port_index_to_id[port_idx];
buffer[CM_ARGB_MODE_BYTE] = led_count;
buffer[CM_ARGB_COLOUR_INDEX_BYTE] = (0x0F - led_count > 0) ? 0x0F - led_count : 0x01;
/*---------------------------------------------*\
| Guard the writes to the controller until the |
| for loop has completed to avoid collisons |
\*---------------------------------------------*/
std::lock_guard<std::mutex> guard(*mutex_ptr);
buffer[CM_ARGB_COLOUR_INDEX_BYTE] = 1;
/*-----------------------------------------------------*\
| Send the command |
\*-----------------------------------------------------*/
hid_write(dev, buffer, buffer_size);
}
void CMARGBController::SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor colour, bool random_colours)
void CMARGBController::SetPortMode
(
unsigned char port_idx,
unsigned char port_mode,
unsigned char port_speed,
unsigned char port_brightness,
bool port_random,
unsigned char port_red,
unsigned char port_green,
unsigned char port_blue
)
{
bool needs_update = !( (current_mode == mode) && (current_speed == speed) && (current_brightness == brightness) && (ToRGBColor(current_red, current_green, current_blue) == colour));
unsigned char buffer[CM_ARGB_PACKET_SIZE] = {0x00};
int buffer_size = (sizeof(buffer) / sizeof(buffer[0]));
bool boolARGB_header = (cm_argb_port_index_to_id[port_idx] != CM_ARGB_PORT_RGB);
bool boolPassthru = (port_mode == CM_ARGB_MODE_PASSTHRU) || (port_mode == CM_RGB_MODE_PASSTHRU);
bool boolDirect = (port_mode == CM_ARGB_MODE_DIRECT);
unsigned char function = boolPassthru ? (boolARGB_header ? 0x02 : 0x04) : (boolARGB_header ? 0x01 : 0x03);
buffer[CM_ARGB_REPORT_BYTE] = 0x80;
buffer[CM_ARGB_COMMAND_BYTE] = 0x01;
if (needs_update)
if(boolDirect)
{
current_mode = mode;
current_speed = speed;
current_brightness = brightness;
current_red = RGBGetRValue(colour);
current_green = RGBGetGValue(colour);
current_blue = RGBGetBValue(colour);
bool_random = random_colours;
buffer[CM_ARGB_FUNCTION_BYTE] = 0x01;
buffer[CM_ARGB_ZONE_BYTE] = 0x02;
SendUpdate();
/*-------------------------------------------------*\
| Send the command |
\*-------------------------------------------------*/
hid_write(dev, buffer, buffer_size);
/*-------------------------------------------------*\
| Direct mode is now set up and no other mode |
| packet is required |
\*-------------------------------------------------*/
return;
}
buffer[CM_ARGB_FUNCTION_BYTE] = function;
/*-----------------------------------------------------*\
| Send the command |
\*-----------------------------------------------------*/
hid_write(dev, buffer, buffer_size);
/*-----------------------------------------------------*\
| ARGB ports send command 0x0B, RGB port sends 0x04 |
\*-----------------------------------------------------*/
if(boolARGB_header)
{
buffer[CM_ARGB_COMMAND_BYTE] = 0x0B;
buffer[CM_ARGB_FUNCTION_BYTE] = (false) ? 0x01 : 0x02;
buffer[CM_ARGB_ZONE_BYTE] = cm_argb_port_index_to_id[port_idx];
buffer[CM_ARGB_MODE_BYTE] = port_mode;
buffer[CM_ARGB_COLOUR_INDEX_BYTE] = port_random ? 0x00 : 0x10;
buffer[CM_ARGB_SPEED_BYTE] = port_speed;
buffer[CM_ARGB_BRIGHTNESS_BYTE] = port_brightness;
buffer[CM_ARGB_RED_BYTE] = port_red;
buffer[CM_ARGB_GREEN_BYTE] = port_green;
buffer[CM_ARGB_BLUE_BYTE] = port_blue;
}
else
{
buffer[CM_ARGB_COMMAND_BYTE] = boolPassthru ? 0x01 : 0x04;
buffer[CM_ARGB_MODE_BYTE + CM_RGB_OFFSET] = port_mode;
buffer[CM_ARGB_COLOUR_INDEX_BYTE + CM_RGB_OFFSET] = port_random ? 0x00 : 0x10;
buffer[CM_ARGB_SPEED_BYTE + CM_RGB_OFFSET] = port_speed;
buffer[CM_ARGB_BRIGHTNESS_BYTE + CM_RGB_OFFSET] = port_brightness;
buffer[CM_ARGB_RED_BYTE + CM_RGB_OFFSET] = port_red;
buffer[CM_ARGB_GREEN_BYTE + CM_RGB_OFFSET] = port_green;
buffer[CM_ARGB_BLUE_BYTE + CM_RGB_OFFSET] = port_blue;
}
/*-----------------------------------------------------*\
| Send the command and wait for response |
\*-----------------------------------------------------*/
hid_write(dev, buffer, buffer_size);
}
void CMARGBController::SetLedsDirect(RGBColor *led_colours, unsigned int led_count)
void CMARGBController::SetPortLEDsDirect(unsigned char port_idx, RGBColor *led_colours, unsigned int led_count)
{
const unsigned char buffer_size = CM_ARGB_PACKET_SIZE;
unsigned char buffer[buffer_size] = { 0x00, 0x00, 0x07, 0x02 };
unsigned char packet_count = 0;
std::vector<uint8_t> colours;
/*---------------------------------------------*\
| Set up the RGB triplets to send |
\*---------------------------------------------*/
/*-----------------------------------------------------*\
| Set up the RGB triplets to send |
\*-----------------------------------------------------*/
for(unsigned int i = 0; i < led_count; i++)
{
RGBColor colour = led_colours[i];
colours.push_back( RGBGetRValue(colour) );
colours.push_back( RGBGetGValue(colour) );
colours.push_back( RGBGetBValue(colour) );
colours.push_back(RGBGetRValue(colour));
colours.push_back(RGBGetGValue(colour));
colours.push_back(RGBGetBValue(colour));
}
buffer[CM_ARGB_FUNCTION_BYTE] = zone_index - 1;
buffer[CM_ARGB_FUNCTION_BYTE] = port_idx;
buffer[CM_ARGB_ZONE_BYTE] = led_count;
unsigned char buffer_idx = CM_ARGB_MODE_BYTE;
/*---------------------------------------------*\
| Guard the writes to the controller until the |
| for loop has completed to avoid collisons |
\*---------------------------------------------*/
std::lock_guard<std::mutex> guard(*mutex_ptr);
for(std::vector<unsigned char>::iterator it = colours.begin(); it != colours.end(); buffer_idx = CM_ARGB_COMMAND_BYTE)
{
/*-----------------------------------------------------------------*\
| Fill the write buffer till its full or the colour buffer is empty |
\*-----------------------------------------------------------------*/
/*-------------------------------------------------*\
| Fill the write buffer till its full or the |
| colour buffer is empty |
\*-------------------------------------------------*/
buffer[CM_ARGB_REPORT_BYTE] = packet_count;
while (( buffer_idx < buffer_size) && ( it != colours.end() ))
while((buffer_idx < buffer_size) && (it != colours.end()))
{
buffer[buffer_idx] = *it;
buffer_idx++;
@@ -223,76 +284,15 @@ void CMARGBController::SetLedsDirect(RGBColor *led_colours, unsigned int led_cou
buffer[CM_ARGB_REPORT_BYTE] += 0x80;
}
/*-------------------------------------------------*\
| Send the buffer |
\*-------------------------------------------------*/
hid_write(dev, buffer, buffer_size);
/*-----------------------------------------------------------------*\
| Reset the write buffer |
\*-----------------------------------------------------------------*/
/*-------------------------------------------------*\
| Reset the write buffer |
\*-------------------------------------------------*/
memset(buffer, 0x00, buffer_size );
packet_count++;
}
}
void CMARGBController::SendUpdate()
{
/*---------------------------------------------*\
| Guard the writes to the controller |
\*---------------------------------------------*/
std::lock_guard<std::mutex> guard(*mutex_ptr);
unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00 };
int buffer_size = (sizeof(buffer) / sizeof(buffer[0]));
bool boolARGB_header = argb_header_data[zone_index].digital;
bool boolPassthru = ( current_mode == CM_ARGB_MODE_PASSTHRU ) || ( current_mode == CM_RGB_MODE_PASSTHRU );
bool boolDirect = ( current_mode == CM_ARGB_MODE_DIRECT );
unsigned char function = boolPassthru ? (boolARGB_header ? 0x02 : 0x04) : (boolARGB_header ? 0x01 : 0x03);
buffer[CM_ARGB_REPORT_BYTE] = 0x80;
buffer[CM_ARGB_COMMAND_BYTE] = 0x01;
if(boolDirect)
{
buffer[CM_ARGB_FUNCTION_BYTE] = 0x01;
buffer[CM_ARGB_ZONE_BYTE] = 0x02;
hid_write(dev, buffer, buffer_size);
hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT);
/*-----------------------------------------------------------------*\
| Direct mode is now set up and no other mode packet is required |
\*-----------------------------------------------------------------*/
return;
}
buffer[CM_ARGB_FUNCTION_BYTE] = function;
hid_write(dev, buffer, buffer_size);
hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT);
if(boolARGB_header)
{
buffer[CM_ARGB_COMMAND_BYTE] = 0x0B; //ARGB sends 0x0B (1011) RGB sends 0x04 (0100)
buffer[CM_ARGB_FUNCTION_BYTE] = (false) ? 0x01 : 0x02; //This controls direct mode TODO
buffer[CM_ARGB_ZONE_BYTE] = argb_header_data[zone_index].header;
buffer[CM_ARGB_MODE_BYTE] = current_mode;
buffer[CM_ARGB_COLOUR_INDEX_BYTE] = bool_random ? 0x00 : 0x10;
buffer[CM_ARGB_SPEED_BYTE] = current_speed;
buffer[CM_ARGB_BRIGHTNESS_BYTE] = current_brightness;
buffer[CM_ARGB_RED_BYTE] = current_red;
buffer[CM_ARGB_GREEN_BYTE] = current_green;
buffer[CM_ARGB_BLUE_BYTE] = current_blue;
}
else
{
buffer[CM_ARGB_COMMAND_BYTE] = boolPassthru ? 0x01 : 0x04; //ARGB sends 0x0b (1011) RGB sends 0x04 (0100)
buffer[CM_ARGB_MODE_BYTE + CM_RGB_OFFSET] = current_mode;
buffer[CM_ARGB_COLOUR_INDEX_BYTE + CM_RGB_OFFSET] = bool_random ? 0x00 : 0x10;
buffer[CM_ARGB_SPEED_BYTE + CM_RGB_OFFSET] = current_speed;
buffer[CM_ARGB_BRIGHTNESS_BYTE + CM_RGB_OFFSET] = current_brightness;
buffer[CM_ARGB_RED_BYTE + CM_RGB_OFFSET] = current_red;
buffer[CM_ARGB_GREEN_BYTE + CM_RGB_OFFSET] = current_green;
buffer[CM_ARGB_BLUE_BYTE + CM_RGB_OFFSET] = current_blue;
}
hid_write(dev, buffer, buffer_size);
hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT);
}
@@ -16,19 +16,20 @@
#include <array>
#include <memory>
#include <hidapi.h>
#include "RGBController.h" //Needed to set the direct mode
#include "RGBController.h"
#define CM_ARGB_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0]))
#define CM_ARGB_HEADER_DATA_SIZE (sizeof(argb_header_data) / sizeof(argb_headers) )
#define CM_ARGB_INTERRUPT_TIMEOUT 250
#define CM_ARGB_PACKET_SIZE 65
#define CM_ARGB_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ]))
#define CM_RGB_OFFSET -2
#define HID_MAX_STR 255
#define CM_ARGB_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0]))
#define CM_ARGB_HEADER_DATA_SIZE (sizeof(argb_header_data) / sizeof(argb_headers) )
#define CM_ARGB_INTERRUPT_TIMEOUT 250
#define CM_ARGB_PACKET_SIZE 65
#define CM_ARGB_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ]))
#define CM_RGB_OFFSET -2
#define HID_MAX_STR 255
#define CM_ARGB_BRIGHTNESS_MAX 255
#define CM_ARGB_FW0023 std::string("A202011171238")
#define CM_ARGB_FW0028 std::string("A202105291658")
#define CM_ARGB_BRIGHTNESS_MAX 255
#define CM_ARGB_FW0000 std::string("A201804091608")
#define CM_ARGB_FW0023 std::string("A202011171238")
#define CM_ARGB_FW0028 std::string("A202105291658")
enum
{
@@ -45,22 +46,13 @@ enum
CM_ARGB_BLUE_BYTE = 11
};
struct argb_headers
enum
{
const char* name;
unsigned char header;
bool digital;
unsigned int count;
};
static argb_headers argb_header_data[] =
{
{ "RGB Header", 0xFE, false, 1 },
{ "Digital ARGB1", 0x01, true, 12 },
{ "Digital ARGB2", 0x02, true, 12 },
{ "Digital ARGB3", 0x04, true, 12 },
{ "Digital ARGB4", 0x08, true, 12 },
//{ "All Digital ARGB", 0xFF, true, 12 }
CM_ARGB_PORT_ARGB_1 = 0x01,
CM_ARGB_PORT_ARGB_2 = 0x02,
CM_ARGB_PORT_ARGB_3 = 0x04,
CM_ARGB_PORT_ARGB_4 = 0x08,
CM_ARGB_PORT_RGB = 0xFE,
};
enum
@@ -101,40 +93,44 @@ enum
class CMARGBController
{
public:
CMARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx, std::shared_ptr<std::mutex> cm_mutex);
CMARGBController(hid_device* dev_handle, char* path);
~CMARGBController();
std::string GetDeviceName();
std::string GetSerial();
std::string GetLocation();
std::string GetVersion();
unsigned char GetZoneIndex();
unsigned char GetMode();
unsigned char GetLedRed();
unsigned char GetLedGreen();
unsigned char GetLedBlue();
unsigned char GetLedSpeed();
bool GetRandomColours();
void SetLedCount(int zone, int led_count);
void SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor colour, bool random_colours);
void SetLedsDirect(RGBColor * led_colours, unsigned int led_count);
void GetPortStatus
(
unsigned char port_idx,
unsigned char* port_mode,
unsigned char* port_speed,
unsigned char* port_brightness,
bool* port_random,
unsigned char* port_red,
unsigned char* port_green,
unsigned char* port_blue
);
void SetPortLEDCount(unsigned char port_idx, unsigned char led_count);
void SetPortMode
(
unsigned char port_idx,
unsigned char port_mode,
unsigned char port_speed,
unsigned char port_brightness,
bool port_random,
unsigned char port_red,
unsigned char port_green,
unsigned char port_blue
);
void SetPortLEDsDirect(unsigned char port_idx, RGBColor *led_colours, unsigned int led_count);
private:
std::string device_name;
std::string location;
hid_device* dev;
std::shared_ptr<std::mutex> mutex_ptr;
unsigned char zone_index;
unsigned char current_mode;
unsigned char current_speed;
unsigned char current_red;
unsigned char current_green;
unsigned char current_blue;
unsigned char current_brightness;
bool bool_random;
void GetStatus();
void SendUpdate();
hid_device* dev;
std::string device_name;
std::string location;
};
@@ -27,268 +27,220 @@
RGBController_CMARGBController::RGBController_CMARGBController(CMARGBController* controller_ptr)
{
controller = controller_ptr;
unsigned char speed = controller->GetLedSpeed();
name = argb_header_data[controller->GetZoneIndex()].name;
name = controller->GetDeviceName();
vendor = "Cooler Master";
type = DEVICE_TYPE_LEDSTRIP;
description = controller->GetDeviceName();
version = "3.0 for FW0028";
description = "Cooler Master ARGB Controller Device";
version = controller->GetVersion();
serial = controller->GetSerial();
location = controller->GetLocation();
if(argb_header_data[controller->GetZoneIndex()].digital)
{
mode Off;
Off.name = "Turn Off";
Off.value = CM_ARGB_MODE_OFF;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
/*-----------------------------------------------------*\
| The ARGB ports support more modes than the RGB port. |
| Define all of the modes the ARGB ports support and |
| map RGB modes to them as best as we can. Per-zone |
| support will be added in the future. |
\*-----------------------------------------------------*/
mode Off;
Off.name = "Off";
Off.value = CM_ARGB_MODE_OFF;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Reload;
Reload.name = "Reload";
Reload.value = CM_ARGB_MODE_RELOAD;
Reload.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Reload.colors_min = 1;
Reload.colors_max = 1;
Reload.colors.resize(Reload.colors_max);
Reload.brightness_min = 0;
Reload.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Reload.brightness = CM_ARGB_BRIGHTNESS_MAX;
Reload.speed_min = CM_ARGB_SPEED_SLOWEST;
Reload.speed_max = CM_ARGB_SPEED_FASTEST;
Reload.color_mode = MODE_COLORS_MODE_SPECIFIC;
Reload.speed = speed;
modes.push_back(Reload);
mode Reload;
Reload.name = "Reload";
Reload.value = CM_ARGB_MODE_RELOAD;
Reload.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Reload.speed_min = CM_ARGB_SPEED_SLOWEST;
Reload.speed_max = CM_ARGB_SPEED_FASTEST;
Reload.speed = CM_ARGB_SPEED_NORMAL;
Reload.brightness_min = 0;
Reload.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Reload.brightness = CM_ARGB_BRIGHTNESS_MAX;
Reload.color_mode = MODE_COLORS_MODE_SPECIFIC;
Reload.colors_min = 1;
Reload.colors_max = 1;
Reload.colors.resize(Reload.colors_max);
modes.push_back(Reload);
mode Recoil;
Recoil.name = "Recoil";
Recoil.value = CM_ARGB_MODE_RECOIL;
Recoil.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Recoil.colors_min = 1;
Recoil.colors_max = 1;
Recoil.colors.resize(Recoil.colors_max);
Recoil.brightness_min = 0;
Recoil.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Recoil.brightness = CM_ARGB_BRIGHTNESS_MAX;
Recoil.speed_min = CM_ARGB_SPEED_SLOWEST;
Recoil.speed_max = CM_ARGB_SPEED_FASTEST;
Recoil.color_mode = MODE_COLORS_MODE_SPECIFIC;
Recoil.speed = speed;
modes.push_back(Recoil);
mode Recoil;
Recoil.name = "Recoil";
Recoil.value = CM_ARGB_MODE_RECOIL;
Recoil.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Recoil.color_mode = MODE_COLORS_MODE_SPECIFIC;
Recoil.speed_min = CM_ARGB_SPEED_SLOWEST;
Recoil.speed_max = CM_ARGB_SPEED_FASTEST;
Recoil.speed = CM_ARGB_SPEED_NORMAL;
Recoil.brightness_min = 0;
Recoil.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Recoil.brightness = CM_ARGB_BRIGHTNESS_MAX;
Recoil.colors_min = 1;
Recoil.colors_max = 1;
Recoil.colors.resize(Recoil.colors_max);
modes.push_back(Recoil);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = CM_ARGB_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(Breathing.colors_max);
Breathing.brightness_min = 0;
Breathing.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Breathing.brightness = CM_ARGB_BRIGHTNESS_MAX;
Breathing.speed_min = CM_ARGB_SPEED_SLOWEST;
Breathing.speed_max = CM_ARGB_SPEED_FASTEST;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.speed = speed;
modes.push_back(Breathing);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = CM_ARGB_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.speed_min = CM_ARGB_SPEED_SLOWEST;
Breathing.speed_max = CM_ARGB_SPEED_FASTEST;
Breathing.speed = CM_ARGB_SPEED_NORMAL;
Breathing.brightness_min = 0;
Breathing.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Breathing.brightness = CM_ARGB_BRIGHTNESS_MAX;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(Breathing.colors_max);
modes.push_back(Breathing);
mode Refill;
Refill.name = "Refill";
Refill.value = CM_ARGB_MODE_REFILL;
Refill.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Refill.colors_min = 1;
Refill.colors_max = 1;
Refill.colors.resize(Refill.colors_max);
Refill.brightness_min = 0;
Refill.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Refill.brightness = CM_ARGB_BRIGHTNESS_MAX;
Refill.speed_min = CM_ARGB_SPEED_SLOWEST;
Refill.speed_max = CM_ARGB_SPEED_FASTEST;
Refill.color_mode = MODE_COLORS_MODE_SPECIFIC;
Refill.speed = speed;
modes.push_back(Refill);
mode Refill;
Refill.name = "Refill";
Refill.value = CM_ARGB_MODE_REFILL;
Refill.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Refill.color_mode = MODE_COLORS_MODE_SPECIFIC;
Refill.speed_min = CM_ARGB_SPEED_SLOWEST;
Refill.speed_max = CM_ARGB_SPEED_FASTEST;
Refill.speed = CM_ARGB_SPEED_NORMAL;
Refill.brightness_min = 0;
Refill.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Refill.brightness = CM_ARGB_BRIGHTNESS_MAX;
Refill.colors_min = 1;
Refill.colors_max = 1;
Refill.colors.resize(Refill.colors_max);
modes.push_back(Refill);
mode Demo;
Demo.name = "Demo";
Demo.value = CM_ARGB_MODE_DEMO;
Demo.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Demo.brightness_min = 0;
Demo.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Demo.brightness = CM_ARGB_BRIGHTNESS_MAX;
Demo.speed_min = CM_ARGB_SPEED_SLOWEST;
Demo.speed_max = CM_ARGB_SPEED_FASTEST;
Demo.color_mode = MODE_COLORS_NONE;
Demo.speed = speed;
modes.push_back(Demo);
mode Demo;
Demo.name = "Demo";
Demo.value = CM_ARGB_MODE_DEMO;
Demo.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Demo.color_mode = MODE_COLORS_NONE;
Demo.speed_min = CM_ARGB_SPEED_SLOWEST;
Demo.speed_max = CM_ARGB_SPEED_FASTEST;
Demo.speed = CM_ARGB_SPEED_NORMAL;
Demo.brightness_min = 0;
Demo.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Demo.brightness = CM_ARGB_BRIGHTNESS_MAX;
modes.push_back(Demo);
mode Spectrum;
Spectrum.name = "Spectrum";
Spectrum.value = CM_ARGB_MODE_SPECTRUM;
Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Spectrum.brightness_min = 0;
Spectrum.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Spectrum.brightness = CM_ARGB_BRIGHTNESS_MAX;
Spectrum.speed_min = CM_ARGB_SPEED_SLOWEST;
Spectrum.speed_max = CM_ARGB_SPEED_FASTEST;
Spectrum.color_mode = MODE_COLORS_NONE;
Spectrum.speed = speed;
modes.push_back(Spectrum);
mode Spectrum;
Spectrum.name = "Rainbow Wave";
Spectrum.value = CM_ARGB_MODE_SPECTRUM;
Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Spectrum.color_mode = MODE_COLORS_NONE;
Spectrum.speed_min = CM_ARGB_SPEED_SLOWEST;
Spectrum.speed_max = CM_ARGB_SPEED_FASTEST;
Spectrum.speed = CM_ARGB_SPEED_NORMAL;
Spectrum.brightness_min = 0;
Spectrum.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Spectrum.brightness = CM_ARGB_BRIGHTNESS_MAX;
modes.push_back(Spectrum);
mode FillFlow;
FillFlow.name = "Fill Flow";
FillFlow.value = CM_ARGB_MODE_FILLFLOW;
FillFlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
FillFlow.brightness_min = 0;
FillFlow.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
FillFlow.brightness = CM_ARGB_BRIGHTNESS_MAX;
FillFlow.speed_min = CM_ARGB_SPEED_SLOWEST;
FillFlow.speed_max = CM_ARGB_SPEED_FASTEST;
FillFlow.color_mode = MODE_COLORS_NONE;
FillFlow.speed = speed;
modes.push_back(FillFlow);
mode FillFlow;
FillFlow.name = "Fill Flow";
FillFlow.value = CM_ARGB_MODE_FILLFLOW;
FillFlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
FillFlow.color_mode = MODE_COLORS_NONE;
FillFlow.speed_min = CM_ARGB_SPEED_SLOWEST;
FillFlow.speed_max = CM_ARGB_SPEED_FASTEST;
FillFlow.speed = CM_ARGB_SPEED_NORMAL;
FillFlow.brightness_min = 0;
FillFlow.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
FillFlow.brightness = CM_ARGB_BRIGHTNESS_MAX;
modes.push_back(FillFlow);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CM_ARGB_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Rainbow.brightness_min = 0;
Rainbow.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Rainbow.brightness = CM_ARGB_BRIGHTNESS_MAX;
Rainbow.speed_min = CM_ARGB_SPEED_SLOWEST;
Rainbow.speed_max = CM_ARGB_SPEED_FASTEST;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.speed = speed;
modes.push_back(Rainbow);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CM_ARGB_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.speed_min = CM_ARGB_SPEED_SLOWEST;
Rainbow.speed_max = CM_ARGB_SPEED_FASTEST;
Rainbow.speed = CM_ARGB_SPEED_NORMAL;
Rainbow.brightness_min = 0;
Rainbow.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Rainbow.brightness = CM_ARGB_BRIGHTNESS_MAX;
modes.push_back(Rainbow);
mode Static;
Static.name = "Static";
Static.value = CM_ARGB_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(Static.colors_max);
Static.brightness_min = 0;
Static.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Static.brightness = CM_ARGB_BRIGHTNESS_MAX;
Static.speed_min = CM_ARGB_SPEED_SLOWEST;
Static.speed_max = CM_ARGB_SPEED_FASTEST;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.speed = speed;
modes.push_back(Static);
mode Static;
Static.name = "Static";
Static.value = CM_ARGB_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.speed_min = CM_ARGB_SPEED_SLOWEST;
Static.speed_max = CM_ARGB_SPEED_FASTEST;
Static.speed = CM_ARGB_SPEED_NORMAL;
Static.brightness_min = 0;
Static.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Static.brightness = CM_ARGB_BRIGHTNESS_MAX;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(Static.colors_max);
modes.push_back(Static);
mode Direct;
Direct.name = (serial >= CM_ARGB_FW0028) ? "Direct" : "Custom";
Direct.value = CM_ARGB_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Direct;
Direct.name = (serial >= CM_ARGB_FW0028) ? "Direct" : "Custom";
Direct.value = CM_ARGB_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode PassThru;
PassThru.name = "Pass Thru";
PassThru.value = CM_ARGB_MODE_PASSTHRU;
PassThru.flags = 0;
PassThru.color_mode = MODE_COLORS_NONE;
modes.push_back(PassThru);
}
else
{
mode Static;
Static.name = "Static";
Static.value = CM_RGB_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(Static.colors_max);
Static.brightness_min = 0;
Static.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Static.brightness = CM_ARGB_BRIGHTNESS_MAX;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.speed = 0;
modes.push_back(Static);
mode PassThru;
PassThru.name = "Pass Thru";
PassThru.value = CM_ARGB_MODE_PASSTHRU;
PassThru.flags = 0;
PassThru.color_mode = MODE_COLORS_NONE;
modes.push_back(PassThru);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = CM_RGB_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(Breathing.colors_max);
Breathing.brightness_min = 0;
Breathing.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Breathing.brightness = CM_ARGB_BRIGHTNESS_MAX;
Breathing.speed_min = CM_ARGB_SPEED_SLOWEST;
Breathing.speed_max = CM_ARGB_SPEED_FASTEST;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.speed = CM_ARGB_SPEED_NORMAL;
modes.push_back(Breathing);
mode Flash;
Flash.name = "Flash";
Flash.value = CM_RGB_MODE_FLASH;
Flash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Flash.colors_min = 1;
Flash.colors_max = 1;
Flash.colors.resize(Flash.colors_max);
Flash.brightness_min = 0;
Flash.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Flash.brightness = CM_ARGB_BRIGHTNESS_MAX;
Flash.speed_min = CM_ARGB_SPEED_SLOWEST;
Flash.speed_max = CM_ARGB_SPEED_FASTEST;
Flash.color_mode = MODE_COLORS_MODE_SPECIFIC;
Flash.speed = CM_ARGB_SPEED_NORMAL;
modes.push_back(Flash);
mode Mirage;
Mirage.name = "Mirage";
Mirage.value = CM_RGB_MODE_MIRAGE;
Mirage.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Mirage.colors_min = 1;
Mirage.colors_max = 1;
Mirage.colors.resize(Mirage.colors_max);
Mirage.brightness_min = 0;
Mirage.brightness_max = CM_ARGB_BRIGHTNESS_MAX;
Mirage.brightness = CM_ARGB_BRIGHTNESS_MAX;
Mirage.speed_min = CM_ARGB_SPEED_SLOWEST;
Mirage.speed_max = CM_ARGB_SPEED_FASTEST;
Mirage.color_mode = MODE_COLORS_MODE_SPECIFIC;
Mirage.speed = CM_ARGB_SPEED_NORMAL;
modes.push_back(Mirage);
mode PassThru;
PassThru.name = "Pass Thru";
PassThru.value = CM_RGB_MODE_PASSTHRU;
PassThru.color_mode = MODE_COLORS_NONE;
modes.push_back(PassThru);
mode Off;
Off.name = "Turn Off";
Off.value = CM_RGB_MODE_OFF;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
}
Init_Controller();
SetupZones();
int temp_mode = controller->GetMode();
for(int mode_idx = 0; mode_idx < (int)modes.size() ; mode_idx++)
/*-----------------------------------------------------*\
| Initialize the active mode to port 0 |
\*-----------------------------------------------------*/
unsigned char port_mode;
unsigned char port_speed;
unsigned char port_brightness;
bool port_random;
unsigned char port_red;
unsigned char port_green;
unsigned char port_blue;
controller->GetPortStatus(0, &port_mode, &port_speed, &port_brightness, &port_random, &port_red, &port_green, &port_blue);
for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++)
{
if (temp_mode == modes[mode_idx].value)
if(modes[mode_idx].value == port_mode)
{
active_mode = mode_idx;
active_mode = (int)mode_idx;
if((modes[mode_idx].flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) && (modes[mode_idx].colors.size() > 0))
{
modes[mode_idx].colors[0] = ToRGBColor(port_red, port_green, port_blue);
}
if(modes[mode_idx].flags & MODE_FLAG_HAS_SPEED)
{
modes[mode_idx].speed = port_speed;
}
if(modes[mode_idx].flags & MODE_FLAG_HAS_BRIGHTNESS)
{
modes[mode_idx].brightness = port_brightness;
}
if(modes[mode_idx].flags & MODE_FLAG_HAS_RANDOM_COLOR)
{
if(port_random)
{
modes[mode_idx].color_mode = MODE_COLORS_RANDOM;
}
}
break;
}
}
if (modes[active_mode].flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR)
{
modes[active_mode].colors[0] = ToRGBColor(controller->GetLedRed(), controller->GetLedGreen(), controller->GetLedBlue());
modes[active_mode].color_mode = (controller->GetRandomColours()) ? MODE_COLORS_RANDOM : MODE_COLORS_MODE_SPECIFIC;
}
if (modes[active_mode].flags & MODE_FLAG_HAS_SPEED)
{
modes[active_mode].speed = controller->GetLedSpeed();
}
}
RGBController_CMARGBController::~RGBController_CMARGBController()
@@ -296,68 +248,76 @@ RGBController_CMARGBController::~RGBController_CMARGBController()
delete controller;
}
void RGBController_CMARGBController::Init_Controller()
{
int zone_idx = controller->GetZoneIndex();
int zone_led_count = argb_header_data[zone_idx].count;
/*-------------------------------------------------*\
| If argb_header_data[zone_idx].count == 1 then the |
| zone is ZONE_TYPE_SINGLE |
\*-------------------------------------------------*/
bool boolSingleLED = ( zone_led_count == 1 );
zone ARGB_zone;
ARGB_zone.name = std::to_string(zone_idx);
ARGB_zone.type = (boolSingleLED) ? ZONE_TYPE_SINGLE : ZONE_TYPE_LINEAR;
ARGB_zone.leds_min = 4;
ARGB_zone.leds_max = 48;
ARGB_zone.leds_count = zone_led_count;
ARGB_zone.matrix_map = NULL;
zones.push_back(ARGB_zone);
}
void RGBController_CMARGBController::SetupZones()
{
/*-------------------------------------------------*\
| Clear any existing color/LED configuration |
\*-------------------------------------------------*/
/*-----------------------------------------------------*\
| Only set LED count on the first run |
\*-----------------------------------------------------*/
bool first_run = false;
if(zones.size() == 0)
{
first_run = true;
}
/*-----------------------------------------------------*\
| Clear any existing color/LED configuration |
\*-----------------------------------------------------*/
leds.clear();
colors.clear();
zones.resize(5);
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
/*-----------------------------------------------------*\
| Set up addressable zones |
\*-----------------------------------------------------*/
for(unsigned int channel_idx = 0; channel_idx < 4; channel_idx++)
{
bool boolSingleLED = (zones[zone_idx].type == ZONE_TYPE_SINGLE);
char ch_idx_string[2];
snprintf(ch_idx_string, 2, "%d", channel_idx + 1);
if (!boolSingleLED)
zones[channel_idx].name = "Addressable RGB Header ";
zones[channel_idx].name.append(ch_idx_string);
zones[channel_idx].type = ZONE_TYPE_LINEAR;
zones[channel_idx].leds_min = 0;
zones[channel_idx].leds_max = 48;
if(first_run)
{
controller->SetLedCount( std::stoi(zones[zone_idx].name), zones[zone_idx].leds_count);
zones[channel_idx].leds_count = 0;
}
for(unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++)
{
led new_led;
unsigned int i = std::stoi(zones[zone_idx].name);
zones[channel_idx].matrix_map = NULL;
if(boolSingleLED)
{
new_led.name = i;
new_led.value = argb_header_data[i].header;
}
else
{
new_led.name = i;
new_led.name.append(" LED " + std::to_string(lp_idx));
new_led.value = argb_header_data[i].header;
}
for(unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++)
{
char led_idx_string[4];
snprintf(led_idx_string, 4, "%d", led_ch_idx + 1);
led new_led;
new_led.name = zones[channel_idx].name;
new_led.name.append(", LED ");
new_led.name.append(led_idx_string);
new_led.value = channel_idx;
leds.push_back(new_led);
}
}
/*-----------------------------------------------------*\
| Set up RGB zone |
\*-----------------------------------------------------*/
zones[4].name = "RGB Header";
zones[4].type = ZONE_TYPE_SINGLE;
zones[4].leds_min = 1;
zones[4].leds_max = 1;
zones[4].leds_count = 1;
zones[4].matrix_map = NULL;
led new_led;
new_led.name = "RGB Header";
new_led.value = 4;
leds.push_back(new_led);
SetupColors();
}
@@ -367,62 +327,114 @@ void RGBController_CMARGBController::ResizeZone(int zone, int new_size)
{
return;
}
uint8_t end_zone = last_zone(zone);
for(std::size_t zone_idx = first_zone(zone); zone_idx < end_zone; zone_idx++)
if(((unsigned int)new_size >= zones[zone].leds_min) && ((unsigned int)new_size <= zones[zone].leds_max))
{
if(((unsigned int)new_size >= zones[zone_idx].leds_min) && ((unsigned int)new_size <= zones[zone_idx].leds_max))
{
zones[zone_idx].leds_count = new_size;
}
}
zones[zone].leds_count = new_size;
SetupZones();
controller->SetPortLEDCount(zone, zones[zone].leds_count);
SetupZones();
}
}
void RGBController_CMARGBController::DeviceUpdateLEDs()
{
uint8_t end_zone = last_zone(cmargb->GetZoneIndex());
for(int zone_idx = first_zone(cmargb->GetZoneIndex()); zone_idx < end_zone; zone_idx++)
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
UpdateZoneLEDs(zone_idx);
UpdateZoneLEDs((int)zone_idx);
}
}
void RGBController_CMARGBController::UpdateZoneLEDs(int zone)
{
controller->SetLedsDirect( zones[zone].colors, zones[zone].leds_count );
/*-----------------------------------------------------*\
| The RGB zone doesn't have a separate Direct mode, so |
| use static mode with the per-LED color for it |
\*-----------------------------------------------------*/
if(zone < 4)
{
controller->SetPortLEDsDirect(zone, zones[zone].colors, zones[zone].leds_count);
}
else
{
controller->SetPortMode(zone, CM_RGB_MODE_STATIC, 0, 255, false, RGBGetRValue(zones[zone].colors[0]), RGBGetGValue(zones[zone].colors[0]), RGBGetBValue(zones[zone].colors[0]));
}
}
void RGBController_CMARGBController::UpdateSingleLED(int led)
{
UpdateZoneLEDs(GetLED_Zone(led));
unsigned int zone_idx = leds[led].value;
UpdateZoneLEDs(zone_idx);
}
void RGBController_CMARGBController::DeviceUpdateMode()
{
bool random_colours = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
RGBColor colour = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) ? modes[active_mode].colors[0] : 0;
/*-----------------------------------------------------*\
| Determine mode parameters |
\*-----------------------------------------------------*/
bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
RGBColor color = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) ? modes[active_mode].colors[0] : 0;
int rgb_mode;
bool rgb_random = random;
controller->SetMode( modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, colour, random_colours );
}
int RGBController_CMARGBController::GetLED_Zone(int led_idx)
{
/*---------------------------------------------------------*\
| This may be more useful in the abstract RGBController.cpp |
\*---------------------------------------------------------*/
for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++)
/*-----------------------------------------------------*\
| Map ARGB modes with the equivalent RGB modes |
\*-----------------------------------------------------*/
switch(modes[active_mode].value)
{
int zone_start = zones[zone_idx].start_idx;
int zone_end = zone_start + zones[zone_idx].leds_count - 1;
case CM_ARGB_MODE_SPECTRUM:
case CM_ARGB_MODE_FILLFLOW:
case CM_ARGB_MODE_RAINBOW:
rgb_mode = CM_RGB_MODE_MIRAGE;
rgb_random = true;
break;
if(zone_start <= led_idx && zone_end >= led_idx)
{
return(zone_idx);
}
case CM_ARGB_MODE_RELOAD:
case CM_ARGB_MODE_RECOIL:
rgb_mode = CM_RGB_MODE_FLASH;
break;
case CM_ARGB_MODE_BREATHING:
rgb_mode = CM_RGB_MODE_BREATHING;
break;
case CM_ARGB_MODE_REFILL:
case CM_ARGB_MODE_STATIC:
rgb_mode = CM_RGB_MODE_STATIC;
break;
case CM_ARGB_MODE_DEMO:
rgb_mode = CM_RGB_MODE_FLASH;
rgb_random = true;
break;
case CM_ARGB_MODE_OFF:
default:
rgb_mode = CM_RGB_MODE_OFF;
break;
case CM_ARGB_MODE_PASSTHRU:
rgb_mode = CM_RGB_MODE_PASSTHRU;
break;
}
return -1;
/*-----------------------------------------------------*\
| Apply mode to all zones |
\*-----------------------------------------------------*/
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
controller->SetPortMode
(
(unsigned char)zone_idx,
(zone_idx == 4) ? rgb_mode : modes[active_mode].value,
modes[active_mode].speed,
modes[active_mode].brightness,
(zone_idx == 4) ? rgb_random : random,
RGBGetRValue(color),
RGBGetGValue(color),
RGBGetBValue(color)
);
}
}
@@ -12,11 +12,8 @@
#pragma once
#include <vector>
#include "RGBController.h"
#include "CMARGBController.h"
#define first_zone(zn) ((zones.size() > 1) ? 1 : 0)
#define last_zone(zn) ((zones.size() > 1) ? 4 : 1)
#include "RGBController.h"
class RGBController_CMARGBController : public RGBController
{
@@ -34,9 +31,6 @@ public:
void DeviceUpdateMode();
private:
void Init_Controller();
int GetDeviceMode();
int GetLED_Zone(int led_idx);
CMARGBController* controller;
CMARGBController* controller;
std::vector<unsigned int> leds_channel;
};
@@ -96,19 +96,18 @@ void DetectCoolerMasterARGB(hid_device_info* info, const std::string&)
if(dev)
{
/*-------------------------------------------------*\
| Create mutex to prevent the controllers sharing a |
| receiver from interfering with each other |
\*-------------------------------------------------*/
std::shared_ptr<std::mutex> cm_mutex = std::make_shared<std::mutex>();
CMARGBController* controller = new CMARGBController(dev, info->path);
for(unsigned char i = 0; i < CM_ARGB_HEADER_DATA_SIZE; i++)
if(controller->GetVersion() != "Unsupported")
{
CMARGBController* controller = new CMARGBController(dev, info->path, i, cm_mutex);
RGBController_CMARGBController* rgb_controller = new RGBController_CMARGBController(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
else
{
LOG_ERROR("[CMARGBController] Unsupported firmware version");
delete controller;
}
}
}
@@ -0,0 +1,422 @@
/*---------------------------------------------------------*\
| CorsairDRAMController.cpp |
| |
| Driver for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "CRC.h"
#include "CorsairDRAMController.h"
#include "LogManager.h"
#define CORSAIR_DRAM_NAME "Corsair DRAM"
using namespace std::chrono_literals;
CorsairDRAMController::CorsairDRAMController(i2c_smbus_interface *bus, corsair_dev_id dev)
{
/*-----------------------------------------------------*\
| Initialize class variables |
\*-----------------------------------------------------*/
this->bus = bus;
this->dev = dev;
device_index = 0;
pid = 0;
vid = 0;
protocol_version = 0;
/*-----------------------------------------------------*\
| Read device information |
\*-----------------------------------------------------*/
ReadDeviceInfo();
}
CorsairDRAMController::~CorsairDRAMController()
{
}
unsigned int CorsairDRAMController::GetLEDCount()
{
return(corsair_dram_device_list[device_index]->led_count);
}
unsigned char CorsairDRAMController::GetProtocolVersion()
{
return(protocol_version);
}
std::string CorsairDRAMController::GetDeviceLocation()
{
std::string return_string(bus->device_name);
char addr[5];
snprintf(addr, 5, "0x%02X", dev);
return_string.append(", address ");
return_string.append(addr);
return("I2C: " + return_string);
}
std::string CorsairDRAMController::GetDeviceName()
{
return(corsair_dram_device_list[device_index]->name);
}
std::string CorsairDRAMController::GetDeviceVersion()
{
return(firmware_version);
}
void CorsairDRAMController::SetColorsPerLED(RGBColor* colors)
{
/*-----------------------------------------------------*\
| Get LED count from device list |
\*-----------------------------------------------------*/
unsigned int led_count = corsair_dram_device_list[device_index]->led_count;
if(direct_mode)
{
/*-------------------------------------------------*\
| Sanity check - Direct mode can only be used on |
| protocol 4+ |
\*-------------------------------------------------*/
if(protocol_version < 4)
{
LOG_ERROR("[%s] Protocol version %d tried to use direct mode, ignoring", CORSAIR_DRAM_NAME, protocol_version);
return;
}
/*-------------------------------------------------*\
| Packet format: |
| Size n is (LED count * 3) + 2 |
| 0: Command byte (0x0A or 0x0C) |
| 1 to (n-2): LED color data in R/G/B order |
| (n-1): CRC8 of bytes 0 to (n-2) |
\*-------------------------------------------------*/
unsigned int direct_packet_size = (led_count * 3) + 2;
unsigned char* direct_packet = new unsigned char[direct_packet_size];
/*-------------------------------------------------*\
| First byte in packet is LED count |
\*-------------------------------------------------*/
direct_packet[0] = led_count;
/*-------------------------------------------------*\
| Fill in LED data |
\*-------------------------------------------------*/
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
{
unsigned int color_index = led_idx;
unsigned int offset = (led_idx * 3) + 1;
if(corsair_dram_device_list[device_index]->reverse)
{
color_index = (led_count -1) - led_idx;
}
direct_packet[offset + 0] = RGBGetRValue(colors[color_index]);
direct_packet[offset + 1] = RGBGetGValue(colors[color_index]);
direct_packet[offset + 2] = RGBGetBValue(colors[color_index]);
}
/*-------------------------------------------------*\
| Last byte in packet is CRC of all data up to it |
\*-------------------------------------------------*/
direct_packet[direct_packet_size - 1] = CRCPP::CRC::Calculate(direct_packet, (direct_packet_size - 1), CRCPP::CRC::CRC_8());
/*-------------------------------------------------*\
| Write using block writes, if packet exceeds 32 |
| bytes, use a second block write to the second |
| block write address for the remaining data |
\*-------------------------------------------------*/
bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_1, 32, direct_packet);
if(direct_packet_size > 32)
{
bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_2, direct_packet_size - 32, direct_packet + 32);
}
/*-------------------------------------------------*\
| Remember to delete the data buffer |
\*-------------------------------------------------*/
delete[] direct_packet;
}
else
{
/*-------------------------------------------------*\
| Local variables |
\*-------------------------------------------------*/
unsigned char device_crc;
unsigned char calc_crc;
/*-------------------------------------------------*\
| Packet format: |
| Size n is (LED count * 4) |
| Format is 0xRR, 0xGG, 0xBB, 0xFF for each LED |
\*-------------------------------------------------*/
unsigned int color_data_size = (led_count * 4);
unsigned char* color_data_packet = new unsigned char[color_data_size];
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
{
unsigned int color_index = led_idx;
if(corsair_dram_device_list[device_index]->reverse)
{
color_index = (led_count -1) - led_idx;
}
color_data_packet[(led_idx * 4) + 0] = RGBGetRValue(colors[color_index]);
color_data_packet[(led_idx * 4) + 1] = RGBGetGValue(colors[color_index]);
color_data_packet[(led_idx * 4) + 2] = RGBGetBValue(colors[color_index]);
color_data_packet[(led_idx * 4) + 3] = 0xFF;
}
/*-------------------------------------------------*\
| Write LED color data packet |
\*-------------------------------------------------*/
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_RESET_BUFFER, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_BINARY_START, 0x00);
for(unsigned int i = 0; i < color_data_size; i++)
{
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_SET_BINARY_DATA, color_data_packet[i]);
}
/*-------------------------------------------------*\
| Calculate CRC and read CRC reported by device |
\*-------------------------------------------------*/
calc_crc = CRCPP::CRC::Calculate(color_data_packet, color_data_size, CRCPP::CRC::CRC_8());
device_crc = bus->i2c_smbus_read_byte_data(dev, CORSAIR_DRAM_REG_GET_CHECKSUM);
/*-------------------------------------------------*\
| Write effect configuration only if CRCs match |
\*-------------------------------------------------*/
if(calc_crc == device_crc)
{
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_WRITE_CONFIGURATION, CORSAIR_DRAM_ID_COLOR_DATA);
WaitReady();
}
/*-------------------------------------------------*\
| Remember to delete the data buffer |
\*-------------------------------------------------*/
delete[] color_data_packet;
}
}
void CorsairDRAMController::SetDirect(bool direct)
{
direct_mode = direct;
}
void CorsairDRAMController::SetEffect
(
unsigned char mode,
unsigned char speed,
unsigned char direction,
bool random,
unsigned char brightness,
unsigned char red1,
unsigned char grn1,
unsigned char blu1,
unsigned char red2,
unsigned char grn2,
unsigned char blu2
)
{
/*-----------------------------------------------------*\
| Local variables |
\*-----------------------------------------------------*/
unsigned char effect_data[20];
unsigned char device_crc;
unsigned char calc_crc;
unsigned char random_byte;
/*-----------------------------------------------------*\
| If mode is direct (which is a dummy value not |
| understood by the hardware), return. Direct mode is |
| not set in the effect configuration. |
\*-----------------------------------------------------*/
direct_mode = (mode == CORSAIR_DRAM_MODE_DIRECT);
if(direct_mode)
{
return;
}
/*-----------------------------------------------------*\
| Determine random byte |
\*-----------------------------------------------------*/
if(random)
{
random_byte = CORSAIR_DRAM_EFFECT_RANDOM_COLORS;
}
else
{
random_byte = CORSAIR_DRAM_EFFECT_CUSTOM_COLORS;
}
/*-----------------------------------------------------*\
| Fill in effect packet |
\*-----------------------------------------------------*/
effect_data[0] = mode; // Mode
effect_data[1] = speed; // Speed
effect_data[2] = random_byte; // Custom color
effect_data[3] = direction; // Direction
effect_data[4] = red1; // Custom color 1 red
effect_data[5] = grn1; // Custom color 1 green
effect_data[6] = blu1; // Custom color 1 blue
effect_data[7] = brightness;
effect_data[8] = red2; // Custom color 2 red
effect_data[9] = grn2; // Custom color 2 green
effect_data[10] = blu2; // Custom color 2 blue
effect_data[11] = brightness;
effect_data[12] = 0x00;
effect_data[13] = 0x00;
effect_data[14] = 0x00;
effect_data[15] = 0x00;
effect_data[16] = 0x00;
effect_data[17] = 0x00;
effect_data[18] = 0x00;
effect_data[19] = 0x00;
/*-----------------------------------------------------*\
| Write effect packet |
\*-----------------------------------------------------*/
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_RESET_BUFFER, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_BINARY_START, 0x00);
for(unsigned int i = 0; i < 20; i++)
{
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_SET_BINARY_DATA, effect_data[i]);
}
/*-----------------------------------------------------*\
| Calculate CRC and read CRC reported by device |
\*-----------------------------------------------------*/
calc_crc = CRCPP::CRC::Calculate(effect_data, sizeof(effect_data), CRCPP::CRC::CRC_8());
device_crc = bus->i2c_smbus_read_byte_data(dev, CORSAIR_DRAM_REG_GET_CHECKSUM);
/*-----------------------------------------------------*\
| Write effect configuration only if CRCs match |
\*-----------------------------------------------------*/
if(calc_crc == device_crc)
{
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_WRITE_CONFIGURATION, CORSAIR_DRAM_ID_EFFECT_CONFIGURATION);
WaitReady();
}
}
bool CorsairDRAMController::WaitReady()
{
/*-----------------------------------------------------*\
| Poll status register 0x30; bit 3 (0x08) = busy. |
| Device is ready when bit 3 is clear. |
\*-----------------------------------------------------*/
for(int retry = 0; retry < 5; retry++)
{
int status = bus->i2c_smbus_read_byte_data(dev, CORSAIR_DRAM_REG_STATUS);
if(status >= 0 && (status & 0x08) == 0)
{
return true;
}
std::this_thread::sleep_for(10ms);
}
return false;
}
void CorsairDRAMController::ReadDeviceInfo()
{
unsigned char device_information_data[32];
unsigned char device_crc;
unsigned char calc_crc;
/*-----------------------------------------------------*\
| Request Device Information Data |
\*-----------------------------------------------------*/
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_GET_DEVICE_INFO, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_DRAM_REG_BINARY_START, 0x00);
/*-----------------------------------------------------*\
| Read Device Information Data |
\*-----------------------------------------------------*/
for(unsigned int i = 0; i < 32; i++)
{
device_information_data[i] = bus->i2c_smbus_read_byte_data(dev, CORSAIR_DRAM_REG_GET_BINARY_DATA);
}
/*-----------------------------------------------------*\
| Compare CRC |
\*-----------------------------------------------------*/
calc_crc = CRCPP::CRC::Calculate(device_information_data, sizeof(device_information_data), CRCPP::CRC::CRC_8());
device_crc = bus->i2c_smbus_read_byte_data(dev, CORSAIR_DRAM_REG_GET_CHECKSUM);
if(calc_crc != device_crc)
{
LOG_ERROR("[%s] ReadDeviceInfo CRC Mismatch", CORSAIR_DRAM_NAME);
}
/*-----------------------------------------------------*\
| Log Device Information Data |
\*-----------------------------------------------------*/
if(LogManager::get()->getLoglevel() >= LL_TRACE)
{
char device_info_buf[256];
unsigned int pos;
pos = snprintf(device_info_buf, sizeof(device_info_buf), "%02X: ", dev);
for(unsigned int i = 0; i < 32; i++)
{
pos += snprintf(&device_info_buf[pos], sizeof(device_info_buf) - pos, "%02X ", device_information_data[i]);
}
LOG_TRACE("[%s] Device Info: %s", CORSAIR_DRAM_NAME, device_info_buf);
}
/*-----------------------------------------------------*\
| Read VID |
\*-----------------------------------------------------*/
vid = (device_information_data[1] << 8) | device_information_data[0];
/*-----------------------------------------------------*\
| Read PID |
\*-----------------------------------------------------*/
pid = (device_information_data[3] << 8) | device_information_data[2];
/*-----------------------------------------------------*\
| Format Firwmare Version |
\*-----------------------------------------------------*/
firmware_version = std::to_string(device_information_data[9]) + "." + std::to_string(device_information_data[8]) + "." + std::to_string((device_information_data[11] << 8) | device_information_data[10]);
/*-----------------------------------------------------*\
| Read Protocol Version |
\*-----------------------------------------------------*/
protocol_version = device_information_data[28];
/*-----------------------------------------------------*\
| Loop through all known devices to look for a PID |
| match |
\*-----------------------------------------------------*/
for(unsigned int i = 0; i < CORSAIR_DRAM_NUM_DEVICES; i++)
{
for(unsigned int j = 0; j < CORSAIR_DRAM_MAX_PIDS; j++)
{
if(corsair_dram_device_list[i]->pids[j] == pid)
{
/*-----------------------------------------*\
| Set device ID |
\*-----------------------------------------*/
device_index = i;
break;
}
}
}
}
@@ -0,0 +1,149 @@
/*---------------------------------------------------------*\
| CorsairDRAMController.h |
| |
| Driver for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
#include "CorsairDRAMDevices.h"
#include "RGBController.h"
typedef unsigned char corsair_dev_id;
enum
{ /* (*) indicates deprecated registers no longer used by iCue */
CORSAIR_DRAM_REG_RESET_BUFFER = 0x0B, /* Reset buffer by writing 0x00 */
CORSAIR_DRAM_REG_SET_BINARY_DATA = 0x20, /* Write byte to active binary data buffer */
CORSAIR_DRAM_REG_BINARY_START = 0x21, /* Start binary data transfer by writing 0x00 */
CORSAIR_DRAM_REG_SWITCH_MODE = 0x23, /* Switch between Bootloader(0x00) and Normal(0x01) */
CORSAIR_DRAM_REG_SET_BUFFER = 0x26, /* Select configuration buffer to write by ID (*) */
CORSAIR_DRAM_REG_STATUS = 0x30, /* Status register */
CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_1 = 0x31, /* Direct color buffer block register 1 */
CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_2 = 0x32, /* Direct color buffer block register 2 */
CORSAIR_DRAM_REG_GET_BINARY_DATA = 0x40, /* Read byte from active binary data buffer */
CORSAIR_DRAM_REG_BUSY_STATUS = 0x41, /* Reads nonzero while busy, zero when ready(*) */
CORSAIR_DRAM_REG_GET_CHECKSUM = 0x42, /* Get checksum (CRC8) of active binary data buffer */
CORSAIR_DRAM_REG_GET_DEVICE_INFO = 0x61, /* Select device info buffer */
CORSAIR_DRAM_REG_GET_CONFIGURATION = 0x63, /* Select configuration buffer to read by ID */
CORSAIR_DRAM_REG_WRITE_CONFIGURATION = 0x82, /* Write/Apply configuration by writing buffer ID */
};
enum
{
CORSAIR_DRAM_ID_COMMAND_LIST = 0, /* Command list */
CORSAIR_DRAM_ID_EFFECT_CONFIGURATION = 1, /* Effect configuration */
CORSAIR_DRAM_ID_COLOR_DATA = 2, /* Color data */
};
enum
{
CORSAIR_DRAM_MODE_DIRECT = 0xDD, /* Arbitrary value to compare against later. Not the actual packet */
CORSAIR_DRAM_MODE_COLOR_SHIFT = 0x00, /* Color Shift mode */
CORSAIR_DRAM_MODE_COLOR_PULSE = 0x01, /* Color Pulse mode */
CORSAIR_DRAM_MODE_RAINBOW_WAVE = 0x03, /* Rainbow Wave mode */
CORSAIR_DRAM_MODE_COLOR_WAVE = 0x04, /* Color Wave mode */
CORSAIR_DRAM_MODE_VISOR = 0x05, /* Visor mode */
CORSAIR_DRAM_MODE_RAIN = 0x06, /* Rain mode */
CORSAIR_DRAM_MODE_MARQUEE = 0x07, /* Marquee mode */
CORSAIR_DRAM_MODE_RAINBOW = 0x08, /* Rainbow mode */
CORSAIR_DRAM_MODE_SEQUENTIAL = 0x09, /* Sequential mode */
CORSAIR_DRAM_MODE_STATIC = 0x10, /* Static mode */
CORSAIR_DRAM_NUMBER_MODES = 10, /* Number of Corsair Pro modes */
};
enum
{
CORSAIR_DRAM_SPEED_SLOW = 0x00, /* Slow speed */
CORSAIR_DRAM_SPEED_MEDIUM = 0x01, /* Medium speed */
CORSAIR_DRAM_SPEED_FAST = 0x02, /* Fast speed */
};
enum
{
CORSAIR_DRAM_EFFECT_RANDOM_COLORS = 0x00, /* Random colors */
CORSAIR_DRAM_EFFECT_CUSTOM_COLORS = 0x01, /* Custom colors */
};
enum
{
CORSAIR_DRAM_DIRECTION_UP = 0x00, /* Up direction */
CORSAIR_DRAM_DIRECTION_DOWN = 0x01, /* Down direction */
CORSAIR_DRAM_DIRECTION_LEFT = 0x02, /* Left direction */
CORSAIR_DRAM_DIRECTION_RIGHT = 0x03, /* Right direction */
CORSAIR_DRAM_DIRECTION_VERTICAL = 0x01, /* Vertical direction */
CORSAIR_DRAM_DIRECTION_HORIZONTAL = 0x03, /* Horizontal direction */
};
enum
{
CORSAIR_DRAM_BRIGHTNESS_MIN = 0, /* Minimum brightness */
CORSAIR_DRAM_BRIGHTNESS_MAX = 255, /* Maximum brightness */
CORSAIR_DRAM_BRIGHTNESS_DEFAULT = 255, /* Default brightness */
};
class CorsairDRAMController
{
public:
CorsairDRAMController(i2c_smbus_interface *bus, corsair_dev_id dev);
~CorsairDRAMController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetDeviceVersion();
unsigned int GetLEDCount();
unsigned char GetProtocolVersion();
void SetColorsPerLED(RGBColor* colors);
void SetDirect(bool direct);
void SetEffect(unsigned char mode,
unsigned char speed,
unsigned char direction,
bool random,
unsigned char brightness,
unsigned char red1,
unsigned char grn1,
unsigned char blu1,
unsigned char red2,
unsigned char grn2,
unsigned char blu2);
bool WaitReady();
private:
/*-----------------------------------------------------*\
| I2C |
\*-----------------------------------------------------*/
i2c_smbus_interface* bus;
corsair_dev_id dev;
/*-----------------------------------------------------*\
| State tracking |
\*-----------------------------------------------------*/
bool direct_mode;
/*-----------------------------------------------------*\
| Corsair DRAM information |
\*-----------------------------------------------------*/
unsigned short vid;
unsigned short pid;
std::string firmware_version;
unsigned char protocol_version;
unsigned int device_index;
/*-----------------------------------------------------*\
| Private functions |
\*-----------------------------------------------------*/
void ReadDeviceInfo();
};
@@ -0,0 +1,92 @@
/*---------------------------------------------------------*\
| CorsairDRAMControllerDetect.cpp |
| |
| Detector for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "Detector.h"
#include "CorsairDRAMController.h"
#include "RGBController_CorsairDRAM.h"
#include "LogManager.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
using namespace std::chrono_literals;
#define CORSAIR_DRAM_NAME "Corsair DRAM"
bool TestForCorsairDRAMController(i2c_smbus_interface *bus, unsigned char address)
{
int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE);
LOG_DEBUG("[%s] Trying address %02X", CORSAIR_DRAM_NAME, address);
if(res < 0)
{
LOG_DEBUG("[%s] Failed: res was %04X", CORSAIR_DRAM_NAME, res);
return false;
}
res = bus->i2c_smbus_read_byte_data(address, 0x43);
if(!(res == 0x1A || res == 0x1B || res == 0x1C))
{
LOG_DEBUG("[%s] Failed: expected 0x1A, 0x1B, or 0x1C, got %04X", CORSAIR_DRAM_NAME, res);
return false;
}
res = bus->i2c_smbus_read_byte_data(address, 0x44);
if(!(res == 0x01 || res == 0x03 || res == 0x04))
{
LOG_DEBUG("[%s] Failed: expected 0x01, 0x03, or 0x04, got %04X", CORSAIR_DRAM_NAME, res);
return false;
}
return true;
}
void DetectCorsairDRAMControllers(std::vector<i2c_smbus_interface *> &busses)
{
for(unsigned int bus = 0; bus < busses.size(); bus++)
{
IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device)
{
LOG_DEBUG("[%s] Testing bus %d", CORSAIR_DRAM_NAME, bus);
std::vector<unsigned char> addresses;
for(unsigned char addr = 0x58; addr <= 0x5F; addr++)
{
addresses.push_back(addr);
}
for(unsigned char addr = 0x18; addr <= 0x1F; addr++)
{
addresses.push_back(addr);
}
for(unsigned char addr : addresses)
{
if(TestForCorsairDRAMController(busses[bus], addr))
{
CorsairDRAMController* controller = new CorsairDRAMController(busses[bus], addr);
RGBController_CorsairDRAM* rgb_controller = new RGBController_CorsairDRAM(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
std::this_thread::sleep_for(10ms);
}
}
}
}
REGISTER_I2C_DETECTOR(CORSAIR_DRAM_NAME, DetectCorsairDRAMControllers);
@@ -0,0 +1,163 @@
/*---------------------------------------------------------*\
| CorsairDRAMDevices.cpp |
| |
| Device list for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 07 Apr 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "CorsairDRAMDevices.h"
static const corsair_dram_device corsair_vengeance_pro_ddr4_device =
{
"Corsair Vengeance RGB Pro DDR4",
{
CORSAIR_VENGEANCE_PRO_DDR4_PID_1,
CORSAIR_VENGEANCE_PRO_DDR4_PID_2,
0,
0,
0,
0,
},
10,
false
};
static const corsair_dram_device corsair_dominator_platinum_ddr4_device =
{
"Corsair Dominator Platinum RGB DDR4",
{
CORSAIR_DOMINATOR_PLATINUM_DDR4_PID_1,
CORSAIR_DOMINATOR_PLATINUM_DDR4_PID_2,
0,
0,
0,
0,
},
12,
true
};
static const corsair_dram_device corsair_vengeance_pro_sl_ddr4_device =
{
"Corsair Vengeance RGB Pro SL DDR4",
{
CORSAIR_VENGEANCE_PRO_SL_DDR4_PID_1,
CORSAIR_VENGEANCE_PRO_SL_DDR4_PID_2,
0,
0,
0,
0,
},
10,
false
};
static const corsair_dram_device corsair_vengeance_rs_ddr4_device =
{
"Corsair Vengeance RGB RS DDR4",
{
CORSAIR_VENGEANCE_RS_DDR4_PID_1,
CORSAIR_VENGEANCE_RS_DDR4_PID_2,
0,
0,
0,
0,
},
6,
false
};
static const corsair_dram_device corsair_dominator_platinum_ddr5_device =
{
"Corsair Dominator Platinum RGB DDR5",
{
CORSAIR_DOMINATOR_PLATINUM_DDR5_PID_1,
CORSAIR_DOMINATOR_PLATINUM_DDR5_PID_2,
0,
0,
0,
0,
},
12,
true
};
static const corsair_dram_device corsair_dominator_titanium_ddr5_device =
{
"Corsair Dominator Titanium RGB DDR5",
{
CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_1,
CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_2,
CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_3,
CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_4,
0,
0,
},
12,
true
};
static const corsair_dram_device corsair_vengeance_ddr5_device =
{
"Corsair Vengeance RGB DDR5",
{
CORSAIR_VENGEANCE_DDR5_PID_1,
CORSAIR_VENGEANCE_DDR5_PID_2,
CORSAIR_VENGEANCE_DDR5_PID_3,
CORSAIR_VENGEANCE_DDR5_PID_4,
CORSAIR_VENGEANCE_DDR5_PID_5,
CORSAIR_VENGEANCE_DDR5_PID_6,
},
10,
false
};
static const corsair_dram_device corsair_vengeance_shugo_series_ddr5_device =
{
"Corsair Vengeance Shugo Series DDR5",
{
CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_1,
CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_2,
CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_3,
CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_4,
0,
0,
},
10,
false
};
static const corsair_dram_device corsair_vengeance_rs_ddr5_device =
{
"Corsair Vengeance RGB RS DDR5",
{
CORSAIR_VENGEANCE_RS_DDR5_PID_1,
CORSAIR_VENGEANCE_RS_DDR5_PID_2,
0,
0,
0,
0,
},
6,
false
};
static const corsair_dram_device* device_list[] =
{
&corsair_vengeance_pro_ddr4_device,
&corsair_dominator_platinum_ddr4_device,
&corsair_vengeance_pro_sl_ddr4_device,
&corsair_vengeance_rs_ddr4_device,
&corsair_dominator_platinum_ddr5_device,
&corsair_dominator_titanium_ddr5_device,
&corsair_vengeance_ddr5_device,
&corsair_vengeance_shugo_series_ddr5_device,
&corsair_vengeance_rs_ddr5_device,
};
const unsigned int CORSAIR_DRAM_NUM_DEVICES = (sizeof(device_list) / sizeof(device_list[ 0 ]));
const corsair_dram_device** corsair_dram_device_list = device_list;
@@ -0,0 +1,68 @@
/*---------------------------------------------------------*\
| CorsairDRAMDevices.h |
| |
| Device list for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 07 Apr 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
/*---------------------------------------------------------*\
| Maximum number of PIDs for a given DRAM model |
\*---------------------------------------------------------*/
#define CORSAIR_DRAM_MAX_PIDS 6
/*---------------------------------------------------------*\
| Corsair DRAM vendor ID |
\*---------------------------------------------------------*/
#define CORSAIR_DRAM_VID 0x1B1C
/*---------------------------------------------------------*\
| Corsair DRAM product IDs |
\*---------------------------------------------------------*/
#define CORSAIR_VENGEANCE_PRO_DDR4_PID_1 0x0100
#define CORSAIR_VENGEANCE_PRO_DDR4_PID_2 0x0101
#define CORSAIR_DOMINATOR_PLATINUM_DDR4_PID_1 0x0200
#define CORSAIR_DOMINATOR_PLATINUM_DDR4_PID_2 0x0201
#define CORSAIR_VENGEANCE_PRO_SL_DDR4_PID_1 0x0300
#define CORSAIR_VENGEANCE_PRO_SL_DDR4_PID_2 0x0301
#define CORSAIR_VENGEANCE_RS_DDR4_PID_1 0x0400
#define CORSAIR_VENGEANCE_RS_DDR4_PID_2 0x0401
#define CORSAIR_DOMINATOR_PLATINUM_DDR5_PID_1 0x0600
#define CORSAIR_DOMINATOR_PLATINUM_DDR5_PID_2 0x0601
#define CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_1 0x0800
#define CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_2 0x0801
#define CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_3 0x0810
#define CORSAIR_DOMINATOR_TITANIUM_DDR5_PID_4 0x0811
#define CORSAIR_VENGEANCE_DDR5_PID_1 0x0700
#define CORSAIR_VENGEANCE_DDR5_PID_2 0x0701
#define CORSAIR_VENGEANCE_DDR5_PID_3 0x0900
#define CORSAIR_VENGEANCE_DDR5_PID_4 0x0901
#define CORSAIR_VENGEANCE_DDR5_PID_5 0x0910
#define CORSAIR_VENGEANCE_DDR5_PID_6 0x0911
#define CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_1 0x0A00
#define CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_2 0x0A01
#define CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_3 0x0A10
#define CORSAIR_VENGEANCE_SHUGO_SERIES_DDR5_PID_4 0x0A11
#define CORSAIR_VENGEANCE_RS_DDR5_PID_1 0x0B00
#define CORSAIR_VENGEANCE_RS_DDR5_PID_2 0x0B01
typedef struct
{
std::string name;
unsigned short pids[CORSAIR_DRAM_MAX_PIDS];
unsigned int led_count;
bool reverse;
} corsair_dram_device;
/*-----------------------------------------------------*\
| These constant values are defined in RazerDevices.cpp |
\*-----------------------------------------------------*/
extern const unsigned int CORSAIR_DRAM_NUM_DEVICES;
extern const corsair_dram_device** corsair_dram_device_list;
@@ -0,0 +1,330 @@
/*---------------------------------------------------------*\
| RGBController_CorsairDRAM.cpp |
| |
| RGBController for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_CorsairDRAM.h"
/**------------------------------------------------------------------*\
@name Corsair DRAM
@category RAM
@type SMBus
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectCorsairDRAMControllers
@comment
The Corsair DRAM RGB controller chip can be found on several
Corsair memory sticks which have different LED counts. This can be controlled
by editing the Part Number in OpenRGB.json with values in the below table.
| Part Number | LED Count |
| :---------: | --------: |
| CMG | 6 |
| CMH | 10 |
| CMN | 10 |
| CMT | 12 |
\*-------------------------------------------------------------------*/
RGBController_CorsairDRAM::RGBController_CorsairDRAM(CorsairDRAMController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Corsair";
type = DEVICE_TYPE_DRAM;
description = "Corsair DRAM RGB Device";
location = controller->GetDeviceLocation();
version = controller->GetDeviceVersion();
if(controller->GetProtocolVersion() >= 4)
{
mode Direct;
Direct.name = "Direct";
Direct.value = CORSAIR_DRAM_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
}
mode Custom;
Custom.name = "Custom";
Custom.value = CORSAIR_DRAM_MODE_STATIC;
Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE;
Custom.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Custom);
mode ColorShift;
ColorShift.name = "Color Shift";
ColorShift.value = CORSAIR_DRAM_MODE_COLOR_SHIFT;
ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorShift.speed_min = CORSAIR_DRAM_SPEED_SLOW;
ColorShift.speed_max = CORSAIR_DRAM_SPEED_FAST;
ColorShift.speed = CORSAIR_DRAM_SPEED_SLOW;
ColorShift.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
ColorShift.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
ColorShift.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
ColorShift.colors_min = 2;
ColorShift.colors_max = 2;
ColorShift.colors.resize(2);
modes.push_back(ColorShift);
mode ColorPulse;
ColorPulse.name = "Color Pulse";
ColorPulse.value = CORSAIR_DRAM_MODE_COLOR_PULSE;
ColorPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
ColorPulse.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorPulse.speed_min = CORSAIR_DRAM_SPEED_SLOW;
ColorPulse.speed_max = CORSAIR_DRAM_SPEED_FAST;
ColorPulse.speed = CORSAIR_DRAM_SPEED_SLOW;
ColorPulse.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
ColorPulse.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
ColorPulse.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
ColorPulse.colors_min = 2;
ColorPulse.colors_max = 2;
ColorPulse.colors.resize(2);
modes.push_back(ColorPulse);
mode RainbowWave;
RainbowWave.name = "Rainbow Wave";
RainbowWave.value = CORSAIR_DRAM_MODE_RAINBOW_WAVE;
RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE;
RainbowWave.color_mode = MODE_COLORS_NONE;
RainbowWave.speed_min = CORSAIR_DRAM_SPEED_SLOW;
RainbowWave.speed_max = CORSAIR_DRAM_SPEED_FAST;
RainbowWave.speed = CORSAIR_DRAM_SPEED_SLOW;
RainbowWave.direction = MODE_DIRECTION_DOWN;
modes.push_back(RainbowWave);
mode ColorWave;
ColorWave.name = "Color Wave";
ColorWave.value = CORSAIR_DRAM_MODE_COLOR_WAVE;
ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorWave.speed_min = CORSAIR_DRAM_SPEED_SLOW;
ColorWave.speed_max = CORSAIR_DRAM_SPEED_FAST;
ColorWave.speed = CORSAIR_DRAM_SPEED_SLOW;
ColorWave.direction = MODE_DIRECTION_DOWN;
ColorWave.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
ColorWave.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
ColorWave.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
ColorWave.colors_min = 2;
ColorWave.colors_max = 2;
ColorWave.colors.resize(2);
modes.push_back(ColorWave);
mode Visor;
Visor.name = "Visor";
Visor.value = CORSAIR_DRAM_MODE_VISOR;
Visor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_HV | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
Visor.color_mode = MODE_COLORS_MODE_SPECIFIC;
Visor.speed_min = CORSAIR_DRAM_SPEED_SLOW;
Visor.speed_max = CORSAIR_DRAM_SPEED_FAST;
Visor.speed = CORSAIR_DRAM_SPEED_SLOW;
Visor.direction = MODE_DIRECTION_VERTICAL;
Visor.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
Visor.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
Visor.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
Visor.colors_min = 2;
Visor.colors_max = 2;
Visor.colors.resize(2);
modes.push_back(Visor);
mode Rain;
Rain.name = "Rain";
Rain.value = CORSAIR_DRAM_MODE_RAIN;
Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
Rain.color_mode = MODE_COLORS_MODE_SPECIFIC;
Rain.speed_min = CORSAIR_DRAM_SPEED_SLOW;
Rain.speed_max = CORSAIR_DRAM_SPEED_FAST;
Rain.speed = CORSAIR_DRAM_SPEED_SLOW;
Rain.direction = MODE_DIRECTION_DOWN;
Rain.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
Rain.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
Rain.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
Rain.colors_min = 2;
Rain.colors_max = 2;
Rain.colors.resize(2);
modes.push_back(Rain);
mode Marquee;
Marquee.name = "Marquee";
Marquee.value = CORSAIR_DRAM_MODE_MARQUEE;
Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC;
Marquee.speed_min = CORSAIR_DRAM_SPEED_SLOW;
Marquee.speed_max = CORSAIR_DRAM_SPEED_FAST;
Marquee.speed = CORSAIR_DRAM_SPEED_SLOW;
Marquee.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
Marquee.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
Marquee.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
Marquee.colors_min = 1;
Marquee.colors_max = 1;
Marquee.colors.resize(1);
modes.push_back(Marquee);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CORSAIR_DRAM_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.speed_min = CORSAIR_DRAM_SPEED_SLOW;
Rainbow.speed_max = CORSAIR_DRAM_SPEED_FAST;
Rainbow.speed = CORSAIR_DRAM_SPEED_SLOW;
modes.push_back(Rainbow);
mode Sequential;
Sequential.name = "Sequential";
Sequential.value = CORSAIR_DRAM_MODE_SEQUENTIAL;
Sequential.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
Sequential.color_mode = MODE_COLORS_MODE_SPECIFIC;
Sequential.speed_min = CORSAIR_DRAM_SPEED_SLOW;
Sequential.speed_max = CORSAIR_DRAM_SPEED_FAST;
Sequential.speed = CORSAIR_DRAM_SPEED_SLOW;
Sequential.direction = MODE_DIRECTION_DOWN;
Sequential.brightness_min = CORSAIR_DRAM_BRIGHTNESS_MIN;
Sequential.brightness_max = CORSAIR_DRAM_BRIGHTNESS_MAX;
Sequential.brightness = CORSAIR_DRAM_BRIGHTNESS_DEFAULT;
Sequential.colors_min = 1;
Sequential.colors_max = 1;
Sequential.colors.resize(1);
modes.push_back(Sequential);
SetupZones();
}
RGBController_CorsairDRAM::~RGBController_CorsairDRAM()
{
delete controller;
}
void RGBController_CorsairDRAM::SetupZones()
{
/*-----------------------------------------------------*\
| Set up zone |
\*-----------------------------------------------------*/
zone new_zone;
new_zone.name = "Corsair DRAM";
new_zone.type = ZONE_TYPE_LINEAR;
new_zone.leds_min = controller->GetLEDCount();
new_zone.leds_max = controller->GetLEDCount();
new_zone.leds_count = controller->GetLEDCount();
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
/*-----------------------------------------------------*\
| Set up LEDs |
\*-----------------------------------------------------*/
for(std::size_t led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
{
led new_led;
new_led.name = "Corsair DRAM LED ";
new_led.name.append(std::to_string(led_idx));
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_CorsairDRAM::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*-----------------------------------------------------*\
| This device does not support resizing zones |
\*-----------------------------------------------------*/
}
void RGBController_CorsairDRAM::DeviceUpdateLEDs()
{
controller->SetColorsPerLED(colors.data());
}
void RGBController_CorsairDRAM::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_CorsairDRAM::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_CorsairDRAM::DeviceUpdateMode()
{
unsigned int corsair_direction = 0;
bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
unsigned char mode_colors[6];
switch(modes[active_mode].direction)
{
case MODE_DIRECTION_LEFT:
corsair_direction = CORSAIR_DRAM_DIRECTION_LEFT;
break;
case MODE_DIRECTION_RIGHT:
corsair_direction = CORSAIR_DRAM_DIRECTION_RIGHT;
break;
case MODE_DIRECTION_UP:
corsair_direction = CORSAIR_DRAM_DIRECTION_UP;
break;
case MODE_DIRECTION_DOWN:
corsair_direction = CORSAIR_DRAM_DIRECTION_DOWN;
break;
case MODE_DIRECTION_HORIZONTAL:
corsair_direction = CORSAIR_DRAM_DIRECTION_HORIZONTAL;
break;
case MODE_DIRECTION_VERTICAL:
corsair_direction = CORSAIR_DRAM_DIRECTION_VERTICAL;
break;
}
mode_colors[0] = 0;
mode_colors[1] = 0;
mode_colors[2] = 0;
mode_colors[3] = 0;
mode_colors[4] = 0;
mode_colors[5] = 0;
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
mode_colors[0] = RGBGetRValue(modes[active_mode].colors[0]);
mode_colors[1] = RGBGetGValue(modes[active_mode].colors[0]);
mode_colors[2] = RGBGetBValue(modes[active_mode].colors[0]);
if(modes[active_mode].colors.size() == 2)
{
mode_colors[3] = RGBGetRValue(modes[active_mode].colors[1]);
mode_colors[4] = RGBGetGValue(modes[active_mode].colors[1]);
mode_colors[5] = RGBGetBValue(modes[active_mode].colors[1]);
}
}
if(modes[active_mode].name == "Direct")
{
controller->SetDirect(true);
}
else
{
controller->SetDirect(false);
}
controller->SetEffect(modes[active_mode].value,
modes[active_mode].speed,
corsair_direction,
random,
(unsigned char)modes[active_mode].brightness,
mode_colors[0],
mode_colors[1],
mode_colors[2],
mode_colors[3],
mode_colors[4],
mode_colors[5]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
}
@@ -1,8 +1,9 @@
/*---------------------------------------------------------*\
| RGBController_CorsairDominatorPlatinum.h |
| RGBController_CorsairDRAM.h |
| |
| RGBController for Corsair Dominator Platinum RAM |
| RGBController for Corsair DRAM RGB controllers |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
@@ -12,13 +13,13 @@
#pragma once
#include "RGBController.h"
#include "CorsairDominatorPlatinumController.h"
#include "CorsairDRAMController.h"
class RGBController_CorsairDominatorPlatinum : public RGBController
class RGBController_CorsairDRAM : public RGBController
{
public:
RGBController_CorsairDominatorPlatinum(CorsairDominatorPlatinumController* controller_ptr);
~RGBController_CorsairDominatorPlatinum();
RGBController_CorsairDRAM(CorsairDRAMController* controller_ptr);
~RGBController_CorsairDRAM();
void SetupZones();
@@ -31,5 +32,5 @@ public:
void DeviceUpdateMode();
private:
CorsairDominatorPlatinumController* controller;
CorsairDRAMController* controller;
};
@@ -1,134 +0,0 @@
/*---------------------------------------------------------*\
| CorsairDominatorPlatinumController.cpp |
| |
| Driver for Corsair Dominator Platinum RAM |
| |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <chrono>
#include "CorsairDominatorPlatinumController.h"
using namespace std::chrono_literals;
CorsairDominatorPlatinumController::CorsairDominatorPlatinumController(i2c_smbus_interface *bus, corsair_dev_id dev, unsigned int leds_count, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->leds_count = leds_count;
this->name = dev_name;
led_data[0] = 0xc;
}
CorsairDominatorPlatinumController::~CorsairDominatorPlatinumController()
{
}
unsigned int CorsairDominatorPlatinumController::GetLEDCount()
{
return leds_count;
}
std::string CorsairDominatorPlatinumController::GetDeviceLocation()
{
std::string return_string(bus->device_name);
char addr[5];
snprintf(addr, 5, "0x%02X", dev);
return_string.append(", address ");
return_string.append(addr);
return("I2C: " + return_string);
}
std::string CorsairDominatorPlatinumController::GetDeviceName()
{
return(name);
}
void CorsairDominatorPlatinumController::SetAllColors
(
unsigned char red,
unsigned char green,
unsigned char blue
)
{
for(unsigned int led = 0; led < leds_count; led++)
{
SetLEDColor(led, red, green, blue);
}
}
void CorsairDominatorPlatinumController::SetLEDColor
(
unsigned int led,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
if(led >= leds_count)
{
return;
}
unsigned int offset = (led * 3) + 1;
led_data[offset] = red;
led_data[offset + 1] = green;
led_data[offset + 2] = blue;
}
unsigned char CorsairDominatorPlatinumController::crc8
(
unsigned char init,
unsigned char poly,
unsigned char* data,
unsigned char len
)
{
unsigned char crc = init;
for(unsigned int i = 0; i < len; i++)
{
unsigned char val = data[i];
for(unsigned char mask = 0x80; mask != 0; mask >>= 1)
{
unsigned char bit;
if ((val & mask) != 0)
{
bit = (crc & 0x80) ^ 0x80;
}
else
{
bit = crc & 0x80;
}
if (bit == 0)
{
crc <<= 1;
}
else
{
crc = (crc << 1) ^ poly;
}
}
}
return crc;
}
void CorsairDominatorPlatinumController::ApplyColors()
{
unsigned char data[sizeof(led_data)];
memcpy(data, led_data, sizeof(led_data));
unsigned char crc = crc8(0x0, 0x7, data, sizeof(data) - 1);
data[sizeof(data) - 1] = crc;
bus->i2c_smbus_write_block_data(dev, 0x31, 0x20, data);
std::this_thread::sleep_for(800us);
bus->i2c_smbus_write_block_data(dev, 0x32, sizeof(data) - 0x20, data + 0x20);
std::this_thread::sleep_for(200us);
}
@@ -1,44 +0,0 @@
/*---------------------------------------------------------*\
| CorsairDominatorPlatinumController.h |
| |
| Driver for Corsair Dominator Platinum RAM |
| |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
#define CORSAIR_DOMINATOR_PLATINUM_DATA_SIZE 38
typedef unsigned char corsair_dev_id;
class CorsairDominatorPlatinumController
{
public:
CorsairDominatorPlatinumController(i2c_smbus_interface *bus, corsair_dev_id dev, unsigned int leds_count, std::string dev_name);
~CorsairDominatorPlatinumController();
std::string GetDeviceLocation();
std::string GetDeviceName();
unsigned int GetLEDCount();
void SetAllColors(unsigned char red, unsigned char green, unsigned char blue);
void SetLEDColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue);
void ApplyColors();
bool WaitReady();
private:
unsigned char led_data[CORSAIR_DOMINATOR_PLATINUM_DATA_SIZE];
i2c_smbus_interface* bus;
corsair_dev_id dev;
unsigned int leds_count;
std::string name;
static unsigned char crc8(unsigned char init, unsigned char poly, unsigned char *data, unsigned char len);
};
@@ -1,176 +0,0 @@
/*---------------------------------------------------------*\
| CorsairDominatorPlatinumControllerDetect.cpp |
| |
| Detector for Corsair Dominator Platinum RAM |
| |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "Detector.h"
#include "CorsairDominatorPlatinumController.h"
#include "RGBController_CorsairDominatorPlatinum.h"
#include "SettingsManager.h"
#include "LogManager.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
using namespace std::chrono_literals;
json corsair_dominator_models =
{
{
"CMT",
{
{"name", "Corsair Dominator Platinum"},
{"leds", 12}
}
},
{
"CMH",
{
{"name", "Corsair Vengeance Pro SL"},
{"leds", 10}
}
},
{
"CMN",
{
{"name", "Corsair Vengeance RGB RT"},
{"leds", 10}
}
},
{
"CMG",
{
{"name", "Corsair Vengeance RGB RS"},
{"leds", 6}
}
},
{
"CMP",
{
{"name", "Corsair Dominator Titanium"},
{"leds", 11}
}
}
};
#define CORSAIR_DOMINATOR_PLATINUM_NAME "Corsair Dominator Platinum"
bool TestForCorsairDominatorPlatinumController(i2c_smbus_interface *bus, unsigned char address)
{
int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE);
LOG_DEBUG("[%s] Trying address %02X", CORSAIR_DOMINATOR_PLATINUM_NAME, address);
if(res < 0)
{
LOG_DEBUG("[%s] Failed: res was %04X", CORSAIR_DOMINATOR_PLATINUM_NAME, res);
return false;
}
res = bus->i2c_smbus_read_byte_data(address, 0x43);
if(!(res == 0x1A || res == 0x1B))
{
LOG_DEBUG("[%s] Failed: expected 0x1a or 0x1b, got %04X", CORSAIR_DOMINATOR_PLATINUM_NAME, res);
return false;
}
res = bus->i2c_smbus_read_byte_data(address, 0x44);
if(res != 0x04)
{
LOG_DEBUG("[%s] Failed: expected 0x04, got %04X", CORSAIR_DOMINATOR_PLATINUM_NAME, res);
return false;
}
return true;
}
/******************************************************************************************\
* *
* DetectCorsairDominatorPlatinumControllers *
* *
* Detect Corsair Dominator Platinum controllers on the enumerated I2C busses. *
* *
* bus - pointer to i2c_smbus_interface where Aura device is connected *
* dev - I2C address of Aura device *
* *
\******************************************************************************************/
void DetectCorsairDominatorPlatinumControllers(std::vector<i2c_smbus_interface *> &busses)
{
SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager();
json corsair_dominator_settings = settings_manager->GetSettings("CorsairDominatorSettings");
if(!corsair_dominator_settings.contains("model"))
{
// Set default value
corsair_dominator_settings["model"] = "CMT";
settings_manager->SetSettings("CorsairDominatorSettings", corsair_dominator_settings);
settings_manager->SaveSettings();
}
std::string model = corsair_dominator_settings["model"];
for(unsigned int bus = 0; bus < busses.size(); bus++)
{
IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device)
{
LOG_DEBUG("[%s] Testing bus %d", CORSAIR_DOMINATOR_PLATINUM_NAME, bus);
std::vector<unsigned char> addresses;
for(unsigned char addr = 0x58; addr <= 0x5F; addr++)
{
addresses.push_back(addr);
}
for(unsigned char addr = 0x18; addr <= 0x1F; addr++)
{
addresses.push_back(addr);
}
for(unsigned char addr : addresses)
{
if(TestForCorsairDominatorPlatinumController(busses[bus], addr))
{
unsigned int leds;
std::string name;
if(corsair_dominator_models.contains(model))
{
leds = corsair_dominator_models[model]["leds"];
name = corsair_dominator_models[model]["name"];
}
else
{
leds = corsair_dominator_models["CMT"]["leds"];
name = corsair_dominator_models["CMT"]["name"];
}
LOG_DEBUG("[%s] Model: %s, Leds: %d", CORSAIR_DOMINATOR_PLATINUM_NAME, name.c_str(), leds);
CorsairDominatorPlatinumController* controller = new CorsairDominatorPlatinumController(busses[bus], addr, leds, name);
RGBController_CorsairDominatorPlatinum* rgbcontroller = new RGBController_CorsairDominatorPlatinum(controller);
ResourceManager::get()->RegisterRGBController(rgbcontroller);
}
std::this_thread::sleep_for(10ms);
}
}
else
{
LOG_DEBUG("[%s] Bus %d is not a DRAM bus", CORSAIR_DOMINATOR_PLATINUM_NAME, bus);
}
}
} /* DetectCorsairDominatorPlatinumControllers() */
REGISTER_I2C_DETECTOR(CORSAIR_DOMINATOR_PLATINUM_NAME, DetectCorsairDominatorPlatinumControllers);
@@ -1,134 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_CorsairDominatorPlatinum.cpp |
| |
| RGBController for Corsair Dominator Platinum RAM |
| |
| Erik Gilling (konkers) 25 Sep 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_CorsairDominatorPlatinum.h"
/**------------------------------------------------------------------*\
@name Corsair Dominator Platinum
@category RAM
@type SMBus
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectCorsairDominatorPlatinumControllers
@comment
The Corsair Dominator controller chip can be found on several
Corsair memory sticks which have different LED counts. This can be controlled
by editing the Part Number in OpenRGB.json with values in the below table.
| Part Number | LED Count |
| :---------: | --------: |
| CMG | 6 |
| CMH | 10 |
| CMN | 10 |
| CMT | 12 |
\*-------------------------------------------------------------------*/
RGBController_CorsairDominatorPlatinum::RGBController_CorsairDominatorPlatinum(CorsairDominatorPlatinumController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Corsair";
type = DEVICE_TYPE_DRAM;
description = "Corsair RAM RGB Device";
location = controller->GetDeviceLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.speed_min = 0;
Direct.speed_max = 0;
Direct.speed = 0;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
active_mode = 0;
}
RGBController_CorsairDominatorPlatinum::~RGBController_CorsairDominatorPlatinum()
{
delete controller;
}
void RGBController_CorsairDominatorPlatinum::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zone |
\*---------------------------------------------------------*/
zone new_zone;
new_zone.name = "Corsair RAM Zone";
new_zone.type = ZONE_TYPE_LINEAR;
new_zone.leds_min = controller->GetLEDCount();
new_zone.leds_max = controller->GetLEDCount();
new_zone.leds_count = controller->GetLEDCount();
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
/*---------------------------------------------------------*\
| Set up LEDs |
\*---------------------------------------------------------*/
for(std::size_t led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
{
led new_led;
new_led.name = "Corsair RAM LED ";
new_led.name.append(std::to_string(led_idx));
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_CorsairDominatorPlatinum::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_CorsairDominatorPlatinum::DeviceUpdateLEDs()
{
for(unsigned int led = 0; led < (unsigned int)colors.size(); led++)
{
RGBColor color = colors[led];
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
controller->SetLEDColor(led, red, grn, blu);
}
controller->ApplyColors();
}
void RGBController_CorsairDominatorPlatinum::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_CorsairDominatorPlatinum::UpdateSingleLED(int led)
{
RGBColor color = colors[led];
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
controller->SetLEDColor(led, red, grn, blu);
controller->ApplyColors();
}
void RGBController_CorsairDominatorPlatinum::DeviceUpdateMode()
{
}
@@ -62,6 +62,8 @@ REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO Low Profile", DetectCorsai
REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO TKL Black", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_TKL_B_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO TKL White", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_TKL_W_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K70 Core RGB", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_CORE_RGB_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K70 Core RGB TKL", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_CORE_RGB_TKL_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K70 RGB PRO", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_PRO_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K70 RGB PRO V2", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_PRO_V2_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K70 RGB TKL", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_TKL_PID, 1, 0xFF42);
@@ -152,6 +152,28 @@ keyboard_keymap_overlay_values corsair_K70_TKL_cs_layout
}
};
keyboard_keymap_overlay_values corsair_K70_CORE_TKL_layout
{
KEYBOARD_SIZE::KEYBOARD_SIZE_TKL,
{
corsair_tkl_values,
{
/* Add more regional layout fixes here */
}
},
{
/*-------------------------------------------------------------------------------------------------------------------------------------*\
| Edit Keys |
| Zone, Row, Column, Value, Name, Alternate Name, OpCode, |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
{ 0, 0, 14, 70, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRSC with Mute
{ 0, 0, 15, 71, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove SCLK
{ 0, 0, 16, 72, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PSBK with Volume Potion Up
}
};
keyboard_keymap_overlay_values corsair_k95_layout
{
KEYBOARD_SIZE::KEYBOARD_SIZE_FULL,
@@ -929,6 +951,39 @@ static const corsair_v2_device k70_rgb_tkl_device =
&corsair_K70_TKL_cs_layout
};
/*-------------------------------------------------------------*\
| Corsair K70 Core RGB TKL 1B1C:2B01 |
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 1 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k70_core_rgb_tkl_zone =
{
ZONE_EN_KEYBOARD,
ZONE_TYPE_MATRIX,
6,
17
};
static const corsair_v2_device k70_core_rgb_tkl_device =
{
CORSAIR_K70_CORE_RGB_TKL_PID,
DEVICE_TYPE_KEYBOARD,
6,
17,
{
&k70_core_rgb_tkl_zone,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
},
&corsair_K70_CORE_TKL_layout
};
/*-------------------------------------------------------------*\
| Corsair K70 RGB TKL Champion Series 1B1C:1BB9 |
| |
@@ -1411,6 +1466,7 @@ const corsair_v2_device* corsair_v2_device_list_data[] =
&k60_rgb_pro_tkl_device_b,
&k60_rgb_pro_tkl_device_w,
&k70_core_rgb_device,
&k70_core_rgb_tkl_device,
&k70_rgb_pro_device,
&k70_rgb_pro_v2_device,
&k70_rgb_tkl_device,
@@ -74,6 +74,7 @@ typedef struct
#define CORSAIR_K60_RGB_PRO_TKL_B_PID 0x1BC7
#define CORSAIR_K60_RGB_PRO_TKL_W_PID 0x1BED
#define CORSAIR_K70_CORE_RGB_PID 0x1BFD
#define CORSAIR_K70_CORE_RGB_TKL_PID 0x2B01
#define CORSAIR_K70_RGB_PRO_PID 0x1BC4
#define CORSAIR_K70_RGB_PRO_V2_PID 0x1BB3
#define CORSAIR_K70_RGB_TKL_PID 0x1B73
@@ -1,213 +0,0 @@
/*---------------------------------------------------------*\
| CorsairVengeanceProController.cpp |
| |
| Driver for Corsair Vengeance Pro RGB RAM |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <chrono>
#include "CorsairVengeanceProController.h"
using namespace std::chrono_literals;
CorsairVengeanceProController::CorsairVengeanceProController(i2c_smbus_interface* bus, corsair_dev_id dev)
{
this->bus = bus;
this->dev = dev;
strcpy(device_name, "Corsair Vengeance Pro RGB");
led_count = CORSAIR_PRO_LED_COUNT;
direct_mode = false;
effect_mode = CORSAIR_PRO_MODE_STATIC;
for (unsigned int i = 0; i < led_count; i++)
{
led_red[i] = 0;
led_green[i] = 0;
led_blue[i] = 0;
}
}
CorsairVengeanceProController::~CorsairVengeanceProController()
{
}
std::string CorsairVengeanceProController::GetDeviceName()
{
return(device_name);
}
std::string CorsairVengeanceProController::GetDeviceLocation()
{
std::string return_string(bus->device_name);
char addr[5];
snprintf(addr, 5, "0x%02X", dev);
return_string.append(", address ");
return_string.append(addr);
return("I2C: " + return_string);
}
unsigned int CorsairVengeanceProController::GetLEDCount()
{
return(led_count);
}
unsigned char CorsairVengeanceProController::GetEffect()
{
return(effect_mode);
}
void CorsairVengeanceProController::SetAllColors(unsigned char red, unsigned char green, unsigned char blue)
{
for (unsigned int i = 0; i < led_count; i++)
{
led_red[i] = red;
led_green[i] = green;
led_blue[i] = blue;
}
}
void CorsairVengeanceProController::SetLEDColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue)
{
led_red[led] = red;
led_green[led] = green;
led_blue[led] = blue;
}
void CorsairVengeanceProController::ApplyColors()
{
if(direct_mode)
{
unsigned char full_packet[32];
unsigned char crc_packet[31];
full_packet[0] = 0x0A;
crc_packet[0] = 0x0A;
for (int i = 0; i < 10; i++)
{
crc_packet[(i * 3) + 1] = led_red[i];
full_packet[(i * 3) + 1] = led_red[i];
crc_packet[(i * 3) + 2] = led_green[i];
full_packet[(i * 3) + 2] = led_green[i];
crc_packet[(i * 3) + 3] = led_blue[i];
full_packet[(i * 3) + 3] = led_blue[i];
}
uint8_t footer = CRCPP::CRC::Calculate(crc_packet, 31, CRCPP::CRC::CRC_8());
full_packet[31] = footer;
bus->i2c_smbus_write_block_data(dev, CORSAIR_PRO_DIRECT_COMMAND, 32, full_packet);
}
else
{
bus->i2c_smbus_write_byte_data(dev, 0x26, 0x02);
std::this_thread::sleep_for(1ms);
bus->i2c_smbus_write_byte_data(dev, 0x21, 0x00);
std::this_thread::sleep_for(1ms);
for (int i = 0; i < 10; i++)
{
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, led_red[i]);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, led_green[i]);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, led_blue[i]);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0xFF);
}
bus->i2c_smbus_write_byte_data(dev, 0x82, 0x02);
}
}
void CorsairVengeanceProController::SetEffect(unsigned char mode,
unsigned char speed,
unsigned char direction,
bool random,
unsigned char red1,
unsigned char grn1,
unsigned char blu1,
unsigned char red2,
unsigned char grn2,
unsigned char blu2
)
{
if(mode == effect_mode)
{
return;
}
effect_mode = mode;
direct_mode = (effect_mode == CORSAIR_PRO_MODE_DIRECT);
if(direct_mode)
{
return;
}
bus->i2c_smbus_write_byte_data(dev, 0x26, 0x01);
std::this_thread::sleep_for(1ms);
bus->i2c_smbus_write_byte_data(dev, 0x21, 0x00);
std::this_thread::sleep_for(1ms);
unsigned char random_byte;
if(random)
{
random_byte = CORSAIR_PRO_EFFECT_RANDOM_COLORS;
}
else
{
random_byte = CORSAIR_PRO_EFFECT_CUSTOM_COLORS;
}
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, effect_mode); // Mode
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, speed); // Speed
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, random_byte); // Custom color
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, direction); // Direction
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, red1); // Custom color 1 red
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, grn1); // Custom color 1 green
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, blu1); // Custom color 1 blue
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0xFF);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, red2); // Custom color 2 red
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, grn2); // Custom color 2 green
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, blu2); // Custom color 2 blue
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0xFF);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, CORSAIR_PRO_REG_COMMAND, 0x00);
bus->i2c_smbus_write_byte_data(dev, 0x82, 0x01);
WaitReady();
}
bool CorsairVengeanceProController::WaitReady()
{
int i = 0;
while (bus->i2c_smbus_read_byte_data(dev, 0x41) != 0x00)
{
i++;
std::this_thread::sleep_for(1ms);
}
return false;
}
void CorsairVengeanceProController::SetDirect(bool direct)
{
direct_mode = direct;
}
@@ -1,109 +0,0 @@
/*---------------------------------------------------------*\
| CorsairVengeanceProController.h |
| |
| Driver for Corsair Vengeance Pro RGB RAM |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
#include "CRC.h"
typedef unsigned char corsair_dev_id;
#define CORSAIR_PRO_LED_COUNT ( 10 )
#define CORSAIR_VENGEANCE_RGB_PRO_NAME "Corsair Vengeance RGB PRO"
enum
{
CORSAIR_PRO_REG_COMMAND = 0x20, /* Command write register */
CORSAIR_PRO_DIRECT_COMMAND = 0x31, /* Where it writes direct mode colors */
};
enum
{
CORSAIR_PRO_MODE_DIRECT = 0xDD, /* Arbitrary value to compare against later. Not the actual packet */
CORSAIR_PRO_MODE_COLOR_SHIFT = 0x00, /* Color Shift mode */
CORSAIR_PRO_MODE_COLOR_PULSE = 0x01, /* Color Pulse mode */
CORSAIR_PRO_MODE_RAINBOW_WAVE = 0x03, /* Rainbow Wave mode */
CORSAIR_PRO_MODE_COLOR_WAVE = 0x04, /* Color Wave mode */
CORSAIR_PRO_MODE_VISOR = 0x05, /* Visor mode */
CORSAIR_PRO_MODE_RAIN = 0x06, /* Rain mode */
CORSAIR_PRO_MODE_MARQUEE = 0x07, /* Marquee mode */
CORSAIR_PRO_MODE_RAINBOW = 0x08, /* Rainbow mode */
CORSAIR_PRO_MODE_SEQUENTIAL = 0x09, /* Sequential mode */
CORSAIR_PRO_MODE_STATIC = 0x10, /* Static mode */
CORSAIR_PRO_NUMBER_MODES = 10, /* Number of Corsair Pro modes */
};
enum
{
CORSAIR_PRO_SPEED_SLOW = 0x00, /* Slow speed */
CORSAIR_PRO_SPEED_MEDIUM = 0x01, /* Medium speed */
CORSAIR_PRO_SPEED_FAST = 0x02, /* Fast speed */
};
enum
{
CORSAIR_PRO_EFFECT_RANDOM_COLORS = 0x00, /* Random colors */
CORSAIR_PRO_EFFECT_CUSTOM_COLORS = 0x01, /* Custom colors */
};
enum
{
CORSAIR_PRO_DIRECTION_UP = 0x00, /* Up direction */
CORSAIR_PRO_DIRECTION_DOWN = 0x01, /* Down direction */
CORSAIR_PRO_DIRECTION_LEFT = 0x02, /* Left direction */
CORSAIR_PRO_DIRECTION_RIGHT = 0x03, /* Right direction */
CORSAIR_PRO_DIRECTION_VERTICAL = 0x01, /* Vertical direction */
CORSAIR_PRO_DIRECTION_HORIZONTAL = 0x03, /* Horizontal direction */
};
class CorsairVengeanceProController
{
public:
CorsairVengeanceProController(i2c_smbus_interface* bus, corsair_dev_id dev);
~CorsairVengeanceProController();
std::string GetDeviceName();
std::string GetDeviceLocation();
unsigned int GetLEDCount();
unsigned char GetEffect();
void SetEffect(unsigned char mode,
unsigned char speed,
unsigned char direction,
bool random,
unsigned char red1,
unsigned char grn1,
unsigned char blu1,
unsigned char red2,
unsigned char grn2,
unsigned char blu2
);
void SetAllColors(unsigned char red, unsigned char green, unsigned char blue);
void SetLEDColor(unsigned int led, unsigned char red, unsigned char green, unsigned char blue);
void ApplyColors();
bool WaitReady();
void SetDirect(bool direct);
private:
char device_name[32];
unsigned int led_count;
bool direct_mode;
unsigned char effect_mode;
unsigned char led_red[CORSAIR_PRO_LED_COUNT];
unsigned char led_green[CORSAIR_PRO_LED_COUNT];
unsigned char led_blue[CORSAIR_PRO_LED_COUNT];
i2c_smbus_interface* bus;
corsair_dev_id dev;
};
@@ -1,107 +0,0 @@
/*---------------------------------------------------------*\
| CorsairVengeanceProControllerDetect.cpp |
| |
| Detector for Corsair Vengeance Pro RGB RAM |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "Detector.h"
#include "CorsairVengeanceProController.h"
#include "RGBController_CorsairVengeancePro.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
#include "LogManager.h"
using namespace std::chrono_literals;
/******************************************************************************************\
* *
* TestForCorsairVengeanceProController *
* *
* Tests the given address to see if a Corsair Pro controller exists there. *
* *
\******************************************************************************************/
bool TestForCorsairVengeanceProController(i2c_smbus_interface* bus, unsigned char address)
{
bool pass = false;
int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE);
LOG_DEBUG("[%s] Trying address %02X", CORSAIR_VENGEANCE_RGB_PRO_NAME, address);
if(res >= 0)
{
pass = true;
res = bus->i2c_smbus_read_byte_data(address, 0x43);
if (res != 0x1C)
{
pass = false;
LOG_DEBUG("[%s] Failed: was expecting 0x1C got %02X", CORSAIR_VENGEANCE_RGB_PRO_NAME, res);
}
res = bus->i2c_smbus_read_byte_data(address, 0x44);
if(!((res == 0x03) || (res == 0x04)))
{
pass = false;
LOG_DEBUG("[%s] Failed: was expecting 0x03 or 0x04 got %02X", CORSAIR_VENGEANCE_RGB_PRO_NAME, res);
}
}
else
{
LOG_DEBUG("[%s] Failed: res was %04X", CORSAIR_VENGEANCE_RGB_PRO_NAME, res);
}
std::this_thread::sleep_for(10ms);
return(pass);
} /* TestForCorsairVengeanceProController() */
/******************************************************************************************\
* *
* DetectCorsairVengeanceProControllers *
* *
* Detect Corsair Vengeance Pro controllers on the enumerated I2C busses. *
* *
* bus - pointer to i2c_smbus_interface where Aura device is connected *
* dev - I2C address of Aura device *
* *
\******************************************************************************************/
void DetectCorsairVengeanceProControllers(std::vector<i2c_smbus_interface*> &busses)
{
for(unsigned int bus = 0; bus < busses.size(); bus++)
{
LOG_DEBUG("[%s] Testing bus %d", CORSAIR_VENGEANCE_RGB_PRO_NAME, bus);
IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device)
{
for(unsigned char addr = 0x58; addr <= 0x5F; addr++)
{
if(TestForCorsairVengeanceProController(busses[bus], addr))
{
CorsairVengeanceProController* new_controller = new CorsairVengeanceProController(busses[bus], addr);
RGBController_CorsairVengeancePro* new_rgbcontroller = new RGBController_CorsairVengeancePro(new_controller);
ResourceManager::get()->RegisterRGBController(new_rgbcontroller);
}
}
}
else
{
LOG_DEBUG("[%s] Bus %d is not a DRAM bus", CORSAIR_VENGEANCE_RGB_PRO_NAME, bus);
}
}
} /* DetectCorsairVengeanceProControllers() */
REGISTER_I2C_DETECTOR("Corsair Vengeance Pro", DetectCorsairVengeanceProControllers);
@@ -1,316 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_CorsairVengeancePro.cpp |
| |
| RGBController for Corsair Vengeance Pro RGB RAM |
| |
| Adam Honse (CalcProgrammer1) 30 Jun 2019 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_CorsairVengeancePro.h"
/**------------------------------------------------------------------*\
@name Corsair Vengeance Pro
@category RAM
@type SMBus
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectCorsairVengeanceProControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_CorsairVengeancePro::RGBController_CorsairVengeancePro(CorsairVengeanceProController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Corsair";
type = DEVICE_TYPE_DRAM;
description = "Corsair Vengeance Pro RGB Device";
location = controller->GetDeviceLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = CORSAIR_PRO_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.speed_min = 0;
Direct.speed_max = 0;
Direct.speed = 0;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Static;
Static.name = "Static";
Static.value = CORSAIR_PRO_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Static.speed_min = 0;
Static.speed_max = 0;
Static.speed = 0;
Static.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Static);
mode ColorShift;
ColorShift.name = "Color Shift";
ColorShift.value = CORSAIR_PRO_MODE_COLOR_SHIFT;
ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
ColorShift.speed_min = CORSAIR_PRO_SPEED_SLOW;
ColorShift.speed_max = CORSAIR_PRO_SPEED_FAST;
ColorShift.colors_min = 2;
ColorShift.colors_max = 2;
ColorShift.speed = CORSAIR_PRO_SPEED_SLOW;
ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorShift.colors.resize(2);
modes.push_back(ColorShift);
mode ColorPulse;
ColorPulse.name = "Color Pulse";
ColorPulse.value = CORSAIR_PRO_MODE_COLOR_PULSE;
ColorPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
ColorPulse.speed_min = CORSAIR_PRO_SPEED_SLOW;
ColorPulse.speed_max = CORSAIR_PRO_SPEED_FAST;
ColorPulse.colors_min = 2;
ColorPulse.colors_max = 2;
ColorPulse.speed = CORSAIR_PRO_SPEED_SLOW;
ColorPulse.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorPulse.colors.resize(2);
modes.push_back(ColorPulse);
mode RainbowWave;
RainbowWave.name = "Rainbow Wave";
RainbowWave.value = CORSAIR_PRO_MODE_RAINBOW_WAVE;
RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD;
RainbowWave.speed_min = CORSAIR_PRO_SPEED_SLOW;
RainbowWave.speed_max = CORSAIR_PRO_SPEED_FAST;
RainbowWave.speed = CORSAIR_PRO_SPEED_SLOW;
RainbowWave.direction = MODE_DIRECTION_DOWN;
RainbowWave.color_mode = MODE_COLORS_NONE;
modes.push_back(RainbowWave);
mode ColorWave;
ColorWave.name = "Color Wave";
ColorWave.value = CORSAIR_PRO_MODE_COLOR_WAVE;
ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
ColorWave.speed_min = CORSAIR_PRO_SPEED_SLOW;
ColorWave.speed_max = CORSAIR_PRO_SPEED_FAST;
ColorWave.colors_min = 2;
ColorWave.colors_max = 2;
ColorWave.speed = CORSAIR_PRO_SPEED_SLOW;
ColorWave.direction = MODE_DIRECTION_DOWN;
ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorWave.colors.resize(2);
modes.push_back(ColorWave);
mode Visor;
Visor.name = "Visor";
Visor.value = CORSAIR_PRO_MODE_VISOR;
Visor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_HV | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
Visor.speed_min = CORSAIR_PRO_SPEED_SLOW;
Visor.speed_max = CORSAIR_PRO_SPEED_FAST;
Visor.colors_min = 2;
Visor.colors_max = 2;
Visor.speed = CORSAIR_PRO_SPEED_SLOW;
Visor.direction = MODE_DIRECTION_VERTICAL;
Visor.color_mode = MODE_COLORS_MODE_SPECIFIC;
Visor.colors.resize(2);
modes.push_back(Visor);
mode Rain;
Rain.name = "Rain";
Rain.value = CORSAIR_PRO_MODE_RAIN;
Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
Rain.speed_min = CORSAIR_PRO_SPEED_SLOW;
Rain.speed_max = CORSAIR_PRO_SPEED_FAST;
Rain.colors_min = 2;
Rain.colors_max = 2;
Rain.speed = CORSAIR_PRO_SPEED_SLOW;
Rain.direction = MODE_DIRECTION_DOWN;
Rain.color_mode = MODE_COLORS_MODE_SPECIFIC;
Rain.colors.resize(2);
modes.push_back(Rain);
mode Marquee;
Marquee.name = "Marquee";
Marquee.value = CORSAIR_PRO_MODE_MARQUEE;
Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Marquee.speed_min = CORSAIR_PRO_SPEED_SLOW;
Marquee.speed_max = CORSAIR_PRO_SPEED_FAST;
Marquee.colors_min = 1;
Marquee.colors_max = 1;
Marquee.speed = CORSAIR_PRO_SPEED_SLOW;
Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC;
Marquee.colors.resize(1);
modes.push_back(Marquee);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CORSAIR_PRO_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED;
Rainbow.speed_min = CORSAIR_PRO_SPEED_SLOW;
Rainbow.speed_max = CORSAIR_PRO_SPEED_FAST;
Rainbow.speed = CORSAIR_PRO_SPEED_SLOW;
Rainbow.color_mode = MODE_COLORS_NONE;
modes.push_back(Rainbow);
mode Sequential;
Sequential.name = "Sequential";
Sequential.value = CORSAIR_PRO_MODE_SEQUENTIAL;
Sequential.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
Sequential.speed_min = CORSAIR_PRO_SPEED_SLOW;
Sequential.speed_max = CORSAIR_PRO_SPEED_FAST;
Sequential.colors_min = 1;
Sequential.colors_max = 1;
Sequential.speed = CORSAIR_PRO_SPEED_SLOW;
Sequential.direction = MODE_DIRECTION_DOWN;
Sequential.color_mode = MODE_COLORS_MODE_SPECIFIC;
Sequential.colors.resize(1);
modes.push_back(Sequential);
SetupZones();
active_mode = 9;
}
RGBController_CorsairVengeancePro::~RGBController_CorsairVengeancePro()
{
delete controller;
}
void RGBController_CorsairVengeancePro::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zone |
\*---------------------------------------------------------*/
zone new_zone;
new_zone.name = "Corsair Pro Zone";
new_zone.type = ZONE_TYPE_LINEAR;
new_zone.leds_min = controller->GetLEDCount();
new_zone.leds_max = controller->GetLEDCount();
new_zone.leds_count = controller->GetLEDCount();
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
/*---------------------------------------------------------*\
| Set up LEDs |
\*---------------------------------------------------------*/
for(std::size_t led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
{
led* new_led = new led();
new_led->name = "Corsair Pro LED ";
new_led->name.append(std::to_string(led_idx));
leds.push_back(*new_led);
}
SetupColors();
}
void RGBController_CorsairVengeancePro::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_CorsairVengeancePro::DeviceUpdateLEDs()
{
for(unsigned int led = 0; led < (unsigned int)colors.size(); led++)
{
RGBColor color = colors[led];
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
controller->SetLEDColor(led, red, grn, blu);
}
controller->ApplyColors();
}
void RGBController_CorsairVengeancePro::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_CorsairVengeancePro::UpdateSingleLED(int led)
{
RGBColor color = colors[led];
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
controller->SetLEDColor(led, red, grn, blu);
controller->ApplyColors();
}
void RGBController_CorsairVengeancePro::DeviceUpdateMode()
{
unsigned int corsair_direction = 0;
bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
unsigned char mode_colors[6];
switch(modes[active_mode].direction)
{
case MODE_DIRECTION_LEFT:
corsair_direction = CORSAIR_PRO_DIRECTION_LEFT;
break;
case MODE_DIRECTION_RIGHT:
corsair_direction = CORSAIR_PRO_DIRECTION_RIGHT;
break;
case MODE_DIRECTION_UP:
corsair_direction = CORSAIR_PRO_DIRECTION_UP;
break;
case MODE_DIRECTION_DOWN:
corsair_direction = CORSAIR_PRO_DIRECTION_DOWN;
break;
case MODE_DIRECTION_HORIZONTAL:
corsair_direction = CORSAIR_PRO_DIRECTION_HORIZONTAL;
break;
case MODE_DIRECTION_VERTICAL:
corsair_direction = CORSAIR_PRO_DIRECTION_VERTICAL;
break;
}
mode_colors[0] = 0;
mode_colors[1] = 0;
mode_colors[2] = 0;
mode_colors[3] = 0;
mode_colors[4] = 0;
mode_colors[5] = 0;
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
mode_colors[0] = RGBGetRValue(modes[active_mode].colors[0]);
mode_colors[1] = RGBGetGValue(modes[active_mode].colors[0]);
mode_colors[2] = RGBGetBValue(modes[active_mode].colors[0]);
if(modes[active_mode].colors.size() == 2)
{
mode_colors[3] = RGBGetRValue(modes[active_mode].colors[1]);
mode_colors[4] = RGBGetGValue(modes[active_mode].colors[1]);
mode_colors[5] = RGBGetBValue(modes[active_mode].colors[1]);
}
}
if (modes[active_mode].name == "Direct")
{
controller->SetDirect(true);
}
else
{
controller->SetDirect(false);
}
controller->SetEffect(modes[active_mode].value,
modes[active_mode].speed,
corsair_direction,
random,
mode_colors[0],
mode_colors[1],
mode_colors[2],
mode_colors[3],
mode_colors[4],
mode_colors[5]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
}
@@ -38,6 +38,8 @@ REGISTER_HID_DETECTOR("DeepRGB SIG V4F", DetectDRGBControllers, DRGBV
REGISTER_HID_DETECTOR("Airgoo AG-DRGB04", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_04_V4F_PID);
REGISTER_HID_DETECTOR("Airgoo AG-DRGB16", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_16_V4F_PID);
REGISTER_HID_DETECTOR("Airgoo AG-DRGB08", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_08_PID);
REGISTER_HID_DETECTOR("Airgoo AG-F8-DRGB08", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_08_F08_PID);
REGISTER_HID_DETECTOR("Airgoo AG-F12-DRGB16", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_16_F12_PID);
REGISTER_HID_DETECTOR("DeepRGB L8 V5", DetectDRGBControllers, DRGBV4_VID, DRGB_L8_V5_PID);
@@ -93,6 +93,16 @@ void RGBController_DRGB::SetupZones()
NUM_Channel_led = 256;
Version = 4;
break;
case DRGB_AG_08_PID:
NUM_CHANNELS = 8;
NUM_Channel_led = 256;
Version = 4;
break;
case DRGB_AG_08_F08_PID:
NUM_CHANNELS = 8;
NUM_Channel_led = 256;
Version = 4;
break;
case DRGB_AG_16_V4F_PID:
NUM_CHANNELS = 16;
NUM_Channel_led = 256;
@@ -21,6 +21,8 @@
#define DRGB_SIG_V4F_PID 0x3636
#define DRGB_AG_04_V4F_PID 0x3204
#define DRGB_AG_16_V4F_PID 0x3216
#define DRGB_AG_08_PID 0x3F08
#define DRGB_AG_08_F08_PID 0x3F16
#define DRGB_AG_16_F12_PID 0x3F28
#define DRGB_L8_V5_PID 0x3208
@@ -65,7 +65,7 @@ void DygmaRaiseController::SendDirect(std::vector<RGBColor>colors, size_t led_nu
/*-----------------------------------------------------*\
| Set up led theme packet |
\*-----------------------------------------------------*/
sprintf(serial_buf,"led.theme");
snprintf(serial_buf, MAX_LEN, "led.theme");
int actual_length=9;
/*-----------------------------------------------------*\
@@ -77,20 +77,20 @@ void DygmaRaiseController::SendDirect(std::vector<RGBColor>colors, size_t led_nu
int g = RGBGetGValue(colors[led_idx]);
int b = RGBGetBValue(colors[led_idx]);
sprintf(serial_buf+actual_length," %d",r);
snprintf(serial_buf + actual_length, MAX_LEN - actual_length, " %d", r);
actual_length += val_char_len(r) + 1;
sprintf(serial_buf+actual_length," %d",g);
snprintf(serial_buf + actual_length, MAX_LEN - actual_length, " %d", g);
actual_length += val_char_len(g) + 1;
sprintf(serial_buf+actual_length," %d",b);
snprintf(serial_buf + actual_length, MAX_LEN - actual_length, " %d", b);
actual_length += val_char_len(b) + 1;
}
/*-----------------------------------------------------*\
| Add the final newline |
\*-----------------------------------------------------*/
sprintf(serial_buf+actual_length,"\n");
snprintf(serial_buf + actual_length, MAX_LEN - actual_length, "\n");
actual_length++;
/*-----------------------------------------------------*\
@@ -266,6 +266,21 @@ ENESMBusController::ENESMBusController(ENESMBusInterface* interface, ene_dev_id
led_count = config_table[ENE_CONFIG_LED_COUNT_0107];
}
/*-----------------------------------------------------*\
| AUMA0-E6K5-1114 |
| Found on ASUS ROG MATRIX PLATINUM 5090 |
\*-----------------------------------------------------*/
else if(strcmp(device_version, "AUMA0-E6K5-1114") == 0)
{
direct_reg = ENE_REG_COLORS_DIRECT_V2;
effect_reg = ENE_REG_COLORS_EFFECT_V2;
channel_cfg = ENE_CONFIG_CHANNEL_V2;
/*-------------------------------------------------*\
| Read LED count from configuration table |
\*-------------------------------------------------*/
led_count = config_table[ENE_CONFIG_LED_COUNT_0107];
}
/*-----------------------------------------------------*\
| ROG ARION - ASUS ROG Arion external SSD enclosure |
| This device does not support ENE read, so we fake the |
| device name string if the interface is ROG Arion type.|
@@ -30,10 +30,11 @@ using namespace std::chrono_literals;
#undef interface
#endif
/*----------------------------------------------------------------------*\
| This list contains the available SMBus addresses for mapping ENE RAM |
\*----------------------------------------------------------------------*/
#define ENE_RAM_ADDRESS_COUNT 23
/*---------------------------------------------------------*\
| This list contains the available SMBus addresses for |
| mapping ENE RAM |
\*---------------------------------------------------------*/
#define ENE_RAM_ADDRESS_COUNT (sizeof(ene_ram_addresses) / sizeof(ene_ram_addresses[0]))
static const unsigned char ene_ram_addresses[] =
{
@@ -44,14 +45,7 @@ static const unsigned char ene_ram_addresses[] =
0x74,
0x75,
0x76,
0x78,
0x79,
0x7A,
0x7B,
0x7C,
0x7D,
0x7E,
0x7F,
0x77,
0x4F,
0x66,
0x67,
@@ -62,10 +56,11 @@ static const unsigned char ene_ram_addresses[] =
0x3D
};
/*---------------------------------------------------------------------------------*\
| This list contains the available SMBus addresses for mapping Aura motherboards |
\*---------------------------------------------------------------------------------*/
#define AURA_MOBO_ADDRESS_COUNT 3
/*---------------------------------------------------------*\
| This list contains the available SMBus addresses for |
| mapping Aura motherboards |
\*---------------------------------------------------------*/
#define AURA_MOBO_ADDRESS_COUNT (sizeof(aura_mobo_addresses) / sizeof(aura_mobo_addresses[0]))
static const unsigned char aura_mobo_addresses[] =
{
@@ -220,7 +215,7 @@ void DetectENESMBusDRAMControllers(std::vector<i2c_smbus_interface*> &busses)
{
address_list_idx++;
if(address_list_idx < ENE_RAM_ADDRESS_COUNT)
if(address_list_idx < (int)ENE_RAM_ADDRESS_COUNT)
{
LOG_DEBUG("[ENE SMBus DRAM] Testing address %02X to see if there is a device there", ene_ram_addresses[address_list_idx]);
@@ -232,7 +227,7 @@ void DetectENESMBusDRAMControllers(std::vector<i2c_smbus_interface*> &busses)
}
} while (res >= 0);
if(address_list_idx < ENE_RAM_ADDRESS_COUNT)
if(address_list_idx < (int)ENE_RAM_ADDRESS_COUNT)
{
LOG_DEBUG("[ENE SMBus DRAM] Remapping slot %d to address %02X", slot, ene_ram_addresses[address_list_idx]);
@@ -355,6 +350,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Ti Gaming OC",
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Ti OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060TI_O8G_OC, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Ti OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060TI_O8G_OC_V2, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Ti V2 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060TI_O8G_V2_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Ti V2 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060TI_O8G_V2_2_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_OC, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_WHITE, 0x67);
@@ -462,8 +458,10 @@ REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White",
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_WHITE_2, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG MATRIX PLATINUM GeForce RTX 4090", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_MATRIX_PLATINUM_RTX_4090_24G, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070_O12G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5060_O8G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070_O12G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_5070TI_O16G_GAMING_OC, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5080_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5090_O32G_GAMING, 0x67);
@@ -471,6 +469,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming",
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC BTF", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_BTF, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_WHITE, 0x67);
@@ -502,6 +501,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7700 XT Gaming OC",
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7800 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7800XT_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7800 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7800XT_O16G_GAMING_0606, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7800 XT Gaming White OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7800XT_O16G_WHITE_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7900 GRE Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7900GRE_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7900 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7900XT_020G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7900 XTX Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7900XTX_O24G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 9070 Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_9070_016G_GAMING, 0x67);
@@ -44,7 +44,7 @@ FnaticStreakController::~FnaticStreakController()
std::string FnaticStreakController::GetDeviceLocation()
{
return("HID " + location);
return("HID: " + location);
}
std::string FnaticStreakController::GetNameString()
@@ -230,16 +230,41 @@ void FnaticStreakController::SetLEDsDirect(std::vector<led> leds, std::vector<RG
void FnaticStreakController::SendRGBToDevice()
{
unsigned int total_leds = GetLEDCount();
unsigned int data_size = total_leds * 3;
if(keyboard_type == FNATIC_STREAK_TYPE_65)
{
unsigned char data[64];
memset(data, 0x00, sizeof(data));
/*-----------------------------------------------------*\
| For direct/software control, use command 0x0f |
| This bypasses the profile and allows immediate update |
| The 0x03 subcommand indicates per-key color data |
\*-----------------------------------------------------*/
unsigned char prefix[] = { 0x0f, 0x03 };
SendRequest(prefix, sizeof(prefix), color_buf, data_size);
data[0] = 0x0F;
data[1] = 0x15;
data[7] = 0x0F;
data[8] = 0x03;
for(unsigned int i = 9; i < 25; i++)
{
data[i] = 0xFF;
}
data[25] = color_buf[0];
data[26] = color_buf[1];
data[27] = color_buf[2];
hid_write(dev, data, sizeof(data));
}
else
{
unsigned int total_leds = GetLEDCount();
unsigned int data_size = total_leds * 3;
/*-----------------------------------------------------*\
| For direct/software control, use command 0x0f |
| This bypasses the profile and allows immediate update |
| The 0x03 subcommand indicates per-key color data |
\*-----------------------------------------------------*/
unsigned char prefix[] = { 0x0f, 0x03 };
SendRequest(prefix, sizeof(prefix), color_buf, data_size);
}
}
void FnaticStreakController::SetPulse(unsigned char color_mode, unsigned char r, unsigned char g, unsigned char b, unsigned char speed)
@@ -51,7 +51,8 @@
enum FnaticStreakType
{
FNATIC_STREAK_TYPE_FULL,
FNATIC_STREAK_TYPE_MINI
FNATIC_STREAK_TYPE_MINI,
FNATIC_STREAK_TYPE_65
};
class FnaticStreakController
@@ -26,6 +26,7 @@
#define FNATIC_STREAK_PID 0x0101
#define FNATIC_MINISTREAK_PID 0x0102
#define FNATIC_STREAK65_PID 0x0105
void DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
{
@@ -39,6 +40,10 @@ void DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
{
kb_type = FNATIC_STREAK_TYPE_MINI;
}
else if(info->product_id == FNATIC_STREAK65_PID)
{
kb_type = FNATIC_STREAK_TYPE_65;
}
else
{
kb_type = FNATIC_STREAK_TYPE_FULL;
@@ -53,3 +58,4 @@ void DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
REGISTER_HID_DETECTOR_I("Fnatic Streak", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_STREAK_PID, 1);
REGISTER_HID_DETECTOR_I("Fnatic miniStreak", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_MINISTREAK_PID, 1);
REGISTER_HID_DETECTOR_I("Fnatic Streak65", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_STREAK65_PID, 1);
@@ -37,19 +37,22 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
\*-----------------------------------------------------------------*/
case 0x32:
res = bus->i2c_smbus_read_byte_data(address, 0x00);
if(res == 0x27 || res == 0x26) {
if(res == 0x27 || res == 0x26)
{
res = bus->i2c_smbus_read_byte_data(address, 0x01);
if (res == 0x10 || res == 0x20)
if(res == 0x10 || res == 0x20)
{
pass = true;
}
}
break;
/*-----------------------------------------------------------------*\
| V1 Controller - RTX 3080 |
| V1 Controller |
\*-----------------------------------------------------------------*/
case 0x23:
res = bus->i2c_smbus_read_byte_data(address, 0x00);
if(res == 0x30)
if(res == 0x27 || res == 0x30)
{
pass = true;
}
@@ -60,8 +63,10 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
\*-----------------------------------------------------------------*/
case 0x51:
res = bus->i2c_smbus_read_byte_data(address, 0x00);
if (res == 0x80)
if(res == 0x80)
{
pass = true;
}
break;
}
@@ -1,203 +0,0 @@
/*---------------------------------------------------------*\
| GigabyteRGBFusion2AorusMasterGPUController.cpp |
| |
| Driver for Gigabyte AORUS MASTER GPU with fan ring LEDs |
| |
| Protocol reverse engineered from GCC on Windows |
| Verified on Linux with i2ctransfer 2025-12-30 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "GigabyteRGBFusion2AorusMasterGPUController.h"
#include "LogManager.h"
#include <chrono>
#include <thread>
RGBFusion2AorusMasterGPUController::RGBFusion2AorusMasterGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
}
RGBFusion2AorusMasterGPUController::~RGBFusion2AorusMasterGPUController()
{
}
std::string RGBFusion2AorusMasterGPUController::GetDeviceLocation()
{
std::string return_string(bus->device_name);
char addr[5];
snprintf(addr, 5, "0x%02X", dev);
return_string.append(", address ");
return_string.append(addr);
return("I2C: " + return_string);
}
std::string RGBFusion2AorusMasterGPUController::GetDeviceName()
{
return(name);
}
/*---------------------------------------------------------*\
| Send mode command to select a fan zone |
| Format: 88 01 06 63 08 <zone_id> 00 00 |
| Byte 0: Mode register (0x88) |
| Byte 1: Static mode (0x01) |
| Byte 2: Unknown constant (0x06) |
| Byte 3: Brightness (0x00-0x63) |
| Byte 4: Unknown constant (0x08) |
| Byte 5: Zone selector (0x02/0x05/0x06) |
| Byte 6-7: Padding (0x00) |
\*---------------------------------------------------------*/
void RGBFusion2AorusMasterGPUController::SendModeCommand(uint8_t zone_id, uint8_t brightness)
{
uint8_t data_pkt[8] = {
RGB_FUSION2_AORUS_MASTER_REG_MODE,
RGB_FUSION2_AORUS_MASTER_MODE_STATIC,
0x06,
brightness,
0x08,
zone_id,
0x00,
0x00
};
bus->i2c_write_block(dev, sizeof(data_pkt), data_pkt);
}
/*---------------------------------------------------------*\
| Send color to a register (controls 2 LEDs) |
| Format: <reg> <mode> R1 G1 B1 R2 G2 B2 |
| Byte 0: Register (0xB0-0xBC) |
| Byte 1: Mode byte (0x01 for fans, 0x00 for logo) |
| Byte 2-4: First LED RGB |
| Byte 5-7: Second LED RGB |
\*---------------------------------------------------------*/
void RGBFusion2AorusMasterGPUController::SendColorRegister(uint8_t reg, uint8_t mode_byte, RGBColor color1, RGBColor color2)
{
uint8_t data_pkt[8] = {
reg,
mode_byte,
(uint8_t)RGBGetRValue(color1),
(uint8_t)RGBGetGValue(color1),
(uint8_t)RGBGetBValue(color1),
(uint8_t)RGBGetRValue(color2),
(uint8_t)RGBGetGValue(color2),
(uint8_t)RGBGetBValue(color2)
};
bus->i2c_write_block(dev, sizeof(data_pkt), data_pkt);
}
/*---------------------------------------------------------*\
| Set colors for a fan zone (8 LEDs = 4 registers) |
| Must send mode command before color commands |
| |
| fan_index: 0=left, 1=middle, 2=right |
| colors: Array of 8 RGB colors for the 8 LEDs |
\*---------------------------------------------------------*/
void RGBFusion2AorusMasterGPUController::SetFanColors(uint8_t fan_index, RGBColor colors[8], uint8_t brightness)
{
uint8_t zone_id;
uint8_t base_reg;
switch(fan_index)
{
case 0:
zone_id = RGB_FUSION2_AORUS_MASTER_ZONE_LEFT;
base_reg = RGB_FUSION2_AORUS_MASTER_REG_LEFT_FAN;
break;
case 1:
zone_id = RGB_FUSION2_AORUS_MASTER_ZONE_MIDDLE;
base_reg = RGB_FUSION2_AORUS_MASTER_REG_MIDDLE_FAN;
break;
case 2:
zone_id = RGB_FUSION2_AORUS_MASTER_ZONE_RIGHT;
base_reg = RGB_FUSION2_AORUS_MASTER_REG_RIGHT_FAN;
break;
default:
LOG_ERROR("[%s] Invalid fan index: %d", name.c_str(), fan_index);
return;
}
/*---------------------------------------------------------*\
| CRITICAL: Send mode command with zone ID first |
| Without this, color commands have no effect |
\*---------------------------------------------------------*/
SendModeCommand(zone_id, brightness);
/*---------------------------------------------------------*\
| Delay after mode command - firmware needs time to process |
| the zone selection before accepting color data |
\*---------------------------------------------------------*/
std::this_thread::sleep_for(std::chrono::milliseconds(5));
/*---------------------------------------------------------*\
| Send 4 color registers (2 LEDs each) |
| Register Bx+0: LEDs 0,1 (colors[0], colors[1]) |
| Register Bx+1: LEDs 2,3 (colors[2], colors[3]) |
| Register Bx+2: LEDs 4,5 (colors[4], colors[5]) |
| Register Bx+3: LEDs 6,7 (colors[6], colors[7]) |
\*---------------------------------------------------------*/
for(int reg_offset = 0; reg_offset < 4; reg_offset++)
{
uint8_t reg = base_reg + reg_offset;
int color_idx = reg_offset * 2;
SendColorRegister(reg, 0x01, colors[color_idx], colors[color_idx + 1]);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
/*---------------------------------------------------------*\
| Apply after each zone - required for multi-zone update |
\*---------------------------------------------------------*/
ApplyChanges();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
/*---------------------------------------------------------*\
| Set logo color |
| Format: BC 00 R G B 00 00 00 |
| Note: Logo uses mode byte 0x00, not 0x01 |
\*---------------------------------------------------------*/
void RGBFusion2AorusMasterGPUController::SetLogoColor(RGBColor color)
{
uint8_t data_pkt[8] = {
RGB_FUSION2_AORUS_MASTER_REG_LOGO,
0x00,
(uint8_t)RGBGetRValue(color),
(uint8_t)RGBGetGValue(color),
(uint8_t)RGBGetBValue(color),
0x00,
0x00,
0x00
};
bus->i2c_write_block(dev, sizeof(data_pkt), data_pkt);
}
/*---------------------------------------------------------*\
| Apply all pending changes |
| Format: AA 00 00 00 00 00 00 00 |
\*---------------------------------------------------------*/
void RGBFusion2AorusMasterGPUController::ApplyChanges()
{
uint8_t data_pkt[8] = {
RGB_FUSION2_AORUS_MASTER_REG_APPLY,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
bus->i2c_write_block(dev, sizeof(data_pkt), data_pkt);
}
@@ -1,97 +0,0 @@
/*---------------------------------------------------------*\
| GigabyteRGBFusion2AorusMasterGPUController.h |
| |
| Driver for Gigabyte AORUS MASTER GPU with fan ring LEDs |
| |
| Protocol reverse engineered from GCC on Windows |
| Fan LEDs only illuminate when fans are spinning |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
#include "RGBController.h"
typedef unsigned char rgb_fusion_dev_id;
/*---------------------------------------------------------*\
| Fan zone configuration |
| Each fan has 8 LEDs controlled by 4 registers |
| Each register controls 2 LEDs with dual RGB values |
\*---------------------------------------------------------*/
struct aorus_master_zone_colors
{
RGBColor led_colors[8]; // 8 LEDs per fan (or 1 for logo)
};
/*---------------------------------------------------------*\
| Register definitions |
\*---------------------------------------------------------*/
enum
{
RGB_FUSION2_AORUS_MASTER_REG_MODE = 0x88,
RGB_FUSION2_AORUS_MASTER_REG_APPLY = 0xAA,
RGB_FUSION2_AORUS_MASTER_REG_LEFT_FAN = 0xB0, // B0-B3
RGB_FUSION2_AORUS_MASTER_REG_MIDDLE_FAN = 0xB4, // B4-B7
RGB_FUSION2_AORUS_MASTER_REG_RIGHT_FAN = 0xB8, // B8-BB
RGB_FUSION2_AORUS_MASTER_REG_LOGO = 0xBC,
};
/*---------------------------------------------------------*\
| Fan zone ID values for mode command (byte 5) |
\*---------------------------------------------------------*/
enum
{
RGB_FUSION2_AORUS_MASTER_ZONE_LEFT = 0x02, // IO side fan
RGB_FUSION2_AORUS_MASTER_ZONE_MIDDLE = 0x05, // Center fan
RGB_FUSION2_AORUS_MASTER_ZONE_RIGHT = 0x06, // Far side fan
};
/*---------------------------------------------------------*\
| Mode definitions |
\*---------------------------------------------------------*/
enum
{
RGB_FUSION2_AORUS_MASTER_MODE_STATIC = 0x01,
};
/*---------------------------------------------------------*\
| Speed and brightness |
\*---------------------------------------------------------*/
enum
{
RGB_FUSION2_AORUS_MASTER_BRIGHTNESS_MIN = 0x00,
RGB_FUSION2_AORUS_MASTER_BRIGHTNESS_MAX = 0x63, // 99
};
/*---------------------------------------------------------*\
| Zone count: 3 fans x 8 LEDs + 1 logo = 25 zones |
\*---------------------------------------------------------*/
#define RGB_FUSION_2_AORUS_MASTER_FAN_LEDS 8
#define RGB_FUSION_2_AORUS_MASTER_TOTAL_ZONES 25
class RGBFusion2AorusMasterGPUController
{
public:
RGBFusion2AorusMasterGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name);
~RGBFusion2AorusMasterGPUController();
std::string GetDeviceLocation();
std::string GetDeviceName();
void SetFanColors(uint8_t fan_index, RGBColor colors[8], uint8_t brightness);
void SetLogoColor(RGBColor color);
void ApplyChanges();
private:
i2c_smbus_interface* bus;
rgb_fusion_dev_id dev;
std::string name;
void SendModeCommand(uint8_t zone_id, uint8_t brightness);
void SendColorRegister(uint8_t reg, uint8_t mode_byte, RGBColor color1, RGBColor color2);
};
@@ -1,82 +0,0 @@
/*---------------------------------------------------------*\
| GigabyteRGBFusion2AorusMasterGPUControllerDetect.cpp |
| |
| Detector for Gigabyte AORUS MASTER GPU |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <stdio.h>
#include "Detector.h"
#include "GigabyteRGBFusion2AorusMasterGPUController.h"
#include "i2c_smbus.h"
#include "LogManager.h"
#include "pci_ids.h"
#include "RGBController_GigabyteRGBFusion2AorusMasterGPU.h"
#define GIGABYTEGPU_CONTROLLER_NAME_AORUS_MASTER "Gigabyte RGB Fusion2 AORUS MASTER GPU"
bool TestForGigabyteRGBFusion2AorusMasterGPUController(i2c_smbus_interface* bus, unsigned char address)
{
bool pass = false;
int res, pktsz;
const int read_sz = 4;
const int write_sz = 8;
uint8_t data_pkt[write_sz] = { 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t data_readpkt[read_sz] = {};
res = bus->i2c_write_block(address, write_sz, data_pkt);
if(res < 0)
{
LOG_DEBUG("[%s] Write probe failed at address 0x%02X", GIGABYTEGPU_CONTROLLER_NAME_AORUS_MASTER, address);
return false;
}
pktsz = read_sz;
res = bus->i2c_read_block(address, &pktsz, data_readpkt);
/*-----------------------------------------------------*\
| All RGB Fusion 2 responses start with 0xAB |
| RTX 5080 AORUS MASTER response: 0xAB 0x10 0x52 0x0B |
\*-----------------------------------------------------*/
if(res >= 0 && data_readpkt[0] == 0xAB)
{
pass = true;
LOG_DEBUG("[%s] Detected at address 0x%02X with response: 0x%02X 0x%02X 0x%02X 0x%02X",
GIGABYTEGPU_CONTROLLER_NAME_AORUS_MASTER, address,
data_readpkt[0], data_readpkt[1], data_readpkt[2], data_readpkt[3]);
}
else
{
std::string text = "";
for(int idx = 0; idx < read_sz; ++idx)
{
char str[6];
snprintf(str, 6, " 0x%02X", data_readpkt[idx]);
text.append(str);
}
LOG_DEBUG("[%s] at address 0x%02X invalid. Expected 0xAB [0x*] but received:%s",
GIGABYTEGPU_CONTROLLER_NAME_AORUS_MASTER, address, text.c_str());
}
return(pass);
}
void DetectGigabyteRGBFusion2AorusMasterGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
if(TestForGigabyteRGBFusion2AorusMasterGPUController(bus, i2c_addr))
{
RGBFusion2AorusMasterGPUController* controller = new RGBFusion2AorusMasterGPUController(bus, i2c_addr, name);
RGBController_RGBFusion2AorusMasterGPU* rgb_controller = new RGBController_RGBFusion2AorusMasterGPU(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
/*---------------------------------------------------------*\
| Nvidia GPUs |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER", DetectGigabyteRGBFusion2AorusMasterGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_16G_SUB_DEV, 0x71);
@@ -1,180 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_GigabyteRGBFusion2AorusMasterGPU.cpp |
| |
| RGBController for Gigabyte AORUS MASTER GPU |
| |
| Each fan has 8 individually addressable LEDs |
| Plus 1 logo LED = 25 total LEDs |
| |
| Note: Fan LEDs only illuminate when fans are spinning |
| Use nvidia-settings to force fans on for testing |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_GigabyteRGBFusion2AorusMasterGPU.h"
#include "LogManager.h"
/**------------------------------------------------------------------*\
@name Gigabyte AORUS MASTER GPU
@category GPU
@type I2C
@save :white_check_mark:
@direct :white_check_mark:
@effects :x:
@detectors DetectGigabyteRGBFusion2AorusMasterGPUControllers
@comment Fan LEDs only work when fans are spinning. Each fan has 8
individually addressable LEDs. Protocol uses zone-based
mode commands before color commands.
\*-------------------------------------------------------------------*/
RGBController_RGBFusion2AorusMasterGPU::RGBController_RGBFusion2AorusMasterGPU(RGBFusion2AorusMasterGPUController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Gigabyte";
description = "Gigabyte AORUS MASTER GPU with Fan Ring LEDs";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
mode Direct;
Direct.name = "Direct";
Direct.value = RGB_FUSION2_AORUS_MASTER_MODE_STATIC;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness_min = RGB_FUSION2_AORUS_MASTER_BRIGHTNESS_MIN;
Direct.brightness_max = RGB_FUSION2_AORUS_MASTER_BRIGHTNESS_MAX;
Direct.brightness = RGB_FUSION2_AORUS_MASTER_BRIGHTNESS_MAX;
modes.push_back(Direct);
SetupZones();
}
RGBController_RGBFusion2AorusMasterGPU::~RGBController_RGBFusion2AorusMasterGPU()
{
delete controller;
}
void RGBController_RGBFusion2AorusMasterGPU::SetupZones()
{
/*---------------------------------------------------------*\
| Create 3 fan zones with 8 LEDs each (linear zones) |
\*---------------------------------------------------------*/
const char* fan_names[] = { "Left Fan", "Middle Fan", "Right Fan" };
for(int fan_idx = 0; fan_idx < 3; fan_idx++)
{
zone fan_zone;
fan_zone.name = fan_names[fan_idx];
fan_zone.type = ZONE_TYPE_LINEAR;
fan_zone.leds_min = 8;
fan_zone.leds_max = 8;
fan_zone.leds_count = 8;
fan_zone.matrix_map = NULL;
zones.push_back(fan_zone);
/*-----------------------------------------------------*\
| Create 8 LEDs for this fan zone |
\*-----------------------------------------------------*/
for(int led_idx = 0; led_idx < 8; led_idx++)
{
led new_led;
new_led.name = fan_names[fan_idx];
new_led.name.append(" LED ");
new_led.name.append(std::to_string(led_idx + 1));
leds.push_back(new_led);
}
}
/*---------------------------------------------------------*\
| Create logo zone with 1 LED |
\*---------------------------------------------------------*/
zone logo_zone;
logo_zone.name = "Logo";
logo_zone.type = ZONE_TYPE_SINGLE;
logo_zone.leds_min = 1;
logo_zone.leds_max = 1;
logo_zone.leds_count = 1;
logo_zone.matrix_map = NULL;
zones.push_back(logo_zone);
led logo_led;
logo_led.name = "Logo";
leds.push_back(logo_led);
SetupColors();
}
void RGBController_RGBFusion2AorusMasterGPU::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_RGBFusion2AorusMasterGPU::DeviceUpdateLEDs()
{
uint8_t brightness = modes[active_mode].brightness;
/*---------------------------------------------------------*\
| Update each fan zone |
| LED indices: 0-7 (left), 8-15 (middle), 16-23 (right) |
\*---------------------------------------------------------*/
for(int fan_idx = 0; fan_idx < 3; fan_idx++)
{
RGBColor fan_colors[8];
int base_led_idx = fan_idx * 8;
for(int led_idx = 0; led_idx < 8; led_idx++)
{
fan_colors[led_idx] = colors[base_led_idx + led_idx];
}
controller->SetFanColors(fan_idx, fan_colors, brightness);
}
/*---------------------------------------------------------*\
| Update logo (LED index 24) |
\*---------------------------------------------------------*/
controller->SetLogoColor(colors[24]);
/*---------------------------------------------------------*\
| Apply all changes |
\*---------------------------------------------------------*/
controller->ApplyChanges();
}
void RGBController_RGBFusion2AorusMasterGPU::UpdateZoneLEDs(int /*zone*/)
{
/*---------------------------------------------------------*\
| For simplicity, update all LEDs when any zone changes |
| The protocol requires sequential updates anyway |
\*---------------------------------------------------------*/
DeviceUpdateLEDs();
}
void RGBController_RGBFusion2AorusMasterGPU::UpdateSingleLED(int /*led*/)
{
/*---------------------------------------------------------*\
| For simplicity, update all LEDs when any LED changes |
| The protocol requires mode command + color sequence |
\*---------------------------------------------------------*/
DeviceUpdateLEDs();
}
void RGBController_RGBFusion2AorusMasterGPU::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
void RGBController_RGBFusion2AorusMasterGPU::DeviceSaveMode()
{
/*---------------------------------------------------------*\
| Apply command also saves to device memory |
\*---------------------------------------------------------*/
controller->ApplyChanges();
}
@@ -15,11 +15,12 @@
using namespace std::chrono_literals;
RGBFusion2BlackwellGPUController::RGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name)
RGBFusion2BlackwellGPUController::RGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name, int gpu_layout)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
this->bus = bus;
this->dev = dev;
this->name = dev_name;
this->gpu_layout = gpu_layout;
}
RGBFusion2BlackwellGPUController::~RGBFusion2BlackwellGPUController()
@@ -51,7 +52,7 @@ void RGBFusion2BlackwellGPUController::SaveConfig()
void RGBFusion2BlackwellGPUController::SetMode(uint8_t type, uint8_t zone, uint8_t mode, fusion2_config zone_config)
{
if(zone_config.numberOfColors == 0 && zone < RGB_FUSION_2_BLACKWELL_GPU_NUMBER_OF_ZONES)
this->zone_color[zone] = zone_config.colors[zone];
this->zone_color[zone] = zone_config.colors[0];
/************************************************************************************\
* *
@@ -67,6 +68,11 @@ void RGBFusion2BlackwellGPUController::SetMode(uint8_t type, uint8_t zone, uint8
if(zone_config.numberOfColors > 0)
{
int currentPos = 12;
if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT)
{
currentPos = 11;
}
for(uint8_t i = 0; i < zone_config.numberOfColors; i++)
{
zone_pkt[currentPos + 0] = RGBGetRValue(zone_config.colors[i]);
@@ -44,6 +44,7 @@ enum
RGB_FUSION2_BLACKWELL_GPU_MODE_COLOR_SHIFT = 0x08, // Not available to Eagle/Aero
RGB_FUSION2_BLACKWELL_GPU_MODE_TRICOLOR = 0x09, // Available to Waterforce
RGB_FUSION2_BLACKWELL_GPU_MODE_DAZZLE = 0x0A, // Not available to Eagle/Aero/Waterforce
RGB_FUSION2_BLACKWELL_GPU_MODE_CLAWS = 0x0C, // Available to AORUS 5080 MASTER
};
enum
@@ -61,16 +62,17 @@ enum
enum
{
RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE = 0,
RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT = 1,
RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT = 2,
RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT = 3,
RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE = 0,
RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT = 1,
RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT = 2,
RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT = 3,
RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT = 4,
};
class RGBFusion2BlackwellGPUController
{
public:
RGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name);
RGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name, int gpu_layout);
~RGBFusion2BlackwellGPUController();
RGBColor zone_color[RGB_FUSION_2_BLACKWELL_GPU_NUMBER_OF_ZONES];
@@ -87,4 +89,6 @@ private:
i2c_smbus_interface* bus;
rgb_fusion_dev_id dev;
std::string name;
int gpu_layout;
};
@@ -52,6 +52,7 @@ bool TestForGigabyteRGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, u
//GeForce RTX 5070 Ti Eagle OC 16G 0x01 0x01 0x01 0x00
//GeForce RTX 5070 Ti Gaming OC 16G 0x01 0x01 0x01 0x00
//GeForce RTX 5070 Gaming OC 12G 0x01 0x01 0x01 0x00
//GeForce RTX 5080 AORUS MASTER 16G 0x01 0x01 0x01 0x10
if(res < 0 || data_readpkt[0] != 0x01 || data_readpkt[1] != 0x01 || data_readpkt[2] != 0x01)
{
@@ -89,7 +90,7 @@ void DetectGigabyteRGBFusion2BlackwellGPUControllers(i2c_smbus_interface* bus, u
// Check for RGB Fusion2 controller
if(TestForGigabyteRGBFusion2BlackwellGPUController(bus, i2c_addr))
{
RGBFusion2BlackwellGPUController* controller = new RGBFusion2BlackwellGPUController(bus, i2c_addr, name);
RGBFusion2BlackwellGPUController* controller = new RGBFusion2BlackwellGPUController(bus, i2c_addr, name, led_zones);
RGBController_RGBFusion2BlackwellGPU* rgb_controller = new RGBController_RGBFusion2BlackwellGPU(controller, led_zones);
ResourceManager::get()->RegisterRGBController(rgb_controller);
@@ -163,6 +164,24 @@ void DetectGigabyteRGBFusion2BlackwellAorusWaterforceLayoutGPUControllers(i2c_sm
DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT);
} /* DetectGigabyteRGBFusion2BlackwellAorusWaterforceLayoutGPUControllers() */
/*******************************************************************************************\
* *
* DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers *
* *
* Detect GigabyteRGB Fusion2 controllers with AORUS waterforce layout on the *
* enumerated I2C busses. *
* *
* bus - pointer to i2c_smbus_interface where RGB Fusion2 device is connected *
* dev - I2C address of RGB Fusion2 device *
* *
\*******************************************************************************************/
void DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT);
} /* DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers() */
/*-----------------------------------------*\
| Nvidia GPUs |
\*-----------------------------------------*/
@@ -177,8 +196,10 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Aero OC",
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_AERO_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellAorusWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER ICE", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV1, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV2, 0x75);
@@ -193,6 +214,7 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9060 XT GAMING",
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9060 XT GAMING OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI44_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9060XT_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 9070 XT Elite", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX9070XT_ELITE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC ICE", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_16G_SUB_DEV, 0x75);
@@ -10,3 +10,4 @@
#pragma once
#define RGB_FUSION_2_BLACKWELL_GPU_NUMBER_OF_ZONES 6
#define RGB_FUSION_2_BLACKWELL_AORUS_MASTER_FAN_LEDS 8
@@ -106,7 +106,7 @@ RGBController_RGBFusion2BlackwellGPU::RGBController_RGBFusion2BlackwellGPU(RGBFu
SpectrumCycle.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
modes.push_back(SpectrumCycle);
if(led_layout == RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT || led_layout == RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT || led_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT)
if(led_layout != RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE)
{
mode Wave;
Wave.name = "Wave";
@@ -150,26 +150,53 @@ RGBController_RGBFusion2BlackwellGPU::RGBController_RGBFusion2BlackwellGPU(RGBFu
ColorShift.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
modes.push_back(ColorShift);
/* Disabled Dazzle as it seems to only execute once, would need to loop it maybe?
* Not for Waterforce
mode Dazzle;
Dazzle.name = "Dazzle";
Dazzle.value = RGB_FUSION2_BLACKWELL_GPU_MODE_DAZZLE;
Dazzle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
Dazzle.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST;
Dazzle.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST;
Dazzle.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL;
Dazzle.color_mode = MODE_COLORS_MODE_SPECIFIC;
Dazzle.colors_min = 1;
Dazzle.colors_max = 8;
Dazzle.colors.resize(8);
Dazzle.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN;
Dazzle.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
Dazzle.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
modes.push_back(Dazzle);*/
if(led_layout != RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT)
{
mode Dazzle;
Dazzle.name = "Dazzle";
Dazzle.value = RGB_FUSION2_BLACKWELL_GPU_MODE_DAZZLE;
Dazzle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
Dazzle.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST;
Dazzle.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST;
Dazzle.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL;
Dazzle.color_mode = MODE_COLORS_MODE_SPECIFIC;
Dazzle.colors_min = 1;
Dazzle.colors_max = 8;
Dazzle.colors.resize(8);
Dazzle.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN;
Dazzle.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
Dazzle.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
modes.push_back(Dazzle);
}
}
SetupZones();
if(led_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT)
{
mode Claws;
Claws.name = "Claws";
Claws.value = RGB_FUSION2_BLACKWELL_GPU_MODE_CLAWS;
Claws.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
Claws.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST;
Claws.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST;
Claws.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL;
Claws.color_mode = MODE_COLORS_MODE_SPECIFIC;
Claws.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN;
Claws.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
Claws.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
modes.push_back(Claws);
for(size_t i = 0; i < modes.size(); i++)
{
if(modes[i].color_mode == MODE_COLORS_PER_LED)
{
modes[i].colors_min = 1;
modes[i].colors_max = RGB_FUSION_2_BLACKWELL_AORUS_MASTER_FAN_LEDS;
modes[i].colors.resize(RGB_FUSION_2_BLACKWELL_AORUS_MASTER_FAN_LEDS);
}
}
}
RGBController_RGBFusion2BlackwellGPU::SetupZones();
}
RGBController_RGBFusion2BlackwellGPU::~RGBController_RGBFusion2BlackwellGPU()
@@ -322,6 +349,56 @@ void RGBController_RGBFusion2BlackwellGPU::SetupZones()
zones.push_back(new_zone);
}
}
else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT)
{
const char * fan_names[] = { "Right Fan", "Left Fan", "Middle Fan" };
for(int i = 0; i < 3; i++)
{
zone fan_zone;
fan_zone.name = fan_names[i];
fan_zone.type = ZONE_TYPE_LINEAR;
fan_zone.leds_min = RGB_FUSION_2_BLACKWELL_AORUS_MASTER_FAN_LEDS;
fan_zone.leds_max = RGB_FUSION_2_BLACKWELL_AORUS_MASTER_FAN_LEDS;
fan_zone.leds_count = RGB_FUSION_2_BLACKWELL_AORUS_MASTER_FAN_LEDS;
fan_zone.matrix_map = NULL;
zones.push_back(fan_zone);
for(unsigned int led_idx = 0; led_idx < fan_zone.leds_count; led_idx++)
{
led new_led;
new_led.name = fan_names[i];
new_led.name.append(" LED ");
new_led.name.append(std::to_string(led_idx + 1));
leds.push_back(new_led);
}
}
zone side_logo;
side_logo.name = "Side Logo";
side_logo.type = ZONE_TYPE_SINGLE;
side_logo.leds_min = 1;
side_logo.leds_max = 1;
side_logo.leds_count = 1;
side_logo.matrix_map = NULL;
zones.push_back(side_logo);
led logo_led;
logo_led.name = "Side Logo";
leds.push_back(logo_led);
zone top_logo;
top_logo.name = "Top Logo";
top_logo.type = ZONE_TYPE_SINGLE;
top_logo.leds_min = 1;
top_logo.leds_max = 1;
top_logo.leds_count = 1;
top_logo.matrix_map = NULL;
zones.push_back(top_logo);
led top_led;
top_led.name = "Top Logo";
leds.push_back(top_led);
}
SetupColors();
}
@@ -336,7 +413,6 @@ void RGBController_RGBFusion2BlackwellGPU::ResizeZone(int /*zone*/, int /*new_si
void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateLEDs()
{
fusion2_config zone_config;
zone_config.brightness = modes[active_mode].brightness;
zone_config.speed = modes[active_mode].speed;
zone_config.direction = modes[active_mode].direction;
@@ -366,6 +442,10 @@ void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateLEDs()
gpu_zones = 5; // Hardware zones 0-4, but zone 0 is skipped
break;
case RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT:
gpu_zones = 6; // Zones 4 and 5 refer to ui zone 4
break;
default:
LOG_TRACE("[%s] Invalid GPU layout (%d) when updating LEDs.", name.c_str(), gpu_layout);
return; // should not happen
@@ -392,19 +472,51 @@ void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateLEDs()
}
ui_zone_idx = zone_idx - 1; // Map: HW zone 1->UI zone 0, HW zone 2->UI zone 1, HW zone 3->UI zone 2, HW zone 4->UI zone 3
}
else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT)
{
if(zone_idx == 5)
{
ui_zone_idx = zone_idx - 1; // Map: HW zone 5->UI zone 4
}
}
if(ui_zone_idx >= zones.size())
{
zone_config.colors[hardware_zone_idx] = colors.back();
zone_config.colors[0] = colors.back();
}
else
{
zone_config.colors[hardware_zone_idx] = colors[ui_zone_idx];
/*---------------------------------------------------------*\
| Equivalent of: |
| zone_config.colors[0] = colors[ui_zone_idx]; |
| when all zones have 1 led. |
\*---------------------------------------------------------*/
uint8_t led_start = 0;
for(uint8_t i = 0; i < ui_zone_idx; i++)
{
led_start += zones[i].leds_count;
}
for(unsigned int i = 0; i < zones[ui_zone_idx].leds_count; i++)
{
zone_config.colors[i] = colors[led_start + i];
}
/*---------------------------------------------------------*\
| If not all led are the same color, then we must pass all |
| led colors in the i2c write. |
\*---------------------------------------------------------*/
if(!std::all_of(zone_config.colors, zone_config.colors + zones[ui_zone_idx].leds_count, [first = zone_config.colors[0]](RGBColor x) { return x == first; }))
{
zone_config.numberOfColors = zones[ui_zone_idx].leds_count;
}
}
for(uint8_t i = 0; i < zone_config.numberOfColors; i++) // specific for MODE_COLORS_MODE_SPECIFIC
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
zone_config.colors[i] = modes[active_mode].colors[i];
for(uint8_t i = 0; i < zone_config.numberOfColors; i++) // specific for MODE_COLORS_MODE_SPECIFIC
{
zone_config.colors[i] = modes[active_mode].colors[i];
}
}
controller->SetZone(hardware_zone_idx, modes[active_mode].value, zone_config);
@@ -193,8 +193,11 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7700 XT GAMING OC",
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7800 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7800XT_GAMING_OC_16G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 GRE GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900GRE_GAMING_OC_16G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XT_GAMING_OC_20G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XTX GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XTX_GAMING_OC_24G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 7900 XTX ELITE 24G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX7900XTX_ELITE_24G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6750 XT ELITE 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX_6750_XT_ELITE_12G_SUB_DEV, 0x70);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6900 XT EXTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, GIGABYTE_SUB_VEN, GIGABYTE_RX6900XT_XTREME_WATERFORCE_WB_SUB_DEV, 0x70);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 9070 XT Elite", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX9070XT_ELITE_16G_SUB_DEV, 0x73);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_16G_SUB_DEV, 0x73);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC ICE", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_ICE_16G_SUB_DEV, 0x73);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070_GAMING_OC_16G_SUB_DEV, 0x73);
@@ -2065,6 +2065,51 @@ static const gb_fusion2_device x570_aorus_ultra_device =
"X570 AORUS ULTRA",
};
/*-------------------------------------------------------------*\
| X570_AORUS_XTREME 048D:8297 |
| |
| Zone "Digital LED 1" : Linear |
| Zone "Digital LED 2" : Linear |
| Zone "Back I/O" : Single |
| Zone "PCIe" : Single |
| Zone "CPU Header" : Single |
\*-------------------------------------------------------------*/
static const gb_fusion2_zone xtreme_back_io_zone =
{
LED3,
1,
1,
"Back I/O",
};
static const gb_fusion2_zone xtreme_cpu_hdr_zone =
{
LED7,
1,
1,
"CPU Header",
};
static gb_fusion2_layout x570_aorus_xtreme_layout =
{
&common_d_led1_zone,
&common_d_led2_zone,
&xtreme_back_io_zone,
&common_pcie_led4_zone,
&xtreme_cpu_hdr_zone,
nullptr,
nullptr,
nullptr
};
static const gb_fusion2_device x570_aorus_xtreme_device =
{
&x570_aorus_xtreme_layout,
0xCDE4CFFE,
1,
"X570 AORUS XTREME",
};
/*-------------------------------------------------------------------------*\
| Generic Layout (Used when no match found) |
\*-------------------------------------------------------------------------*/
@@ -3831,6 +3876,7 @@ const gb_fusion2_device* gb_fusion2_device_list_data[] =
&x570_aorus_pro_device,
&x570_aorus_pro_wifi_device,
&x570_aorus_ultra_device,
&x570_aorus_xtreme_device,
&x570i_aorus_pro_wifi_device,
&z390_aorus_master_cf_device,
@@ -105,6 +105,7 @@ void DetectGigabyteRGBFusionGPUControllers(i2c_smbus_interface* bus, uint8_t i2c
}
} /* DetectGigabyteRGBFusionGPUControllers() */
REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX 1050 G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050_G1_GAMING_SUB_DEV, 0x47);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1050 Ti G1 Gaming Rev A1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050TI_G1_GAMING_SUB_DEV, 0x47);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1050 Ti G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050TI_G1_GAMING_SUB_DEV, 0x48);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_G1_GAMING_SUB_DEV, 0x48);
@@ -91,7 +91,7 @@ void RGBController_HPOmenLaptopWMI_Windows::SetupZones()
SetupColors();
}
void RGBController_HPOmenLaptopWMI_Windows::ResizeZone(int zone, int new_size)
void RGBController_HPOmenLaptopWMI_Windows::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*-----------------------------------------------------*\
| Not Supported |
@@ -106,7 +106,7 @@ void RGBController_HPOmenLaptopWMI_Windows::DeviceUpdateLEDs()
controller->setColors(this->colors);
}
void RGBController_HPOmenLaptopWMI_Windows::UpdateZoneLEDs(int zone)
void RGBController_HPOmenLaptopWMI_Windows::UpdateZoneLEDs(int /*zone*/)
{
/*-----------------------------------------------------*\
| Set new colors |
@@ -114,7 +114,7 @@ void RGBController_HPOmenLaptopWMI_Windows::UpdateZoneLEDs(int zone)
controller->setColors(this->colors);
}
void RGBController_HPOmenLaptopWMI_Windows::UpdateSingleLED(int led)
void RGBController_HPOmenLaptopWMI_Windows::UpdateSingleLED(int /*led*/)
{
/*-----------------------------------------------------*\
| Set new colors |
@@ -17,7 +17,7 @@ HyperXAlloyOrigins60and65Controller::HyperXAlloyOrigins60and65Controller(hid_dev
{
dev = dev_handle;
location = path;
dev_name = name;
name = dev_name;
}
HyperXAlloyOrigins60and65Controller::~HyperXAlloyOrigins60and65Controller()
@@ -0,0 +1,121 @@
/*---------------------------------------------------------*\
| HyperXEve1800Controller.cpp |
| |
| Driver for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXEve1800Controller.h"
#include "StringUtils.h"
HyperXEve1800Controller::HyperXEve1800Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXEve1800Controller::~HyperXEve1800Controller()
{
hid_close(dev);
}
std::string HyperXEve1800Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string HyperXEve1800Controller::GetNameString()
{
return(name);
}
std::string HyperXEve1800Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXEve1800Controller::SetBrightness(unsigned int brightness)
{
unsigned char buf[65];
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x40;
buf[0x01] = 0x01;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
buf[0x04] = brightness & 0xFF;
hid_write(dev, buf, 65);
}
void HyperXEve1800Controller::SetLEDsDirect(std::vector<RGBColor> colors)
{
SendDirectInitialization();
if(colors.empty())
{
RGBColor temp = 0x00000000;
SendDirectColorPacket(&temp, 1);
}
else
{
SendDirectColorPacket(&colors[0], (unsigned int)colors.size());
}
}
void HyperXEve1800Controller::SendDirectInitialization()
{
unsigned char buf[65];
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x44;
buf[0x01] = 0x01;
buf[0x02] = 0x04;
buf[0x03] = 0x00;
hid_write(dev, buf, 65);
}
void HyperXEve1800Controller::SendDirectColorPacket(RGBColor* color_data, unsigned int color_count)
{
unsigned char buf[65];
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x44;
buf[0x01] = 0x02;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
/*-----------------------------------------------------*\
| The Eve 1800 exposes 10 lighting zones, but this |
| report format can carry up to 20 RGB triplets. |
\*-----------------------------------------------------*/
if(color_count > 20)
{
color_count = 20;
}
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
{
buf[4 + (color_idx * 3)] = RGBGetRValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 1] = RGBGetGValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 2] = RGBGetBValue(color_data[color_idx]);
}
hid_write(dev, buf, 65);
}
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| HyperXEve1800Controller.h |
| |
| Driver for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
class HyperXEve1800Controller
{
public:
HyperXEve1800Controller(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXEve1800Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetBrightness(unsigned int brightness);
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
void SendDirectColorPacket(RGBColor* color_data, unsigned int color_count);
};
@@ -0,0 +1,127 @@
/*---------------------------------------------------------*\
| RGBController_HyperXEve1800.cpp |
| |
| RGBController for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_HyperXEve1800.h"
using namespace std::chrono_literals;
#define HYPERX_EVE_1800_BRIGHTNESS_MIN 0x00
#define HYPERX_EVE_1800_BRIGHTNESS_MAX 0xFF
#define HYPERX_EVE_1800_ZONE_COUNT 10
/**------------------------------------------------------------------*\
@name HyperX Eve 1800
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXEve1800
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXEve1800::RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Eve 1800 Keyboard Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Direct.brightness_min = HYPERX_EVE_1800_BRIGHTNESS_MIN;
Direct.brightness_max = HYPERX_EVE_1800_BRIGHTNESS_MAX;
Direct.brightness = HYPERX_EVE_1800_BRIGHTNESS_MAX;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXEve1800::KeepaliveThread, this);
}
RGBController_HyperXEve1800::~RGBController_HyperXEve1800()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
delete controller;
}
void RGBController_HyperXEve1800::SetupZones()
{
zone new_zone;
new_zone.name = "Keyboard";
new_zone.type = ZONE_TYPE_LINEAR;
new_zone.leds_min = HYPERX_EVE_1800_ZONE_COUNT;
new_zone.leds_max = HYPERX_EVE_1800_ZONE_COUNT;
new_zone.leds_count = HYPERX_EVE_1800_ZONE_COUNT;
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
{
led new_led;
new_led.name = "Zone ";
new_led.name.append(std::to_string(led_idx + 1));
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXEve1800::ResizeZone(int /*zone*/, int /*new_size*/)
{
}
void RGBController_HyperXEve1800::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(colors);
last_update_time = std::chrono::steady_clock::now();
}
void RGBController_HyperXEve1800::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXEve1800::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXEve1800::DeviceUpdateMode()
{
controller->SetBrightness(modes[active_mode].brightness);
DeviceUpdateLEDs();
}
void RGBController_HyperXEve1800::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);
}
}
@@ -0,0 +1,39 @@
/*---------------------------------------------------------*\
| RGBController_HyperXEve1800.h |
| |
| RGBController for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXEve1800Controller.h"
class RGBController_HyperXEve1800 : public RGBController
{
public:
RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr);
~RGBController_HyperXEve1800();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXEve1800Controller* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -15,12 +15,16 @@
#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 |
@@ -44,6 +48,8 @@
#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)
{
@@ -140,12 +146,41 @@ void DetectHyperXAlloyOrigins60and65(hid_device_info* info, const std::string& n
}
}
void DetectHyperXOrigins2_65(hid_device_info* info, const std::string& name)
{
hid_device* 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);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXEve1800(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXEve1800Controller* controller = new HyperXEve1800Controller(dev, info->path, name);
RGBController_HyperXEve1800* rgb_controller = new RGBController_HyperXEve1800(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite RGB", DetectHyperXAlloyElite, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_PID, 2, 0xFF01);
REGISTER_HID_DETECTOR_IP("HyperX Alloy FPS RGB", DetectHyperXAlloyFPS, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_FPS_RGB_PID, 2, 0xFF01);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOriginsCore, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 2);
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);
@@ -0,0 +1,151 @@
/*---------------------------------------------------------*\
| HyperXOrigins2_65Controller.cpp |
| |
| Driver for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXOrigins2_65Controller.h"
#include "StringUtils.h"
HyperXOrigins2_65Controller::HyperXOrigins2_65Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXOrigins2_65Controller::~HyperXOrigins2_65Controller()
{
hid_close(dev);
}
std::string HyperXOrigins2_65Controller::GetDeviceLocation()
{
return("HID " + location);
}
std::string HyperXOrigins2_65Controller::GetNameString()
{
return(name);
}
std::string HyperXOrigins2_65Controller::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 HyperXOrigins2_65Controller::SetLEDsDirect(std::vector<RGBColor> colors)
{
/*-----------------------------------------------------*\
| Set up variables to track progress of color transmit |
| Do this after inserting blanks |
\*-----------------------------------------------------*/
int colors_to_send = (int)colors.size();
int colors_sent = 0;
SendDirectInitialization();
for(int pkt_idx = 0; pkt_idx < 4; pkt_idx++)
{
if(colors_to_send > 20)
{
SendDirectColorPacket(&colors[colors_sent], 20, pkt_idx);
colors_sent += 20;
colors_to_send -= 20;
}
else if(colors_to_send > 0)
{
SendDirectColorPacket(&colors[colors_sent], colors_to_send, pkt_idx);
colors_sent += colors_to_send;
colors_to_send -= colors_to_send;
}
else
{
RGBColor temp = 0x00000000;
SendDirectColorPacket(&temp, 1, pkt_idx);
}
}
}
void HyperXOrigins2_65Controller::SendDirectInitialization()
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x44;
buf[0x01] = 0x01;
buf[0x02] = 0x04;
buf[0x03] = 0x00;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, buf, 65);
}
void HyperXOrigins2_65Controller::SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count,
unsigned int seq
)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x44;
buf[0x01] = 0x02;
buf[0x02] = (unsigned char)seq;
buf[0x03] = 0x00;
/*-----------------------------------------------------*\
| The maximum number of colors per packet is 20 |
\*-----------------------------------------------------*/
if(color_count > 20)
{
color_count = 20;
}
/*-----------------------------------------------------*\
| Copy in color data |
\*-----------------------------------------------------*/
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
{
buf[4 + (color_idx * 3)] = RGBGetRValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 1] = RGBGetGValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 2] = RGBGetBValue(color_data[color_idx]);
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, buf, 65);
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| HyperXOrigins2_65Controller.h |
| |
| Driver for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 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"
class HyperXOrigins2_65Controller
{
public:
HyperXOrigins2_65Controller(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXOrigins2_65Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
void SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count,
unsigned int seq
);
};
@@ -0,0 +1,257 @@
/*---------------------------------------------------------*\
| RGBController_HyperXOrigins2_65.cpp |
| |
| RGBController for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXOrigins2_65.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[5][15] =
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, NA, 29 },
{ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44 },
{ 45, 61, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 59 },
{ 60, 62, 63, 65, NA, NA, 66, NA, NA, 68, 69, 70, 71, 72, 73 } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
74,
};
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_1,
KEY_EN_2,
KEY_EN_3,
KEY_EN_4,
KEY_EN_5,
KEY_EN_6,
KEY_EN_7,
KEY_EN_8,
KEY_EN_9,
KEY_EN_0,
KEY_EN_MINUS,
KEY_EN_EQUALS,
KEY_EN_BACKSPACE,
KEY_EN_DELETE,
KEY_EN_TAB,
KEY_EN_Q,
KEY_EN_W,
KEY_EN_E,
KEY_EN_R,
KEY_EN_T,
KEY_EN_Y,
KEY_EN_U,
KEY_EN_I,
KEY_EN_O,
KEY_EN_P,
KEY_EN_LEFT_BRACKET,
KEY_EN_RIGHT_BRACKET,
KEY_EN_UNUSED,
KEY_EN_HOME,
KEY_EN_CAPS_LOCK,
KEY_EN_A,
KEY_EN_S,
KEY_EN_D,
KEY_EN_F,
KEY_EN_G,
KEY_EN_H,
KEY_EN_J,
KEY_EN_K,
KEY_EN_L,
KEY_EN_SEMICOLON,
KEY_EN_QUOTE,
KEY_EN_POUND,
KEY_EN_ISO_ENTER,
KEY_EN_PAGE_UP,
KEY_EN_LEFT_SHIFT,
KEY_EN_Z,
KEY_EN_X,
KEY_EN_C,
KEY_EN_V,
KEY_EN_B,
KEY_EN_N,
KEY_EN_M,
KEY_EN_COMMA,
KEY_EN_PERIOD,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_SHIFT,
KEY_EN_UP_ARROW,
KEY_EN_UNUSED,
KEY_EN_PAGE_DOWN,
KEY_EN_LEFT_CONTROL,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_LEFT_WINDOWS,
KEY_EN_LEFT_ALT,
KEY_EN_UNUSED,
"Left Space",
KEY_EN_SPACE,
"Right Space",
KEY_EN_UNUSED,
KEY_EN_RIGHT_ALT,
KEY_EN_RIGHT_FUNCTION,
KEY_EN_LEFT_ARROW,
KEY_EN_DOWN_ARROW,
KEY_EN_RIGHT_ARROW
};
/**------------------------------------------------------------------*\
@name HyperX Origins 2 65
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXOrigins2_65
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXOrigins2_65::RGBController_HyperXOrigins2_65(HyperXOrigins2_65Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXOrigins2_65::KeepaliveThread, this);
}
RGBController_HyperXOrigins2_65::~RGBController_HyperXOrigins2_65()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXOrigins2_65::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->height = 5;
new_zone.matrix_map->width = 15;
new_zone.matrix_map->map = (unsigned int *)&matrix_map;
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
total_led_count += zone_sizes[zone_idx];
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXOrigins2_65::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXOrigins2_65::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(colors);
}
void RGBController_HyperXOrigins2_65::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXOrigins2_65::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXOrigins2_65::DeviceUpdateMode()
{
}
void RGBController_HyperXOrigins2_65::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);;
}
}
@@ -0,0 +1,42 @@
/*---------------------------------------------------------*\
| RGBController_HyperXOrigins2_65.h |
| |
| RGBController for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXOrigins2_65Controller.h"
class RGBController_HyperXOrigins2_65 : public RGBController
{
public:
RGBController_HyperXOrigins2_65(HyperXOrigins2_65Controller* controller_ptr);
~RGBController_HyperXOrigins2_65();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXOrigins2_65Controller* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -18,7 +18,7 @@
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "JGINYUEInternalUSBV2Controller.h"
#include "LogManager.h"
#include "dmiinfo.h"
#define JGINYUE_V2_HID_GENERAL_COMMAND_HEADER 0x01
@@ -55,8 +55,10 @@ JGINYUEInternalUSBV2Controller::JGINYUEInternalUSBV2Controller(hid_device* jy_hi
JGINYUEInternalUSBV2Controller::~JGINYUEInternalUSBV2Controller()
{
hid_close(jy_hid_interface);
delete jy_cdc_interface;
if(jy_cdc_interface != nullptr)
{
delete jy_cdc_interface;
}
}
unsigned int JGINYUEInternalUSBV2Controller::GetZoneCount()
@@ -91,14 +93,26 @@ void JGINYUEInternalUSBV2Controller::Init_device()
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0] = JGINYUE_V2_HID_GENERAL_COMMAND_HEADER;
usb_buf[1] = 0x0F;
hid_write(jy_hid_interface, usb_buf, 64);
std::this_thread::sleep_for(20ms);
hid_read(jy_hid_interface, usb_buf, 64);
if(usb_buf[1] != 0x0F)
int write_result = hid_write(jy_hid_interface, usb_buf, 64);
if(write_result < 0)
{
LOG_ERROR("[JGINYUEInternalUSBV2Controller] Failed to write to JGINYUE device during initialization");
ZoneCount = 0x00;
memset(device_config, 0x00, sizeof(device_config));
memset (&device_config_Global, 0x00, sizeof(device_config_Global));
memset(&device_config_Global, 0x00, sizeof(device_config_Global));
return;
}
std::this_thread::sleep_for(20ms);
int bytes_read = hid_read_timeout(jy_hid_interface, usb_buf, 64, 1000);
if(bytes_read <= 0 || usb_buf[1] != 0x0F)
{
LOG_ERROR("[JGINYUEInternalUSBV2Controller] JGINYUE device did not respond or invalid response (bytes read: %d)", bytes_read);
ZoneCount = 0x00;
memset(device_config, 0x00, sizeof(device_config));
memset(&device_config_Global, 0x00, sizeof(device_config_Global));
return;
}
unsigned char Zone_Info = usb_buf[4];
@@ -135,13 +149,25 @@ void JGINYUEInternalUSBV2Controller::Init_Zone(int zone)
usb_buf[1] = JGINYUE_V2_HID_REQUEST_ARGB_SETTING;
usb_buf[2] = Area_ID;
hid_write(jy_hid_interface, usb_buf, 64);
int write_result = hid_write(jy_hid_interface, usb_buf, 64);
if(write_result < 0)
{
LOG_ERROR("[JGINYUEInternalUSBV2Controller] Failed to write to JGINYUE device for zone %d", zone);
return;
}
std::this_thread::sleep_for(20ms);
hid_read(jy_hid_interface, usb_buf, 64);
if((usb_buf[1] != JGINYUE_V2_HID_REQUEST_ARGB_SETTING)|(usb_buf[2] != Area_ID))
int bytes_read = hid_read_timeout(jy_hid_interface, usb_buf, 64, 1000);
if(bytes_read <= 0)
{
LOG_ERROR("[JGINYUEInternalUSBV2Controller] Failed to read zone %d config from JGINYUE device (bytes read: %d)", zone, bytes_read);
return;
}
if((usb_buf[1] != JGINYUE_V2_HID_REQUEST_ARGB_SETTING) || (usb_buf[2] != Area_ID))
{
LOG_ERROR("[JGINYUEInternalUSBV2Controller] Invalid response for zone %d from JGINYUE device", zone);
return;
}
@@ -200,6 +226,16 @@ void JGINYUEInternalUSBV2Controller::DirectLEDControl
unsigned char Area
)
{
/*-----------------------------------------------------*\
| Direct mode requires CDC interface |
| If CDC is not available, log error and return |
\*-----------------------------------------------------*/
if(jy_cdc_interface == nullptr)
{
LOG_WARNING("[JGINYUEInternalUSBV2Controller] Direct mode requires serial port (CDC) which is not available. Use other modes instead.");
return;
}
unsigned char cdc_buf[512];
memset(cdc_buf, 0x00, sizeof(cdc_buf));
cdc_buf[0] = JGINYUE_V2_CDC_COMMAND_HEADER;
@@ -46,30 +46,49 @@ void DetectJGINYUEInternalUSBV2Controller(hid_device_info* info,const std::strin
std::transform(manufacturer.begin(), manufacturer.end(), manufacturer.begin(), ::toupper);
if(manufacturer.find("JGINYUE") == std::string::npos)
{
LOG_INFO("JGINYUE Internal USB ControllerV2 not found,error manufacturer name:%s",manufacturer.c_str());
LOG_INFO("[JGINYUEInternalUSBV2ControllerDetect] JGINYUE Internal USB ControllerV2 not found,error manufacturer name:%s",manufacturer.c_str());
hid_close(hid_dev);
return;
}
LOG_INFO("Pass manufacture name check.Start to init HID and CDC interface");
LOG_INFO("[JGINYUEInternalUSBV2ControllerDetect] Pass manufacture name check.Start to init HID and CDC interface");
if(hid_dev != nullptr )
{
serial_port *port = nullptr;
std::vector<std::string*> serial_ports = find_usb_serial_port(JGINYUE_VID_V2, JGINYUE_MOTHERBOARD_PID_V2);
if(serial_ports.size() ==1)
if(serial_ports.size() == 0)
{
serial_port *port = new serial_port();
LOG_WARNING("[JGINYUEInternalUSBV2ControllerDetect] JGINYUE device found but no serial port detected - Direct mode will be unavailable");
}
else if(serial_ports.size() > 1)
{
LOG_WARNING("[JGINYUEInternalUSBV2ControllerDetect] Multiple serial ports found for JGINYUE device, using first one");
}
if(serial_ports.size() >= 1)
{
port = new serial_port();
if(!port->serial_open(serial_ports[0]->c_str(), 115200))
{
LOG_ERROR("Failed to open serial port %s", serial_ports[0]->c_str());
LOG_WARNING("[JGINYUEInternalUSBV2ControllerDetect] Failed to open serial port %s - Direct mode will be unavailable. HID modes will still work.", serial_ports[0]->c_str());
delete port;
hid_close(hid_dev);
return;
port = nullptr;
}
JGINYUEInternalUSBV2Controller *controller = new JGINYUEInternalUSBV2Controller(hid_dev, info->path,port);
RGBController_JGINYUEInternalUSBV2 *rgb_controller = new RGBController_JGINYUEInternalUSBV2(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
LOG_INFO("JGINYUE Internal USB ControllerV2 found");
}
/*-----------------------------------------------------*\
| Clean up serial port string vector |
\*-----------------------------------------------------*/
for(std::string* str_ptr : serial_ports)
{
delete str_ptr;
}
JGINYUEInternalUSBV2Controller *controller = new JGINYUEInternalUSBV2Controller(hid_dev, info->path, port);
RGBController_JGINYUEInternalUSBV2 *rgb_controller = new RGBController_JGINYUEInternalUSBV2(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
@@ -38,6 +38,7 @@
#define LEGION_7GEN9 0xC997
#define LEGION_7GEN9_H 0xC998
#define LEGION_7GEN10 0xC197
#define LEGION_5GEN10 0xC195
enum LENOVO_KEYBOARD
{
@@ -318,7 +318,7 @@ void RGBController_LenovoK510::ReadAndUpdateCurrentDeviceState()
current_active_mode.direction = current_active_mode.direction ? MODE_DIRECTION_UP : MODE_DIRECTION_DOWN;
}
active_mode = i;
active_mode = (int)i;
break;
}
}
@@ -67,3 +67,4 @@ REGISTER_HID_DETECTOR_PU("Lenovo Legion 7S Gen 8", DetectLenovoLegionUSBControl
REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 9", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN9, LENOVO_PAGE, LENOVO_USAGE);
REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 9", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN9_H, LENOVO_PAGE, LENOVO_USAGE);
REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 10", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN10, LENOVO_PAGE, LENOVO_USAGE);
REGISTER_HID_DETECTOR_PU("Lenovo Legion 5 Gen 10", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_5GEN10, LENOVO_PAGE, LENOVO_USAGE);
@@ -17,7 +17,7 @@ using namespace std;
static void SetGen10PayloadLength(uint16_t pid, uint8_t* buffer, uint16_t payload_length)
{
if(pid != LEGION_7GEN10)
if(pid != LEGION_7GEN10 && pid != LEGION_5GEN10)
{
return;
}
@@ -26,6 +26,11 @@ static void SetGen10PayloadLength(uint16_t pid, uint8_t* buffer, uint16_t payloa
buffer[3] = (payload_length >> 8) & 0xFF;
}
static bool UsesGen10PacketFormat(uint16_t pid)
{
return pid == LEGION_7GEN10 || pid == LEGION_5GEN10;
}
LenovoGen7And8USBController::LenovoGen7And8USBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name)
{
dev = dev_handle;
@@ -114,7 +119,7 @@ void LenovoGen7And8USBController::setLedsByGroup(uint8_t profile_id, vector<led_
i+= led_count * sizeof(uint16_t);
}
if(pid == LEGION_7GEN10)
if(UsesGen10PacketFormat(pid))
{
SetGen10PayloadLength(pid, buffer, static_cast<uint16_t>(i - 4));
}
@@ -162,7 +167,7 @@ void LenovoGen7And8USBController::setLedsDirectOff(uint8_t profile_id)
void LenovoGen7And8USBController::setLedsDirect(std::vector<led> &leds, std::vector<RGBColor> &colors)
{
if(pid == LEGION_7GEN10)
if(UsesGen10PacketFormat(pid))
{
/*---------------------------------------------------------*\
| Gen10 uses 0x07/A1 direct updates, with payload length |
@@ -13,6 +13,78 @@
using namespace std;
static bool UsesGen10PacketFormat(uint16_t pid)
{
return pid == LEGION_7GEN10 || pid == LEGION_5GEN10;
}
static bool Is24ZoneDevice(uint16_t pid)
{
return pid == LEGION_5GEN10;
}
static bool IsKeyboardOnlyDevice(uint16_t pid)
{
return pid == LEGION_5GEN10;
}
static const lenovo_led legion_5gen10_24zone_leds[] =
{
{0x01, "Zone R1C1"},
{0x02, "Zone R1C2"},
{0x03, "Zone R1C3"},
{0x04, "Zone R1C4"},
{0x05, "Zone R1C5"},
{0x06, "Zone R1C6"},
{0x07, "Zone R2C1"},
{0x08, "Zone R2C2"},
{0x09, "Zone R2C3"},
{0x0A, "Zone R2C4"},
{0x0B, "Zone R2C5"},
{0x0C, "Zone R2C6"},
{0x0D, "Zone R3C1"},
{0x0E, "Zone R3C2"},
{0x0F, "Zone R3C3"},
{0x10, "Zone R3C4"},
{0x11, "Zone R3C5"},
{0x12, "Zone R3C6"},
{0x13, "Zone R4C1"},
{0x14, "Zone R4C2"},
{0x15, "Zone R4C3"},
{0x16, "Zone R4C4"},
{0x17, "Zone R4C5"},
{0x18, "Zone R4C6"},
};
static const unsigned int legion_5gen10_24zone_matrix_map[] =
{
0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23,
};
static const lenovo_zone legion_5gen10_kbd_24zone =
{
"Keyboard (24-zone)",
ZONE_TYPE_MATRIX,
0,
4,
6,
legion_5gen10_24zone_matrix_map,
legion_5gen10_24zone_leds,
0,
23,
};
static const RGBColor legion_5gen10_zone_visualization_colors[24] =
{
0xFF0000, 0x00FFFF, 0xFFFF00, 0x0000FF, 0x00FF00, 0xFF00FF,
0xFF7F00, 0x007FFF, 0x7FFF00, 0x7F00FF, 0xFF007F, 0x00FF7F,
0xFFD700, 0x0055FF, 0x55FF00, 0xFF0055, 0x00BFFF, 0xBF00FF,
0xFF3B00, 0x00FF3B, 0x3B00FF, 0xFF1493, 0x14FF93, 0x9314FF,
};
LenovoRGBController_Gen7_8::LenovoRGBController_Gen7_8(LenovoGen7And8USBController* controller_ptr)
{
controller = controller_ptr;
@@ -139,72 +211,79 @@ LenovoRGBController_Gen7_8::LenovoRGBController_Gen7_8(LenovoGen7And8USBControll
Smooth.brightness = brightness;
modes.push_back(Smooth);
mode Rain;
Rain.name = "Rain";
Rain.value = LENOVO_LEGION_GEN7_8_MODE_RAIN;
Rain.flags = MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Rain.speed_min = 0x01;
Rain.speed_max = 0x03;
Rain.speed = 2;
Rain.colors_min = 1;
Rain.colors_max = 4;
Rain.colors.resize(4);
Rain.colors[0] = 0xFFF500;
Rain.color_mode = MODE_COLORS_RANDOM;
Rain.brightness_min = 0;
Rain.brightness_max = 9;
Rain.brightness = brightness;
modes.push_back(Rain);
if(!Is24ZoneDevice(controller->getPid()))
{
mode Rain;
Rain.name = "Rain";
Rain.value = LENOVO_LEGION_GEN7_8_MODE_RAIN;
Rain.flags = MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Rain.speed_min = 0x01;
Rain.speed_max = 0x03;
Rain.speed = 2;
Rain.colors_min = 1;
Rain.colors_max = 4;
Rain.colors.resize(4);
Rain.colors[0] = 0xFFF500;
Rain.color_mode = MODE_COLORS_RANDOM;
Rain.brightness_min = 0;
Rain.brightness_max = 9;
Rain.brightness = brightness;
modes.push_back(Rain);
}
mode Ripple;
Ripple.name = "Ripple";
Ripple.value = LENOVO_LEGION_GEN7_8_MODE_RIPPLE;
Ripple.flags = MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Ripple.speed_min = 0x01;
Ripple.speed_max = 0x03;
Ripple.speed = 2;
Ripple.colors_min = 1;
Ripple.colors_max = 4;
Ripple.colors.resize(4);
Ripple.colors[0] = 0xFFF500;
Ripple.color_mode = MODE_COLORS_RANDOM;
Ripple.brightness_min = 0;
Ripple.brightness_max = 9;
Ripple.brightness = brightness;
modes.push_back(Ripple);
if(!IsKeyboardOnlyDevice(controller->getPid()))
{
mode Ripple;
Ripple.name = "Ripple";
Ripple.value = LENOVO_LEGION_GEN7_8_MODE_RIPPLE;
Ripple.flags = MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Ripple.speed_min = 0x01;
Ripple.speed_max = 0x03;
Ripple.speed = 2;
Ripple.colors_min = 1;
Ripple.colors_max = 4;
Ripple.colors.resize(4);
Ripple.colors[0] = 0xFFF500;
Ripple.color_mode = MODE_COLORS_RANDOM;
Ripple.brightness_min = 0;
Ripple.brightness_max = 9;
Ripple.brightness = brightness;
modes.push_back(Ripple);
mode AudioBounce;
AudioBounce.name = "Audio Bounce Lighting";
AudioBounce.value = LENOVO_LEGION_GEN7_8_MODE_AUDIO_BOUNCE;
AudioBounce.flags = MODE_FLAG_HAS_BRIGHTNESS;
AudioBounce.color_mode = MODE_COLORS_NONE;
AudioBounce.brightness_min = 0;
AudioBounce.brightness_max = 9;
AudioBounce.brightness = brightness;
modes.push_back(AudioBounce);
mode AudioBounce;
AudioBounce.name = "Audio Bounce Lighting";
AudioBounce.value = LENOVO_LEGION_GEN7_8_MODE_AUDIO_BOUNCE;
AudioBounce.flags = MODE_FLAG_HAS_BRIGHTNESS;
AudioBounce.color_mode = MODE_COLORS_NONE;
AudioBounce.brightness_min = 0;
AudioBounce.brightness_max = 9;
AudioBounce.brightness = brightness;
modes.push_back(AudioBounce);
mode AudioRipple;
AudioRipple.name = "Audio Ripple Lighting";
AudioRipple.value = LENOVO_LEGION_GEN7_8_MODE_AUDIO_RIPPLE;
AudioRipple.flags = MODE_FLAG_HAS_BRIGHTNESS;
AudioRipple.color_mode = MODE_COLORS_NONE;
AudioRipple.brightness_min = 0;
AudioRipple.brightness_max = 9;
AudioRipple.brightness = brightness;
modes.push_back(AudioRipple);
mode AudioRipple;
AudioRipple.name = "Audio Ripple Lighting";
AudioRipple.value = LENOVO_LEGION_GEN7_8_MODE_AUDIO_RIPPLE;
AudioRipple.flags = MODE_FLAG_HAS_BRIGHTNESS;
AudioRipple.color_mode = MODE_COLORS_NONE;
AudioRipple.brightness_min = 0;
AudioRipple.brightness_max = 9;
AudioRipple.brightness = brightness;
modes.push_back(AudioRipple);
}
mode Static;
Static.name = "Static";
Static.value = LENOVO_LEGION_GEN7_8_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Static.color_mode = MODE_COLORS_PER_LED;
@@ -213,37 +292,43 @@ LenovoRGBController_Gen7_8::LenovoRGBController_Gen7_8(LenovoGen7And8USBControll
Static.brightness = brightness;
modes.push_back(Static);
mode Type;
Type.name = "Type Lighting";
Type.value = LENOVO_LEGION_GEN7_8_MODE_TYPE;
Type.flags = MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Type.speed_min = 0x01;
Type.speed_max = 0x03;
Type.speed = 2;
Type.colors_min = 1;
Type.colors_max = 4;
Type.colors.resize(4);
Type.colors[0] = 0xFFF500;
Type.color_mode = MODE_COLORS_RANDOM;
Type.brightness_min = 0;
Type.brightness_max = 9;
Type.brightness = brightness;
modes.push_back(Type);
if(!Is24ZoneDevice(controller->getPid()))
{
mode Type;
Type.name = "Type Lighting";
Type.value = LENOVO_LEGION_GEN7_8_MODE_TYPE;
Type.flags = MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_RANDOM_COLOR |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_AUTOMATIC_SAVE;
Type.speed_min = 0x01;
Type.speed_max = 0x03;
Type.speed = 2;
Type.colors_min = 1;
Type.colors_max = 4;
Type.colors.resize(4);
Type.colors[0] = 0xFFF500;
Type.color_mode = MODE_COLORS_RANDOM;
Type.brightness_min = 0;
Type.brightness_max = 9;
Type.brightness = brightness;
modes.push_back(Type);
}
mode Direct;
Direct.name = "Direct";
Direct.value = LENOVO_LEGION_GEN7_8_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR |
MODE_FLAG_HAS_BRIGHTNESS;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness_min = 0;
Direct.brightness_max = 9;
Direct.brightness = brightness;
modes.push_back(Direct);
if(!IsKeyboardOnlyDevice(controller->getPid()))
{
mode Direct;
Direct.name = "Direct";
Direct.value = LENOVO_LEGION_GEN7_8_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR |
MODE_FLAG_HAS_BRIGHTNESS;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness_min = 0;
Direct.brightness_max = 9;
Direct.brightness = brightness;
modes.push_back(Direct);
}
name = controller->getName();
type = DEVICE_TYPE_KEYBOARD;
@@ -275,6 +360,10 @@ LenovoRGBController_Gen7_8::LenovoRGBController_Gen7_8(LenovoGen7And8USBControll
case LEGION_7GEN10:
description = "Lenovo Legion 7 Generation 10";
break;
case LEGION_5GEN10:
description = "Lenovo Legion 5 Gen 10";
break;
}
brightness = controller->getCurrentBrightness();
@@ -286,15 +375,15 @@ LenovoRGBController_Gen7_8::LenovoRGBController_Gen7_8(LenovoGen7And8USBControll
SetupZones();
/*-----------------*\
| Initiliaze Static |
\*-----------------*/
/*-----------------------------------------------------*\
| Initiliaze Static |
\*-----------------------------------------------------*/
active_mode = 0;
for(size_t i = 0; i < modes.size(); i++)
{
if(modes[i].value == LENOVO_LEGION_GEN7_8_MODE_STATIC)
{
active_mode = i;
active_mode = (int)i;
break;
}
}
@@ -307,12 +396,22 @@ LenovoRGBController_Gen7_8::~LenovoRGBController_Gen7_8()
delete controller;
}
void LenovoRGBController_Gen7_8::SetupZones()
{
vector<lenovo_zone> lenovo_zones;
lenovo_zones.push_back(legion7_gen7and8_kbd_ansi);
lenovo_zones.push_back(legion7_gen7and8_neon);
if(Is24ZoneDevice(controller->getPid()))
{
lenovo_zones.push_back(legion_5gen10_kbd_24zone);
}
else
{
lenovo_zones.push_back(legion7_gen7and8_kbd_ansi);
}
if(!IsKeyboardOnlyDevice(controller->getPid()))
{
lenovo_zones.push_back(legion7_gen7and8_neon);
}
if (controller->getPid() == LEGION_7GEN7)
{
@@ -363,9 +462,9 @@ void LenovoRGBController_Gen7_8::SetupZones()
new_led.value = lenovo_zones[i].id << 8 | lenovo_zones[i].leds[led_idx].led_num ;
leds.push_back(new_led);
/*---------------------------------------------------------*\
| create led id to index map for fast look up |
\*---------------------------------------------------------*/
/*---------------------------------------------*\
| create led id to index map for fast look up |
\*---------------------------------------------*/
led_id_to_index[new_led.value]=leds.size() - 1;
}
}
@@ -423,7 +522,7 @@ void LenovoRGBController_Gen7_8::DeviceUpdateMode()
{
controller->setLedsDirectOn(profile_id);
direct_enabled = true;
if(controller->getPid() != LEGION_7GEN10)
if(!UsesGen10PacketFormat(controller->getPid()))
{
controller->setLedsByGroup(profile_id, GetLedGroups());
}
@@ -447,11 +546,12 @@ void LenovoRGBController_Gen7_8::DeviceUpdateLEDs()
{
if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_DIRECT)
{
if(controller->getPid() == LEGION_7GEN10)
if(UsesGen10PacketFormat(controller->getPid()))
{
/*---------------------------------------------------------*\
| Gen10 may ignore A1 updates unless D0 is reasserted. |
\*---------------------------------------------------------*/
/*---------------------------------------------*\
| Gen10 may ignore A1 updates unless D0 is |
| reasserted. |
\*---------------------------------------------*/
controller->setLedsDirectOn(profile_id);
direct_enabled = true;
}
@@ -570,6 +670,29 @@ void LenovoRGBController_Gen7_8::ReadDeviceSettings()
std::vector<led_group> LenovoRGBController_Gen7_8::GetLedGroups()
{
if(Is24ZoneDevice(controller->getPid()) &&
modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_STATIC &&
modes[active_mode].color_mode == MODE_COLORS_RANDOM)
{
vector<led_group> led_groups;
led_groups.reserve(leds.size());
for(size_t i = 0; i < leds.size(); i++)
{
led_group group;
group.mode = modes[active_mode].value;
group.speed = modes[active_mode].speed;
group.spin = 0x00;
group.direction = 0x00;
group.color_mode = 0x02;
group.colors.push_back(legion_5gen10_zone_visualization_colors[i % 24]);
group.leds.push_back(leds[i].value);
led_groups.push_back(group);
}
return led_groups;
}
std::unordered_map<RGBColor, vector<uint16_t>> led_map;
if(modes[active_mode].color_mode == MODE_COLORS_PER_LED &&
@@ -585,9 +708,9 @@ std::vector<led_group> LenovoRGBController_Gen7_8::GetLedGroups()
size_t start = 0;
size_t end = leds.size();
/*---------------------------------------------------------*\
| Riplle and Type only apply to keyboard |
\*---------------------------------------------------------*/
/*-------------------------------------------------*\
| Riplle and Type only apply to keyboard |
\*-------------------------------------------------*/
if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_RIPPLE ||
modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_TYPE)
{
@@ -291,7 +291,7 @@ void LianLiUniHubSLController::SendActivate(size_t channel, unsigned char num_fa
buf[0x00] = UNIHUB_SL_REPORT_ID;
buf[0x01] = 0x10;
buf[0x02] = 0x32;
buf[0x03] = 0x10 * channel + num_fans;
buf[0x03] = 0x10 * (unsigned char)channel + num_fans;
this->LogBuffer("SendActivate", buf, sizeof(buf));
@@ -329,10 +329,10 @@ void LianLiUniHubSLController::SendMerge()
void LianLiUniHubSLController::SendColor(size_t channel, const unsigned char *colors, size_t num_colors)
{
unsigned char* buf = new unsigned char[2 + num_colors];
memset(buf, 0x00, sizeof(buf));
memset(buf, 0x00, (2 + num_colors));
buf[0x00] = UNIHUB_SL_REPORT_ID;
buf[0x01] = 0x30 + channel; // Channel 1: 0x30, Channel 2: 0x31, etc.
buf[0x01] = 0x30 + (unsigned char)channel; // Channel 1: 0x30, Channel 2: 0x31, etc.
memcpy(&buf[0x02], colors, num_colors);
@@ -350,7 +350,7 @@ void LianLiUniHubSLController::SendMode(size_t channel, const mode &active)
memset(buf, 0x00, sizeof(buf));
buf[0x00] = UNIHUB_SL_REPORT_ID;
buf[0x01] = 0x10 + channel; // Channel 1: 0x10, Channel 2: 0x11, etc.
buf[0x01] = 0x10 + (unsigned char)channel; // Channel 1: 0x10, Channel 2: 0x11, etc.
buf[0x02] = active.value;
buf[0x03] = this->ConvertSpeed(active.speed);
buf[0x04] = this->ConvertDirection(active.direction);
@@ -321,7 +321,7 @@ void RGBController_LianLiUniHubSL::SetupZones()
new_led.name = zones[zone_idx].name;
new_led.name.append(", Fan ");
new_led.name.append(std::to_string(led_idx + 1));
new_led.value = zone_idx;
new_led.value = (unsigned int)zone_idx;
leds.push_back(new_led);
}
@@ -235,7 +235,7 @@ void LianLiUniHubSLV2Controller::SetChannelMode(unsigned char channel, const mod
void LianLiUniHubSLV2Controller::SendStartAction(unsigned char channel, unsigned int num_fans)
{
unsigned char usb_buf[65];
unsigned char usb_buf[353];
/*-----------------------------------------------------*\
| Zero out buffer |
@@ -291,7 +291,7 @@ void LianLiUniHubSLV2Controller::SendColorData(unsigned char channel, unsigned
void LianLiUniHubSLV2Controller::SendCommitAction(unsigned char channel, unsigned char effect, unsigned char speed, unsigned int direction, unsigned int brightness)
{
unsigned char usb_buf[65];
unsigned char usb_buf[353];
/*-----------------------------------------------------*\
| Zero out buffer |
@@ -66,7 +66,7 @@ std::string LianLiUniversalScreenController::GetVersion()
void LianLiUniversalScreenController::SetLedColors(RGBColor* colors, size_t count)
{
unsigned char leds_in_packet = 20;
std::size_t leds_in_packet = 20;
unsigned char offset = 0;
unsigned char usb_buf[64];
@@ -91,7 +91,7 @@ void LianLiUniversalScreenController::SetLedColors(RGBColor* colors, size_t coun
usb_buf[6 + (led_idx * 3)] = RGBGetBValue(colors[offset + led_idx]);
}
offset += leds_in_packet;
offset += (unsigned char)leds_in_packet;
int actual_length = sizeof(usb_buf);
libusb_bulk_transfer(dev, 1, usb_buf, sizeof(usb_buf), &actual_length, 25);
@@ -38,6 +38,7 @@ void DetectMSIGPUv2Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const
} /* DetectMSIGPUv2Controllers() */
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Gaming X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060_DEV, MSI_SUB_VEN, MSI_RTX4060_GAMING_X_8G_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Gaming X NV Edition", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060_DEV, MSI_SUB_VEN, MSI_RTX4060_GAMING_X_NV_EDITION_8G_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Ti Gaming X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060TI_DEV, MSI_SUB_VEN, MSI_RTX4060TI_GAMING_X_8G_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Ti 16GB Gaming X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060TI_16G_DEV, MSI_SUB_VEN, MSI_RTX4060TI_GAMING_X_16G_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Ti 16GB Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060TI_16G_DEV, MSI_SUB_VEN, MSI_RTX4060TI_GAMING_X_16G_SLIM_WHITE_SUB_DEV, 0x68);
@@ -46,6 +47,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 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);
@@ -66,10 +68,13 @@ REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Gaming X Trio",
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_GAMING_X_SLIM_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Suprim Liquid X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_SUPRIM_LIQUID_X_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Suprim X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_SUPRIM_X_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5070 Gaming Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, MSI_SUB_VEN, MSI_RTX5070_GAMING_TRIO_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5070 Ti Gaming Trio OC Plus", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, MSI_SUB_VEN, MSI_RTX5070TI_GAMING_TRIO_SUB_DEV, 0x68);
REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5070 Ti VANGUARD SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, MSI_SUB_VEN, MSI_RTX5070TI_VANGUARD_SOC_SUB_DEV, 0x68);
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 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);
@@ -20,7 +20,7 @@
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectMSIMysticLight1565Controller
@detectors DetectMSIKeyboardController
@comment
\*-------------------------------------------------------------------*/
@@ -0,0 +1,89 @@
/*---------------------------------------------------------*\
| MSILaptopController.cpp |
| |
| Driver for MSI laptop SteelSeries KLC/ALC RGB devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "MSILaptopController.h"
#include "StringUtils.h"
#define MSI_LAPTOP_REPORT_ID 0x00
#define MSI_LAPTOP_COMMAND 0x0C
#define MSI_LAPTOP_KLC_PACKET_ID 0x66
#define MSI_LAPTOP_ALC_PACKET_ID 0x06
#define MSI_LAPTOP_PACKET_SIZE 525
#define MSI_LAPTOP_PAYLOAD_OFFSET 5
MSILaptopController::MSILaptopController(hid_device* dev_handle, const char* path, std::string dev_name, msi_laptop_device device_type)
{
dev = dev_handle;
location = path;
name = dev_name;
type = device_type;
}
MSILaptopController::~MSILaptopController()
{
hid_close(dev);
}
std::string MSILaptopController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string MSILaptopController::GetDeviceName()
{
return(name);
}
std::string MSILaptopController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
msi_laptop_device MSILaptopController::GetDeviceType()
{
return(type);
}
void MSILaptopController::SetLEDs(std::vector<led> leds, std::vector<RGBColor> colors)
{
unsigned char buf[MSI_LAPTOP_PACKET_SIZE];
unsigned int led_count = (leds.size() < colors.size()) ? leds.size() : colors.size();
memset(buf, 0x00, sizeof(buf));
buf[0x00] = MSI_LAPTOP_REPORT_ID;
buf[0x01] = MSI_LAPTOP_COMMAND;
buf[0x03] = (type == MSI_LAPTOP_KLC) ? MSI_LAPTOP_KLC_PACKET_ID : MSI_LAPTOP_ALC_PACKET_ID;
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
{
unsigned int offset = MSI_LAPTOP_PAYLOAD_OFFSET + (led_idx * 4);
if((offset + 3) >= sizeof(buf))
{
break;
}
buf[offset + 0] = leds[led_idx].value;
buf[offset + 1] = RGBGetRValue(colors[led_idx]);
buf[offset + 2] = RGBGetGValue(colors[led_idx]);
buf[offset + 3] = RGBGetBValue(colors[led_idx]);
}
hid_send_feature_report(dev, buf, sizeof(buf));
}
@@ -0,0 +1,67 @@
/*---------------------------------------------------------*\
| MSILaptopController.h |
| |
| Driver for MSI laptop SteelSeries KLC/ALC RGB devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <vector>
#include <hidapi.h>
#include "RGBController.h"
typedef enum
{
MSI_LAPTOP_KLC,
MSI_LAPTOP_ALC,
} msi_laptop_device;
typedef struct
{
const char* name;
unsigned char id;
} msi_laptop_led;
struct MSILaptopModel
{
const char* sys_vendor;
const char* product_name;
/* Keyboard layout */
const msi_laptop_led* klc_leds;
unsigned int klc_leds_count;
unsigned int klc_matrix_height;
unsigned int klc_matrix_width;
const unsigned int* klc_matrix_map;
/* Lightbar layout */
const msi_laptop_led* alc_leds;
unsigned int alc_leds_count;
unsigned int alc_lightbar_leds;
};
class MSILaptopController
{
public:
MSILaptopController(hid_device* dev_handle, const char* path, std::string dev_name, msi_laptop_device device_type);
~MSILaptopController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetSerialString();
msi_laptop_device GetDeviceType();
void SetLEDs(std::vector<led> leds, std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
msi_laptop_device type;
};
@@ -0,0 +1,225 @@
/*---------------------------------------------------------*\
| MSILaptopControllerDetect.cpp |
| |
| Detector for MSI laptop SteelSeries RGB devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "Detector.h"
#include "RGBControllerKeyNames.h"
#include "RGBController_MSILaptop.h"
#include "MSILaptopController.h"
#include "dmiinfo.h"
#define MSI_LAPTOP_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define STEELSERIES_VID 0x1038
#define STEELSERIES_MSI_RAIDER_A18_KLC_PID 0x1122
#define STEELSERIES_MSI_RAIDER_A18_ALC_PID 0x1161
#define NA 0xFFFFFFFF
#define MSI_LAPTOP_KLC_MATRIX_HEIGHT 6
#define MSI_LAPTOP_KLC_MATRIX_WIDTH 23
#define MSI_LAPTOP_ALC_LIGHTBAR_LEDS 5
static const msi_laptop_led msi_raider_a18_klc_leds[] =
{
{ KEY_EN_A, 0x04 },
{ KEY_EN_B, 0x05 },
{ KEY_EN_C, 0x06 },
{ KEY_EN_D, 0x07 },
{ KEY_EN_E, 0x08 },
{ KEY_EN_F, 0x09 },
{ KEY_EN_G, 0x0A },
{ KEY_EN_H, 0x0B },
{ KEY_EN_I, 0x0C },
{ KEY_EN_J, 0x0D },
{ KEY_EN_K, 0x0E },
{ KEY_EN_L, 0x0F },
{ KEY_EN_M, 0x10 },
{ KEY_EN_N, 0x11 },
{ KEY_EN_O, 0x12 },
{ KEY_EN_P, 0x13 },
{ KEY_EN_Q, 0x14 },
{ KEY_EN_R, 0x15 },
{ KEY_EN_S, 0x16 },
{ KEY_EN_T, 0x17 },
{ KEY_EN_U, 0x18 },
{ KEY_EN_V, 0x19 },
{ KEY_EN_W, 0x1A },
{ KEY_EN_X, 0x1B },
{ KEY_EN_Y, 0x1C },
{ KEY_EN_Z, 0x1D },
{ KEY_EN_1, 0x1E },
{ KEY_EN_2, 0x1F },
{ KEY_EN_3, 0x20 },
{ KEY_EN_4, 0x21 },
{ KEY_EN_5, 0x22 },
{ KEY_EN_6, 0x23 },
{ KEY_EN_7, 0x24 },
{ KEY_EN_8, 0x25 },
{ KEY_EN_9, 0x26 },
{ KEY_EN_0, 0x27 },
{ KEY_EN_ESCAPE, 0x29 },
{ KEY_EN_TAB, 0x2B },
{ KEY_EN_SPACE, 0x2C },
{ KEY_EN_MINUS, 0x2D },
{ KEY_EN_EQUALS, 0x2E },
{ KEY_EN_LEFT_BRACKET, 0x2F },
{ KEY_EN_RIGHT_BRACKET, 0x30 },
{ KEY_EN_SEMICOLON, 0x33 },
{ KEY_EN_QUOTE, 0x34 },
{ KEY_EN_BACK_TICK, 0x35 },
{ KEY_EN_COMMA, 0x36 },
{ KEY_EN_PERIOD, 0x37 },
{ KEY_EN_FORWARD_SLASH, 0x38 },
{ KEY_EN_CAPS_LOCK, 0x39 },
{ KEY_EN_F1, 0x3A },
{ KEY_EN_F2, 0x3B },
{ KEY_EN_F3, 0x3C },
{ KEY_EN_F4, 0x3D },
{ KEY_EN_F5, 0x3E },
{ KEY_EN_F6, 0x3F },
{ KEY_EN_F7, 0x40 },
{ KEY_EN_F8, 0x41 },
{ KEY_EN_F9, 0x42 },
{ KEY_EN_F10, 0x43 },
{ KEY_EN_F11, 0x44 },
{ KEY_EN_F12, 0x45 },
{ KEY_EN_PRINT_SCREEN, 0x46 },
{ KEY_EN_SCROLL_LOCK, 0x47 },
{ KEY_EN_INSERT, 0x49 },
{ "Home/Page Up", 0x4B },
{ KEY_EN_DELETE, 0x4C },
{ KEY_EN_PAGE_DOWN, 0x4E },
{ KEY_EN_RIGHT_ARROW, 0x4F },
{ KEY_EN_LEFT_ARROW, 0x50 },
{ KEY_EN_DOWN_ARROW, 0x51 },
{ KEY_EN_UP_ARROW, 0x52 },
{ KEY_EN_NUMPAD_LOCK, 0x53 },
{ KEY_EN_NUMPAD_DIVIDE, 0x54 },
{ KEY_EN_NUMPAD_TIMES, 0x55 },
{ KEY_EN_NUMPAD_MINUS, 0x56 },
{ KEY_EN_NUMPAD_PLUS, 0x57 },
{ KEY_EN_NUMPAD_ENTER, 0x58 },
{ KEY_EN_NUMPAD_1, 0x59 },
{ KEY_EN_NUMPAD_2, 0x5A },
{ KEY_EN_NUMPAD_3, 0x5B },
{ KEY_EN_NUMPAD_4, 0x5C },
{ KEY_EN_NUMPAD_5, 0x5D },
{ KEY_EN_NUMPAD_6, 0x5E },
{ KEY_EN_NUMPAD_7, 0x5F },
{ KEY_EN_NUMPAD_8, 0x60 },
{ KEY_EN_NUMPAD_9, 0x61 },
{ KEY_EN_NUMPAD_0, 0x62 },
{ KEY_EN_NUMPAD_PERIOD, 0x63 },
{ KEY_EN_POWER, 0x66 },
{ KEY_EN_LEFT_CONTROL, 0xE0 },
{ KEY_EN_LEFT_SHIFT, 0xE1 },
{ KEY_EN_LEFT_ALT, 0xE2 },
{ KEY_EN_LEFT_WINDOWS, 0xE3 },
{ KEY_EN_RIGHT_WINDOWS, 0xE4 },
{ KEY_EN_RIGHT_FUNCTION, 0xF0 },
{ KEY_EN_ANSI_ENTER, 0x28 },
{ KEY_EN_BACKSPACE, 0x2A },
{ KEY_EN_BACK_SLASH, 0x31 },
{ KEY_EN_ISO_BACK_SLASH, 0x64 },
{ KEY_EN_RIGHT_SHIFT, 0xE5 },
{ KEY_EN_RIGHT_ALT, 0xE6 },
};
static unsigned int msi_raider_a18_klc_matrix_map[MSI_LAPTOP_KLC_MATRIX_HEIGHT][MSI_LAPTOP_KLC_MATRIX_WIDTH] =
{
{ 36, NA, 50, 51, 52, 53, NA, 54, 55, 56, 57, NA, 58, 59, 60, 61, 62, 63, NA, NA, NA, NA, 89 },
{ 45, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 39, 40, 97, NA, 64, 65, NA, 72, 73, 74, 75, NA },
{ 37, 16, 22, 4, 17, 19, 24, 20, 8, 14, 15, 41, 42, 98, NA, 66, 67, NA, 84, 85, 86, 76, NA },
{ 49, 0, 18, 3, 5, 6, 7, 9, 10, 11, 43, 44, 96, NA, NA, NA, NA, NA, 81, 82, 83, NA, NA },
{ 91, 25, 23, 2, 21, 1, 13, 12, 46, 47, 48,100, NA, NA, NA, NA, 71, NA, 78, 79, 80, 77, NA },
{ 90, 93, 92, NA, NA, NA, 38, NA, NA, NA,101, 94, 95, NA, 69, 70, 68, NA, 87, NA, 88, NA, NA },
};
static const msi_laptop_led msi_raider_a18_alc_leds[] =
{
{ "Lightbar 1", 0x00 },
{ "Lightbar 2", 0x01 },
{ "Lightbar 3", 0x02 },
{ "Lightbar 4", 0x03 },
{ "Lightbar 5", 0x04 },
{ "Logo", 0x05 },
};
static const MSILaptopModel msi_laptop_models[] =
{
{
"Micro-Star International Co., Ltd.",
"Raider A18 HX A9WJG",
/* Keyboard layout */
msi_raider_a18_klc_leds,
MSI_LAPTOP_ARRAY_SIZE(msi_raider_a18_klc_leds),
MSI_LAPTOP_KLC_MATRIX_HEIGHT,
MSI_LAPTOP_KLC_MATRIX_WIDTH,
(const unsigned int*)msi_raider_a18_klc_matrix_map,
/* Lightbar layout */
msi_raider_a18_alc_leds,
MSI_LAPTOP_ARRAY_SIZE(msi_raider_a18_alc_leds),
MSI_LAPTOP_ALC_LIGHTBAR_LEDS,
},
};
static const MSILaptopModel* GetMSILaptopModelDMI()
{
DMIInfo dmi;
for(unsigned int i = 0; i < MSI_LAPTOP_ARRAY_SIZE(msi_laptop_models); i++)
{
if((dmi.getManufacturer() == msi_laptop_models[i].sys_vendor) &&
(dmi.getProductName() == msi_laptop_models[i].product_name))
{
return &msi_laptop_models[i];
}
}
return nullptr;
}
void DetectMSILaptop(hid_device_info* info, const std::string& name)
{
const MSILaptopModel* model = GetMSILaptopModelDMI();
if(!model)
{
return;
}
msi_laptop_device device_type;
if(info->product_id == STEELSERIES_MSI_RAIDER_A18_KLC_PID)
{
device_type = MSI_LAPTOP_KLC;
}
else if(info->product_id == STEELSERIES_MSI_RAIDER_A18_ALC_PID)
{
device_type = MSI_LAPTOP_ALC;
}
else
{
return;
}
hid_device* dev = hid_open_path(info->path);
if(dev)
{
MSILaptopController* controller = new MSILaptopController(dev, info->path, name, device_type);
RGBController_MSILaptop* rgb_controller = new RGBController_MSILaptop(controller, model);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_HID_DETECTOR_I("MSI Laptop Keyboard", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_KLC_PID, 0);
REGISTER_HID_DETECTOR_I("MSI Laptop Lightbar", DetectMSILaptop, STEELSERIES_VID, STEELSERIES_MSI_RAIDER_A18_ALC_PID, 0);
@@ -0,0 +1,141 @@
/*---------------------------------------------------------*\
| RGBController_MSILaptop.cpp |
| |
| RGBController for MSI laptop SteelSeries RGB devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_MSILaptop.h"
#define NA 0xFFFFFFFF
/**------------------------------------------------------------------*\
@name MSI Laptop SteelSeries RGB
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectMSILaptop
@comment
\*-------------------------------------------------------------------*/
RGBController_MSILaptop::RGBController_MSILaptop(MSILaptopController* controller_ptr, const MSILaptopModel* model_ptr)
{
controller = controller_ptr;
model = model_ptr;
name = controller->GetDeviceName();
vendor = "SteelSeries";
description = std::string(model->sys_vendor) + " " + std::string(model->product_name) + " RGB Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
type = (controller->GetDeviceType() == MSI_LAPTOP_KLC) ? DEVICE_TYPE_KEYBOARD : DEVICE_TYPE_LEDSTRIP;
mode Direct;
Direct.name = "Direct";
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_MSILaptop::~RGBController_MSILaptop()
{
for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
if(zones[zone_idx].matrix_map != NULL)
{
delete zones[zone_idx].matrix_map;
}
}
delete controller;
}
void RGBController_MSILaptop::SetupZones()
{
if(controller->GetDeviceType() == MSI_LAPTOP_KLC)
{
zone keyboard_zone;
keyboard_zone.name = ZONE_EN_KEYBOARD;
keyboard_zone.type = ZONE_TYPE_MATRIX;
keyboard_zone.leds_min = model->klc_leds_count;
keyboard_zone.leds_max = model->klc_leds_count;
keyboard_zone.leds_count = model->klc_leds_count;
keyboard_zone.matrix_map = new matrix_map_type;
keyboard_zone.matrix_map->height = model->klc_matrix_height;
keyboard_zone.matrix_map->width = model->klc_matrix_width;
keyboard_zone.matrix_map->map = (unsigned int *)model->klc_matrix_map;
zones.push_back(keyboard_zone);
for(unsigned int led_idx = 0; led_idx < model->klc_leds_count; led_idx++)
{
led new_led;
new_led.name = model->klc_leds[led_idx].name;
new_led.value = model->klc_leds[led_idx].id;
leds.push_back(new_led);
}
}
else
{
zone lightbar_zone;
lightbar_zone.name = "Lightbar";
lightbar_zone.type = ZONE_TYPE_LINEAR;
lightbar_zone.start_idx = 0;
lightbar_zone.leds_min = model->alc_lightbar_leds;
lightbar_zone.leds_max = model->alc_lightbar_leds;
lightbar_zone.leds_count = model->alc_lightbar_leds;
lightbar_zone.matrix_map = NULL;
zones.push_back(lightbar_zone);
zone logo_zone;
logo_zone.name = "Logo";
logo_zone.type = ZONE_TYPE_SINGLE;
logo_zone.start_idx = model->alc_lightbar_leds;
logo_zone.leds_min = 1;
logo_zone.leds_max = 1;
logo_zone.leds_count = 1;
logo_zone.matrix_map = NULL;
zones.push_back(logo_zone);
for(unsigned int led_idx = 0; led_idx < model->alc_leds_count; led_idx++)
{
led new_led;
new_led.name = model->alc_leds[led_idx].name;
new_led.value = model->alc_leds[led_idx].id;
leds.push_back(new_led);
}
}
SetupColors();
}
void RGBController_MSILaptop::ResizeZone(int /*zone*/, int /*new_size*/)
{
}
void RGBController_MSILaptop::DeviceUpdateLEDs()
{
controller->SetLEDs(leds, colors);
}
void RGBController_MSILaptop::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_MSILaptop::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_MSILaptop::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -0,0 +1,34 @@
/*---------------------------------------------------------*\
| RGBController_MSILaptop.h |
| |
| RGBController for MSI laptop SteelSeries RGB devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "MSILaptopController.h"
class RGBController_MSILaptop : public RGBController
{
public:
RGBController_MSILaptop(MSILaptopController* controller_ptr, const MSILaptopModel* model_ptr);
~RGBController_MSILaptop();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
MSILaptopController* controller;
const MSILaptopModel* model;
};
@@ -227,6 +227,23 @@ const std::vector<MSI_ZONE> zones_set19 =
MSI_ZONE_J_RAINBOW_3
};
const std::vector<MSI_ZONE> zones_set20 =
{
MSI_ZONE_J_RGB_1,
};
const std::vector<MSI_ZONE> zones_set21 =
{
MSI_ZONE_J_RGB_1,
MSI_ZONE_J_RGB_2,
MSI_ZONE_J_RAINBOW_1,
MSI_ZONE_J_RAINBOW_2,
MSI_ZONE_J_CORSAIR,
MSI_ZONE_J_PIPE_1,
MSI_ZONE_J_PIPE_2,
MSI_ZONE_ON_BOARD_LED_0
};
/*---------------------------------------------------------------------------------------------------------------------------------*\
| Definition of the board sepcific configurations (number of onboard LEDs and supported zones). |
@@ -312,6 +329,7 @@ static const mystic_light_185_config board_configs[] =
{ 0x7D77, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-A WIFI
{ 0x7D78, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650-P WIFI
{ 0x7D86, 0, 18, 4, 1, &zones_set16, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z790 ACE
{ 0x7D88, 0, 0, 0, 1, &zones_set20, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z790-S WIFI
{ 0x7D89, 0, 6, 0, 1, &zones_set18, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z790 CARBON WIFI
{ 0x7D90, 0, 0, 0, 1, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B760M BOMBER DDR4
{ 0x7D91, 1, 0, 0, 1, &zones_set10, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG Z790 TOMAHAWK WIFI
@@ -327,10 +345,12 @@ static const mystic_light_185_config board_configs[] =
{ 0x7E09, 0, 0, 0, 0, &zones_set19, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B650M PROJECT ZERO
{ 0x7E10, 0, 6, 0, 2, &zones_set17, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG B650 EDGE WIFI
{ 0x7E12, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG X670E TOMAHAWK WIFI
{ 0x0076, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG X670E TOMAHAWK WIFI (Common PID)
{ 0x7E16, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // X670E GAMING PLUS WIFI
{ 0x7E24, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B650M GAMING PLUS WIFI
{ 0x7E26, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B650 GAMING PLUS WIFI
{ 0x7E27, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-P
{ 0x7E28, 6, 0, 0, 2, &zones_set21, MSIMysticLight185Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO A620M-B (MS-7E28)
};
@@ -698,6 +718,19 @@ bool MSIMysticLight185Controller::Update
}
else
{
/*-----------------------------------------------------*\
| Save new state, read current state from board, |
| send old state first, then new state. |
| Windows Mystic Light sends two consecutive reports. |
\*-----------------------------------------------------*/
FeaturePacket_185 new_data = data;
memcpy((unsigned char*)&new_data, (unsigned char*)&data, sizeof(data));
ReadSettings();
data.save_data = save;
hid_send_feature_report(dev, (unsigned char*)&data, sizeof(data));
memcpy((unsigned char*)&data, (unsigned char*)&new_data, sizeof(data));
data.save_data = save;
return (hid_send_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof(data));
}
@@ -478,7 +478,7 @@ void RGBController_MSIMysticLight185::GetDeviceConfig()
if(zones[i].colors != nullptr)
{
for(size_t j = 0; j < zones[i].leds_count; ++j)
for(size_t j = 0; j < GetLEDsInZone((unsigned int)i); ++j)
{
zones[i].colors[j] = color;
}
@@ -62,6 +62,15 @@ static const std::string board_names[] =
"MSI PRO X870E-P WIFI (MS-7E70)",
"MSI MPG X870I EDGE TI EVO WIFI (MS-7E50)",
"MSI B850 GAMING PLUS WIFI (MS-7E56)",
"MSI PRO X870-P WIFI (MS-7E47)",
"MSI MPG X870E EDGE TI WIFI (MS-7E59)",
"MSI MAG B850 TOMAHAWK MAX WIFI (MS-7E62)",
"MSI PRO B850M-P WIFI (MS-7E71)",
"MSI MAG Z890 TOMAHAWK WIFI (MS-7E32)",
"MSI MPG B850 EDGE TI WIFI (MS-7E62)",
"MSI PRO B850M-VC WIFI6E (MS-7E71)",
"MSI MAG B850 TOMAHAWK WIFI (MS-7E53)",
"MSI MEG Z890 UNIFY-X (MS-7E20)",
};
static const mystic_light_761_config board_configs[] =
@@ -81,6 +90,15 @@ static const mystic_light_761_config board_configs[] =
{ &(board_names[12]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO X870E-P WIFI
{ &(board_names[13]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MPG X870I EDGE TI EVO WIFI (MS-7E50)
{ &(board_names[14]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI B850 GAMING PLUS WIFI (MS-7E56)
{ &(board_names[15]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO X870-P WIFI
{ &(board_names[16]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MPG X870E EDGE TI WIFI
{ &(board_names[17]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG B850 TOMAHAWK MAX WIFI
{ &(board_names[18]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO B850M-P WIFI (MS-7E71)
{ &(board_names[19]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG Z890 TOMAHAWK WIFI (MS-7E32)
{ &(board_names[20]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MPG B850 EDGE TI WIFI (MS-7E62)
{ &(board_names[21]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO B850M-VC WIFI6E (MS-7E71)
{ &(board_names[22]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG B850 TOMAHAWK WIFI (MS-7E53)
{ &(board_names[23]), 0, 0, 0, 1, &zone_set1, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MEG Z890 UNIFY-X (MS-7E20)
};
enum MSI_ZONE setup_map [] =
@@ -417,7 +417,7 @@ void RGBController_MSIMysticLight761::GetDeviceConfig()
if(zones[i].colors != nullptr)
{
for(unsigned int j = 0; j < zones[i].leds_count; ++j)
for(size_t j = 0; j < GetLEDsInZone((unsigned int)i); ++j)
{
zones[i].colors[j] = color;
}
@@ -231,6 +231,7 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D76", DetectMSIMysticLightCont
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D77", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D77, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D78", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D78, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D86", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D86, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D88", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D88, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D89", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D89, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D90", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D90, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D91", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D91, 0x0001, 0x00);
@@ -251,6 +252,8 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E59", DetectMSIMysticLightCont
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E80", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E80, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E81", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E81, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E34", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E34, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E32", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E32, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E20", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E20, 0x0001, 0x00);
// Detector for the set of common boards
REGISTER_HID_DETECTOR_PU("MSI Mystic Light Common", DetectMSIMysticLightControllers, MSI_USB_VID_COMMON, MSI_USB_PID_COMMON, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light X870", DetectMSIMysticLightControllers, MSI_USB_VID_COMMON, MSI_USB_PID_COMMON, 0xFF00, 0x01);
@@ -22,6 +22,19 @@ Mountain60KeyboardController::Mountain60KeyboardController(hid_device* dev_handl
dev = dev_handle;
location = path;
name = dev_name;
unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE];
unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE];
memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE);
usb_buf[0x01] = MOUNTAIN60_KEYBOARD_RESET_CMD;
usb_buf[0x02] = 0x46; //constant data
usb_buf[0x03] = 0x23; //constant data
usb_buf[0x04] = 0xEA; //constant data
hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE);
memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE);
hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE);
}
Mountain60KeyboardController::~Mountain60KeyboardController()
@@ -26,6 +26,7 @@
enum
{
MOUNTAIN60_KEYBOARD_RESET_CMD = 0x03,
MOUNTAIN60_KEYBOARD_CHECK_NUMPAD = 0x08,
MOUNTAIN60_KEYBOARD_SELECT_MODE_CMD = 0x16,
MOUNTAIN60_KEYBOARD_SEND_CMD = 0x17,
@@ -15,9 +15,9 @@
using namespace std::chrono_literals;
/*-------------------------------*\
| TODO: Detect detached keypad |
\*-------------------------------*/
/*---------------------------------------------------------*\
| TODO: Detect detached keypad |
\*---------------------------------------------------------*/
std::vector<unsigned int> mountain60_keyboard_key_id_values =
{
@@ -28,7 +28,7 @@ std::vector<unsigned int> mountain60_keyboard_key_id_values =
/* CPLK A S D F G H J K L ; " ENTR */
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76,
/* LSFT Z X C V B N M , . / RSFT ARWU DEL */
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 97, 94, 56,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 97, 99, 56,
/* LCTL LWIN LALT SPC RALT RFNC FNC ARWL ARWD ARWR */
105, 106, 107, 110, 113, 115, 119, 120, 121,
};
@@ -37,9 +37,9 @@ layout_values mountain60_layout =
{
mountain60_keyboard_key_id_values,
{
/*------------------------------------------*\
| No regional layout fix for the moment |
\*------------------------------------------*/
/*---------------------------------------------*\
| No regional layout fix for the moment |
\*---------------------------------------------*/
},
};
@@ -348,9 +348,9 @@ RGBController_Mountain60Keyboard::~RGBController_Mountain60Keyboard()
mountain_thread->join();
delete mountain_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Delete the matrix map |
\*-----------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].type == ZONE_TYPE_MATRIX)
@@ -406,10 +406,10 @@ void RGBController_Mountain60Keyboard::DeviceUpdateLEDs()
{
unsigned char* color_data = new unsigned char[(leds.size()*4)];
/*---------------------------------------------------------*\
| Filling the color_data vector with progressive index |
| leaving space for RGB data |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Filling the color_data vector with progressive index |
| leaving space for RGB data |
\*-----------------------------------------------------*/
for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++)
{
const unsigned int idx = led_idx * 4;
@@ -419,7 +419,7 @@ void RGBController_Mountain60Keyboard::DeviceUpdateLEDs()
color_data[idx + 3] = RGBGetBValue(colors[led_idx]);
}
controller->SendDirect(modes[active_mode].brightness, color_data, (leds.size()*4));
controller->SendDirect(modes[active_mode].brightness, color_data, ((unsigned int)leds.size() * 4));
delete[] color_data;
}
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| NollieController.cpp |
| |
| Driver for Nollie |
@@ -82,7 +82,7 @@ void NollieController::SetMos(bool mos)
void NollieController::SetChannelLEDs(unsigned char channel, RGBColor* colors, unsigned int num_colors)
{
if(usb_pid == NOLLIE32_PID || usb_pid == NOLLIE16_PID)
if(usb_pid == NOLLIE32_PID || usb_pid == NOLLIE16_PID || usb_pid == NOLLIE32_OS21_PID || usb_pid == NOLLIE16_OS21_PID)
{
SendPacket(channel,&colors[0], num_colors);
}
@@ -162,9 +162,12 @@ void NollieController::SendPacketFS(unsigned char channel,unsigned char packet_i
packet_interval = 2;
break;
case NOLLIE8_PID:
case NOLLIE8_OS21_PID:
case PRISM8_OS21_PID:
packet_interval = 6;
break;
case NOLLIE1_PID:
case NOLLIE1_OS21_PID:
packet_interval = 30;
break;
default:
@@ -179,7 +182,7 @@ void NollieController::SendPacketFS(unsigned char channel,unsigned char packet_i
usb_buf[0x02 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]);
usb_buf[0x03 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]);
usb_buf[0x04 + (color_idx * 3)] = RGBGetBValue(colors[color_idx]);
if(dev_pid == NOLLIE8_PID || dev_pid == NOLLIE1_PID )
if(dev_pid == NOLLIE8_PID || dev_pid == NOLLIE1_PID || dev_pid == NOLLIE8_OS21_PID || dev_pid == PRISM8_OS21_PID || dev_pid == NOLLIE1_OS21_PID)
{
usb_buf[0x02 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]);
usb_buf[0x03 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]);
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| NollieController.h |
| |
| Driver for Nollie |
@@ -26,18 +26,23 @@
#define NOLLIE32_CHANNELS_NUM 32
#define NOLLIE32_PID 0x4714
#define NOLLIE32_OS21_PID 0x2A32
#define NOLLIE32_VID 0x3061
#define NOLLIE16_CHANNELS_NUM 16
#define NOLLIE16_PID 0x4716
#define NOLLIE16_OS21_PID 0x2A16
#define NOLLIE16_VID 0x3061
#define NOLLIE8_CHANNELS_NUM 8
#define NOLLIE8_PID 0x1F01
#define NOLLIE8_OS21_PID 0x2A08
#define PRISM8_OS21_PID 0x2C08
#define NOLLIE8_VID 0x16D2
#define NOLLIE1_CHANNELS_NUM 1
#define NOLLIE1_PID 0x1F11
#define NOLLIE1_OS21_PID 0x2A01
#define NOLLIE1_VID 0x16D2
#define NOLLIE28_12_CHANNELS_NUM 12
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| NollieControllerDetect.cpp |
| |
| Detector for Nollie |
@@ -16,6 +16,18 @@
void DetectNollieControllers(hid_device_info* info, const std::string& name)
{
if((info->product_id == NOLLIE1_OS21_PID || info->product_id == NOLLIE8_OS21_PID || info->product_id == PRISM8_OS21_PID)
&& info->interface_number != 2)
{
return;
}
if((info->product_id == NOLLIE16_OS21_PID || info->product_id == NOLLIE32_OS21_PID)
&& info->interface_number != 0)
{
return;
}
hid_device* dev = hid_open_path(info->path);
if(dev)
@@ -37,6 +49,11 @@ REGISTER_HID_DETECTOR("Nollie 32CH", DetectNollieControllers, NOLLIE32_VID, NOLL
REGISTER_HID_DETECTOR("Nollie 16CH", DetectNollieControllers, NOLLIE16_VID, NOLLIE16_PID);
REGISTER_HID_DETECTOR("Nollie 8CH", DetectNollieControllers, NOLLIE8_VID, NOLLIE8_PID);
REGISTER_HID_DETECTOR("Nollie 1CH", DetectNollieControllers, NOLLIE1_VID, NOLLIE1_PID);
REGISTER_HID_DETECTOR("Nollie 32_OS2.1", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE32_OS21_PID);
REGISTER_HID_DETECTOR("Nollie 16_OS2.1", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE16_OS21_PID);
REGISTER_HID_DETECTOR("Nollie 8_OS2.1", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE8_OS21_PID);
REGISTER_HID_DETECTOR("Prism 8_OS2.1", DetectNollieControllers, NOLLIERGBOS_2_VID, PRISM8_OS21_PID);
REGISTER_HID_DETECTOR("Nollie 1_OS2.1", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE1_OS21_PID);
REGISTER_HID_DETECTOR("Nollie 28 12", DetectNollieControllers, NOLLIE28_12_VID, NOLLIE28_12_PID);
REGISTER_HID_DETECTOR("Nollie 28 L1", DetectNollieControllers, NOLLIE28_12_VID, NOLLIE28_L1_PID);
REGISTER_HID_DETECTOR("Nollie 28 L2", DetectNollieControllers, NOLLIE28_12_VID, NOLLIE28_L2_PID);
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| RGBController_Nollie.cpp |
| |
| RGBController for Nollie |
@@ -64,11 +64,13 @@ void RGBController_Nollie::SetupZones()
switch(controller->GetUSBPID())
{
case NOLLIE32_PID:
case NOLLIE32_OS21_PID:
channels_num = NOLLIE32_CHANNELS_NUM;
ch_led_num = NOLLIE_HS_CH_LED_NUM;
channel_index = ch32;
break;
case NOLLIE16_PID:
case NOLLIE16_OS21_PID:
channels_num = NOLLIE16_CHANNELS_NUM;
ch_led_num = NOLLIE_HS_CH_LED_NUM;
channel_index = ch16;
@@ -80,10 +82,13 @@ void RGBController_Nollie::SetupZones()
ch_led_num = NOLLIE_12_CH_LED_NUM;
break;
case NOLLIE8_PID:
case NOLLIE8_OS21_PID:
case PRISM8_OS21_PID:
channels_num = NOLLIE8_CHANNELS_NUM;
ch_led_num = NOLLIE_8_CH_LED_NUM;
break;
case NOLLIE1_PID:
case NOLLIE1_OS21_PID:
channels_num = NOLLIE1_CHANNELS_NUM;
ch_led_num = NOLLIE_1_CH_LED_NUM;
break;
@@ -171,7 +176,7 @@ void RGBController_Nollie::ResizeZone(int zone, int new_size)
/*-----------------------------------------------------*\
| Nollie1 needs to report the number of LEDs |
\*-----------------------------------------------------*/
if(controller->GetUSBVID() == NOLLIE1_VID && controller->GetUSBPID() == NOLLIE1_PID)
if(controller->GetUSBPID() == NOLLIE1_PID)
{
controller->InitChLEDs(&new_size,NOLLIE1_CHANNELS_NUM);
}
@@ -192,7 +197,7 @@ void RGBController_Nollie::ResizeZone(int zone, int new_size)
void RGBController_Nollie::DeviceUpdateLEDs()
{
unsigned int DevPid = controller->GetUSBPID();
if(DevPid == NOLLIE32_PID || DevPid == NOLLIE16_PID)
if(DevPid == NOLLIE32_PID || DevPid == NOLLIE16_PID || DevPid == NOLLIE32_OS21_PID || DevPid == NOLLIE16_OS21_PID)
{
std::vector<int> ChSort;
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
@@ -12,11 +12,12 @@
#include "PNYARGBEpicXGPUController.h"
PNYARGBEpicXGPUController::PNYARGBEpicXGPUController(i2c_smbus_interface* bus, unsigned char init_i2c_addr, std::string name)
PNYARGBEpicXGPUController::PNYARGBEpicXGPUController(i2c_smbus_interface* bus, unsigned char init_i2c_addr, std::string name, bool large_variant)
{
this->bus = bus;
this->i2c_addr = init_i2c_addr;
this->name = name;
this->bus = bus;
this->i2c_addr = init_i2c_addr;
this->name = name;
this->large_variant = large_variant;
}
PNYARGBEpicXGPUController::~PNYARGBEpicXGPUController()
@@ -39,9 +40,14 @@ std::string PNYARGBEpicXGPUController::GetDeviceName()
return(name);
}
bool PNYARGBEpicXGPUController::IsLargeVariant()
{
return(large_variant);
}
void PNYARGBEpicXGPUController::SetZoneMode(unsigned char zone, unsigned char mode, unsigned char speed, unsigned char brightness, unsigned char subcmd, RGBColor color)
{
unsigned char data[7] =
unsigned char data[7] =
{
mode,
brightness,
@@ -69,4 +75,4 @@ void PNYARGBEpicXGPUController::SetLEDDirect(unsigned char zone, unsigned char l
};
bus->i2c_smbus_write_i2c_block_data(i2c_addr, zone, sizeof(data), data);
}
}
@@ -45,12 +45,14 @@ enum
class PNYARGBEpicXGPUController
{
public:
PNYARGBEpicXGPUController(i2c_smbus_interface* bus, unsigned char init_i2c_addr, std::string name);
PNYARGBEpicXGPUController(i2c_smbus_interface* bus, unsigned char init_i2c_addr, std::string name, bool large_variant);
~PNYARGBEpicXGPUController();
std::string GetDeviceLocation();
std::string GetDeviceName();
bool IsLargeVariant();
void SetZoneMode(unsigned char zone, unsigned char mode, unsigned char speed, unsigned char brightness, unsigned char subcmd, RGBColor color);
void SetLEDDirect(unsigned char zone, unsigned char led, unsigned char mode, RGBColor color);
@@ -58,4 +60,5 @@ private:
i2c_smbus_interface* bus;
unsigned char i2c_addr;
std::string name;
bool large_variant;
};
@@ -11,29 +11,36 @@
\*---------------------------------------------------------*/
#include "Detector.h"
#include "i2c_smbus.h"
#include "LogManager.h"
#include "pci_ids.h"
#include "PNYARGBEpicXGPUController.h"
#include "RGBController_PNYARGBEpicXGPU.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
/*-----------------------------------------------------------------------------------------*\
| DetectPNYARGBEpicXGPUControllers |
| |
| Detect PNY ARGB Epic X GPU controllers on the enumerated I2C busses at address 0x60. |
| |
| bus - pointer to i2c_smbus_interface where PNY GPU device is connected |
| dev - I2C address of PNY GPU device |
\*-----------------------------------------------------------------------------------------*/
void DetectPNYARGBEpicXGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
void DetectPNYARGBEpicXGPUSmallControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
PNYARGBEpicXGPUController* controller = new PNYARGBEpicXGPUController(bus, i2c_addr, name);
RGBController_PNYARGBEpicXGPU* rgb_controller = new RGBController_PNYARGBEpicXGPU(controller);
if(bus->port_id == 1)
{
PNYARGBEpicXGPUController* controller = new PNYARGBEpicXGPUController(bus, i2c_addr, name, false);
RGBController_PNYARGBEpicXGPU* rgb_controller = new RGBController_PNYARGBEpicXGPU(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
} /* DetectPNYARGBEpicXGPUControllers() */
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5070Ti ARGB Epic-X OC", DetectPNYARGBEpicXGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PNY_SUB_VEN, PNY_RTX_5070TI_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
//REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5080 ARGB Epic-X OC", DetectPNYARGBEpicXGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PNY_SUB_VEN, PNY_RTX_5080_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
//REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5090 ARGB Epic-X OC", DetectPNYARGBEpicXGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, PNY_SUB_VEN, PNY_RTX_5090_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
void DetectPNYARGBEpicXGPULargeControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
if(bus->port_id == 1)
{
PNYARGBEpicXGPUController* controller = new PNYARGBEpicXGPUController(bus, i2c_addr, name, true);
RGBController_PNYARGBEpicXGPU* rgb_controller = new RGBController_PNYARGBEpicXGPU(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5060Ti ARGB Epic-X OC", DetectPNYARGBEpicXGPUSmallControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, PNY_SUB_VEN, PNY_RTX_5060TI_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5070 ARGB Epic-X OC", DetectPNYARGBEpicXGPUSmallControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, PNY_SUB_VEN, PNY_RTX_5070_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5070Ti ARGB Epic-X OC", DetectPNYARGBEpicXGPUSmallControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PNY_SUB_VEN, PNY_RTX_5070TI_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5080 ARGB Epic-X OC", DetectPNYARGBEpicXGPULargeControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PNY_SUB_VEN, PNY_RTX_5080_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5090 ARGB Epic-X OC", DetectPNYARGBEpicXGPULargeControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, PNY_SUB_VEN, PNY_RTX_5090_ARGB_EPIC_X_OC_SUB_DEV, 0x60);
@@ -28,24 +28,115 @@
RGBController_PNYARGBEpicXGPU::RGBController_PNYARGBEpicXGPU(PNYARGBEpicXGPUController* controller_ptr)
{
controller = controller_ptr;
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "PNY";
description = "PNY ARGB Epic-X GPU Device";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
name = controller->GetDeviceName();
vendor = "PNY";
description = "PNY ARGB Epic-X GPU Device";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
mode Direct;
Direct.name = "Direct";
Direct.value = PNY_GPU_MODE_ARGB_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness = 0xFF;
Direct.brightness_min = 0;
Direct.brightness_max = 0xFF;
Direct.name = "Direct";
Direct.value = PNY_GPU_MODE_ARGB_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Off;
Off.name = "Off";
Off.value = PNY_GPU_MODE_ARGB_OFF;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Cycle;
Cycle.name = "Spectrum Cycle";
Cycle.value = PNY_GPU_MODE_ARGB_CYCLE;
Cycle.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Cycle.color_mode = MODE_COLORS_RANDOM;
Cycle.speed = 0x09;
Cycle.speed_min = 0x0F;
Cycle.speed_max = 0x00;
Cycle.brightness = 0xFF;
Cycle.brightness_min = 0;
Cycle.brightness_max = 0xFF;
modes.push_back(Cycle);
mode Neon;
Neon.name = "Neon";
Neon.value = PNY_GPU_MODE_ARGB_NEON;
Neon.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Neon.color_mode = MODE_COLORS_RANDOM;
Neon.speed = 0x09;
Neon.speed_min = 0x5F;
Neon.speed_max = 0x00;
Neon.brightness = 0xFF;
Neon.brightness_min = 0;
Neon.brightness_max = 0xFF;
modes.push_back(Neon);
// mode Explosion;
// Explosion.name = "Explosion";
// Explosion.value = PNY_GPU_MODE_ARGB_EXPLOSION;
// Explosion.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
// Explosion.color_mode = MODE_COLORS_MODE_SPECIFIC;
// Explosion.brightness = 0xFF;
// Explosion.brightness_min = 0;
// Explosion.brightness_max = 0xFF;
// Explosion.colors_min = 1;
// Explosion.colors_max = 1;
// Explosion.colors.resize(1);
// modes.push_back(Explosion);
// mode Supernova;
// Supernova.name = "Supernova";
// Supernova.value = PNY_GPU_MODE_ARGB_SUPERNOVA;
// Supernova.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
// Supernova.color_mode = MODE_COLORS_RANDOM;
// Supernova.brightness = 0xFF;
// Supernova.brightness_min = 0;
// Supernova.brightness_max = 0xFF;
// modes.push_back(Supernova);
mode Infinity;
Infinity.name = "Infinity";
Infinity.value = PNY_GPU_MODE_ARGB_INFINITY;
Infinity.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Infinity.color_mode = MODE_COLORS_RANDOM;
Infinity.speed = 0x09;
Infinity.speed_min = 0x5F;
Infinity.speed_max = 0x00;
Infinity.brightness = 0xFF;
Infinity.brightness_min = 0;
Infinity.brightness_max = 0xFF;
modes.push_back(Infinity);
mode Streamer;
Streamer.name = "Streamer";
Streamer.value = PNY_GPU_MODE_ARGB_STREAMER;
Streamer.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Streamer.color_mode = MODE_COLORS_RANDOM;
Streamer.speed = 0x09;
Streamer.speed_min = 0x5F;
Streamer.speed_max = 0x00;
Streamer.brightness = 0xFF;
Streamer.brightness_min = 0;
Streamer.brightness_max = 0xFF;
modes.push_back(Streamer);
mode Wave;
Wave.name = "Rainbow Wave";
Wave.value = PNY_GPU_MODE_ARGB_WAVE;
Wave.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Wave.color_mode = MODE_COLORS_RANDOM;
Wave.speed = 0x09;
Wave.speed_min = 0x5F;
Wave.speed_max = 0x00;
Wave.brightness = 0xFF;
Wave.brightness_min = 0;
Wave.brightness_max = 0xFF;
modes.push_back(Wave);
SetupZones();
active_mode = 0;
@@ -59,26 +150,39 @@ RGBController_PNYARGBEpicXGPU::~RGBController_PNYARGBEpicXGPU()
void RGBController_PNYARGBEpicXGPU::SetupZones()
{
/*-----------------------------------------------------*\
| The logo zone has 4 LEDs, but they are part of the |
| FRONT register zone |
| The side logo zone has 4 LEDs, but they are part of |
| the FRONT register zone |
| |
| This card has two variants, large and small. Large |
| is used on the 5080 and 5090 and has an extra logo |
| zone on the rear of the card as well as additional |
| LEDs in the arrow zone. The small variant is used on |
| the 5070 Ti and lower cards. |
\*-----------------------------------------------------*/
zone logo;
logo.name = "Logo";
logo.type = ZONE_TYPE_LINEAR;
logo.leds_min = 4;
logo.leds_max = 4;
logo.leds_count = 4;
logo.matrix_map = NULL;
zones.push_back(logo);
zone side_logo;
for(std::size_t led_idx = 0; led_idx < logo.leds_count; led_idx++)
if(controller->IsLargeVariant())
{
led logo_led;
side_logo.name = "Side Logo";
}
else
{
side_logo.name = "Logo";
}
logo_led.name = "Logo LED " + std::to_string(led_idx);
logo_led.value = PNY_GPU_REG_ZONE_FRONT;
side_logo.type = ZONE_TYPE_LINEAR;
side_logo.leds_min = 4;
side_logo.leds_max = 4;
side_logo.leds_count = 4;
side_logo.matrix_map = NULL;
zones.push_back(side_logo);
leds.push_back(logo_led);
for(std::size_t led_idx = 0; led_idx < side_logo.leds_count; led_idx++)
{
led side_logo_led;
side_logo_led.name = side_logo.name + " LED " + std::to_string(led_idx);
side_logo_led.value = PNY_GPU_REG_ZONE_FRONT;
leds.push_back(side_logo_led);
zone_led_idx.push_back((unsigned char)(led_idx + 20));
}
@@ -98,37 +202,67 @@ void RGBController_PNYARGBEpicXGPU::SetupZones()
for(std::size_t led_idx = 0; led_idx < front.leds_count; led_idx++)
{
led front_led;
front_led.name = "Front LED " + std::to_string(led_idx);
front_led.value = PNY_GPU_REG_ZONE_FRONT;
leds.push_back(front_led);
zone_led_idx.push_back((unsigned char)led_idx);
}
/*-----------------------------------------------------*\
| The arrow zone has 17 LEDs |
| The arrow zone has 17 LEDs on the small variant, 19 |
| LEDs on the large variant |
\*-----------------------------------------------------*/
unsigned int arrow_led_count;
if(controller->IsLargeVariant())
{
arrow_led_count = 19;
}
else
{
arrow_led_count = 17;
}
zone arrow;
arrow.name = "Arrow";
arrow.type = ZONE_TYPE_LINEAR;
arrow.leds_min = 17;
arrow.leds_max = 17;
arrow.leds_count = 17;
arrow.leds_min = arrow_led_count;
arrow.leds_max = arrow_led_count;
arrow.leds_count = arrow_led_count;
arrow.matrix_map = NULL;
zones.push_back(arrow);
for(std::size_t led_idx = 0; led_idx < arrow.leds_count; led_idx++)
{
led arrow_led;
arrow_led.name = "Arrow LED " + std::to_string(led_idx);
arrow_led.value = PNY_GPU_REG_ZONE_ARROW;
leds.push_back(arrow_led);
zone_led_idx.push_back((unsigned char)led_idx);
}
/*-----------------------------------------------------*\
| The rear logo zone is only present on the large |
| variant |
\*-----------------------------------------------------*/
if(controller->IsLargeVariant())
{
zone rear_logo;
rear_logo.name = "Rear Logo";
rear_logo.type = ZONE_TYPE_SINGLE;
rear_logo.leds_min = 1;
rear_logo.leds_max = 1;
rear_logo.leds_count = 1;
rear_logo.matrix_map = NULL;
zones.push_back(rear_logo);
led rear_logo_led;
rear_logo_led.name = "Rear Logo LED";
rear_logo_led.value = PNY_GPU_REG_ZONE_LOGO;
leds.push_back(rear_logo_led);
zone_led_idx.push_back(0);
}
SetupColors();
}
@@ -162,15 +296,36 @@ void RGBController_PNYARGBEpicXGPU::UpdateSingleLED(int led)
void RGBController_PNYARGBEpicXGPU::DeviceUpdateMode()
{
if(modes[active_mode].color_mode == MODE_COLORS_NONE || modes[active_mode].color_mode == MODE_COLORS_RANDOM)
{
controller->SetZoneMode(PNY_GPU_REG_ZONE_FRONT, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, 0);
controller->SetZoneMode(PNY_GPU_REG_ZONE_ARROW, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, 0);
if(controller->IsLargeVariant())
{
controller->SetZoneMode(PNY_GPU_REG_ZONE_LOGO, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, 0);
}
}
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
controller->SetZoneMode(PNY_GPU_REG_ZONE_FRONT, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, modes[active_mode].colors[0]);
controller->SetZoneMode(PNY_GPU_REG_ZONE_ARROW, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, modes[active_mode].colors[0]);
if(controller->IsLargeVariant())
{
controller->SetZoneMode(PNY_GPU_REG_ZONE_LOGO, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, modes[active_mode].colors[0]);
}
}
else if(modes[active_mode].color_mode == MODE_COLORS_PER_LED)
{
controller->SetZoneMode(PNY_GPU_REG_ZONE_FRONT, modes[active_mode].value, 0, 0xFF, 0, 0);
controller->SetZoneMode(PNY_GPU_REG_ZONE_ARROW, modes[active_mode].value, 0, 0xFF, 0, 0);
if(controller->IsLargeVariant())
{
controller->SetZoneMode(PNY_GPU_REG_ZONE_LOGO, modes[active_mode].value, 0, 0xFF, 0, 0);
}
DeviceUpdateLEDs();
}
}

Some files were not shown because too many files have changed in this diff Show More