Compare commits

...
Author SHA1 Message Date
SalastilandClaude Opus 5 f888b1ddbc Fix Corsair K70 RGB PRO V2 direct lighting
The K70 RGB PRO V2 (1B1C:1BB3) was detected but never lit: it blanked
into software render mode and then fell back to its onboard effect.
Getting it working turned up five faults, three of which affect every
Corsair V2 device rather than just this keyboard.

Packet size is now read from the HID report descriptor before the first
write instead of being inferred from a reply. These devices come in a 64
byte and a 1024 byte flavour, and sending a short packet to a 1024 byte
endpoint stalls it until the device is power cycled, so the size has to
be known up front rather than after two short queries have gone out.

CORSAIR_V2_PACKET_SIZE was 1024 while pkt_sze reached 1025, so every
read using pkt_sze overran its stack buffer by a byte. The command
helpers now use pkt_sze against buffers of the corrected size.

The lighting resource probe ran before the device was placed in software
render mode, where the answer is meaningless, and treated any error as
"use resource 1". Devices that answer invalid or unsupported for
resource 1 want the alternate lighting resource, which takes RGB
triplets; this keyboard is one of them. The probe now runs after the
render mode switch and distinguishes a stale open handle from an
unsupported resource.

Direct lighting writes were sized from the keymap, which covers only the
keys that exist. The hardware expects its full slot count and ignores a
short write, so corsair_v2_device carries an optional hw_led_count and
the buffer map is padded to it. Set to 193 for this keyboard.

The keepalive thread wrote LEDs on its first pass, because
last_update_time was left at the clock epoch and so always read as older
than the update period. That raced detection on the same HID handle with
no locking, which both corrupted the transaction and could abort the
process. The clock is now started before the thread runs, device
transactions are serialised behind a mutex, and the thread is stopped
before Shutdown rather than after.

Also fixes an uninitialised stack buffer sent to the device during
setup, and widens the K70 RGB PRO matrix to 22 columns so the numpad
period key has a position in the layout instead of being dropped.

Verified on hardware: repeated colour changes apply and the device stays
responsive across runs.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 21:08:51 -04:00
Alzeroff-The-Allfather f03b3472ea Add Corsair K60 RGB PRO SE support 2026-09-21 12:01:20 -05:00
Kamil Rojewski 3e53302613 Apply active profile plugin data when the GUI loads its plugins 2026-09-21 07:20:47 -05:00
Kamil Rojewski 30043e3835 Do not clear the active profile when a profile cannot be read 2026-09-21 07:20:14 +02:00
André Schwarz ce3ee27d8e Renaming PAGE_SIZE in LogitechHIDPP20Controller.cpp 2026-09-20 23:20:08 -05:00
Dmitry Kychanov 0873907793 Fix potential race condition in log message 2026-09-21 03:26:28 +04:00
rom4ster 5303e29628 Remove Debug and Extra Line 2026-09-20 15:33:55 -05:00
rom4ster ffcf003c37 Add Support for Razer Naga V3 Pro 2026-09-20 15:33:54 -05:00
ubelhj f7e0e3d77b Add MSI PRO B850-S WIFI6E to supported devices 2026-09-20 12:45:15 -05:00
Adam Honse cb0052c761 Add a mutex to protect against concurrent saving of configuration file that could result in corruption of the file 2026-09-19 15:18:47 -05:00
Jan Dvořák e075870853 Improve Intel GPU I2C bus detection 2026-09-19 14:36:31 -05:00
Victor Ferreira 4cf5fe9346 Correct the swapped brightness and speed comments
Measured on an ASRock Intel Arc B580 Steel Legend, which uses this same
packet: holding everything else fixed and stepping data[5] through 0xFF,
0x40 and 0x00 dims the zone progressively and turns it off at zero, while
data[4] does not change brightness.  So data[4] is the effect speed and
data[5] is the brightness, the other way around from what the comments
said.  The bytes written are unchanged, this only fixes the labels.
2026-09-19 14:35:25 -05:00
Victor Ferreira eb5d88537d Call Shutdown() in the ASRock GPU controller destructor
Every other ASRock controller shuts the device thread down before deleting
the controller.  This one did not, so tearing it down logs

  Device thread still active in base class destructor, ensure Shutdown()
  was called from inherited destructor

on every exit.  Seen on an ASRock Intel Arc B580 Steel Legend, but the file
is shared with the Radeon Steel Legend and Taichi cards.
2026-09-19 14:35:25 -05:00
Adam Honse d5e0c94fdc Fix LED view hiding if a device supports per-zone modes and a zone is selected that is following device mode while the device mode is per-LED 2026-09-19 14:23:37 -05:00
Petre cd44e41d46 [New Device] Gigabyte GeForce RTX 4070 SUPER Eagle OC (non-ICE) 2026-09-18 14:02:43 -05:00
epicchillman 0129e58f53 Add support for MSI PRO B850M-A WIFI motherboard 2026-09-18 01:04:25 -07:00
Adam Honse 0adfde971b Update PalitGPUControllerDetect to filter for port ID 1 (the NVIDIA OEM bus) and re-add the PALIT string check in addition to the Gainward i2c_smbus_write_quick check for V1 controllers 2026-09-18 00:47:41 -05:00
Adam Honse 27a93edec5 Add second ID for PNY RTX 5070TI ARGB Epic-X OC 2026-09-18 00:38:50 -05:00
Adam Honse 65e04a5332 Fix crash in MSI 185 controller when board config is null, fixes #5869 2026-09-18 00:24:19 -05:00
Eder Sánchez ec5ff26eda Migrate pre-1.0 AutoStart and UserInterface settings 2026-09-18 00:08:10 -05:00
Prasad Patole 51398fd6c5 Added Support for ASRock RX 9070 XT Steel Legend Dark (0x5414) 2026-09-17 23:45:02 -05:00
Adam Honse 9a6cfaf021 Add visible field to schema for hiding entries from the UI. Use it to hide the no show dialog hashes 2026-09-17 20:39:33 -05:00
Adam Honse 0a201edbc1 Fix a null pointer dereference in SendReply_PluginList 2026-09-17 16:48:41 -05:00
Adam Honse 83ea112603 Update drivers settings defaults 2026-09-16 12:04:43 -05:00
DJMalachite 2c37d4eebb [Quadcast 2 S] Edit RGBController_HyperXMicrophoneV2.cpp to fix reversed matrix map 2026-09-16 07:43:17 -05:00
Matthew Uniack 08a9f83ff4 Add PID for Corsair Sabre RGB Optical mouse (0x1B32) 2026-09-15 12:07:28 -05:00
Nicolas Wendling 1cee73e125 Add alternate subsystem device ID for Sapphire Radeon RX 9070 XT Nitro+ 2026-09-15 12:02:24 -05:00
Yoann Laissus 6f027de52b Fix layout on Gigabyte RTX 5090 XTREME WATERFORCE non WB version 2026-09-15 11:59:50 -05:00
Daniel Clark 94e7b03a50 update the led10 and led 11 zone count routine to handle new cases. 2026-09-15 11:41:11 -05:00
Adam Honse ec13cda548 Correct rc names and mark as development in AppStream manifest 2026-09-15 11:33:31 -05:00
Adam Honse de580d736c Clean up unnecessary and broken Debian dependencies 2026-09-15 11:31:50 -05:00
Adam Honse d42ed48ae1 Always reply to plugin list even if plugin manager is null 2026-09-15 11:29:32 -05:00
Adam Honse 384e1faa56 Change suffix back to git after 1.0 release 2026-09-14 17:28:04 -05:00
Adam Honse 81bbe18a84 OpenRGB version 1.0 2026-09-11 18:06:58 -05:00
Adam Honse 8eb30ba840 Fix warnings in RGBController_PalitGPUv2 2026-09-11 18:02:20 -05:00
Adam Honse f01ab516df Filter out i2c entries that are non-numeric, my PC has a /sys/bus/i2c/devices/i2c-ITE8800:00 that was failing 2026-09-11 17:57:42 -05:00
Adam Honse 0440478acb Protect against out of bounds memory type, replaces !3598 2026-09-11 17:21:29 -05:00
Denilson Martins 6bb57b8822 MSI 7E76 (MSI B840M GAMING WIFI6E) 2026-09-11 15:02:29 -05:00
Adam Honse 954027f087 Update WIX configuration to ensure default INSTALLLEVEL is 2 (service installation) and fix cut off text 2026-09-11 11:50:57 -05:00
OfotViking 243889d818 Add support for Gainward GeForce RTX 4090 Phantom 2026-09-11 10:07:00 -05:00
Adam Honse f69213db02 Palit GPU Cleanup - Merge Palit, Gainward, and PNY - V1 and V2 2026-09-11 10:07:00 -05:00
Jonathan Arellano f4173ed72f Gigabyte RGB Fusion 2 USB: apply once per zone update, not per LED 2026-09-11 09:05:09 -05:00
Jonathan Arellano 69226884cb Device page: coalesce rapid colour-wheel updates instead of queueing 2026-09-11 09:04:17 -05:00
Adam Honse 728846f668 Update screenshot 2026-09-10 20:34:04 -05:00
Adam Honse f6cfac8eef Update Debian dependencies 2026-09-10 20:23:02 -05:00
Adam Honse 9a4857ac33 Update Debian and Fedora package dependencies 2026-09-10 19:09:47 -05:00
Adam Honse 45a6c93bb3 Use 1 second TCP connection timeout for local client autoconnect 2026-09-10 13:11:01 -05:00
RedBlackAka 77285e308a Update German and Norwegian translations for 1.0 final 2026-09-10 07:25:56 -05:00
Adam Honse 84fb7d18d0 Fix warning in RGBController_Alienware.cpp 2026-09-09 21:14:08 -05:00
brenmous e161314090 Add support for MSI B850MPOWER 2026-09-09 23:26:10 +10:00
Adam Honse 0ff7f0fcd6 Fix missing handling of new zone types and fall back to legacy types for older protocols 2026-09-09 01:04:52 -05:00
Adam Honse e6ea038ac8 Update prepare-artifacts.py 2026-09-09 00:25:48 -05:00
Adam Honse 6be0193788 Add an AutoStart implementation that uses the FreeDesktop Background portal for Flatpak builds 2026-09-09 00:02:22 -05:00
Adam Honse 8963586ead Fix removing settings tab plugin, fixes #5844 2026-09-08 21:51:13 -05:00
Adam Honse 9ac50bd646 Add firmware read timeout in Corsair Lighting Node controller to prevent lockup, fixes #5838 2026-09-08 21:22:38 -05:00
Adam Honse fde019d920 Skip DPMST i2c interfaces 2026-09-08 20:13:22 -05:00
Adam Honse 2b24d0a2e9 Add firmware version check to MSIMotherboard185Controller 2026-09-08 19:59:04 -05:00
Vangel Dior afb654aa55 Added support for Gainward GeForce RTX 5080 Phoenix 2026-09-08 16:44:07 -05:00
Aman Ali 82ae818712 Add PNY GeForce RTX 3060 XLR8 Revel EPIC-X LHR (196E:138F) 2026-09-08 04:01:52 -07:00
Adam Yearout 6ac47cc4f3 HID LampArray: fix keyboard usage mappings 2026-09-08 00:43:17 -05:00
vectorseven 1e1b26e062 macOS: initialize macUSPCIO in SMBus detectors
Ensure macOS SMBus detectors initialize the macUSPCIO connection before attempting detection instead of relying on the cached connection status.

InitMacUSPCIODriver() is idempotent, so this preserves the normal startup path while allowing the detectors to establish the required connection when needed.

Also update the failure messages to report initialization failure rather than incorrectly assuming macUSPCIO is not loaded.
2026-09-08 00:42:35 -05:00
Adam Honse aaa7cb0886 Clean up MSI flags handling and add comments 2026-09-08 00:41:38 -05:00
JAO1988 a42352c867 Added MSI MAG X870E GAMING MAX WIFI motherboard 2026-09-07 22:14:01 -05:00
Michael Updike 1da6a652fd Fix Clevo ITE8291 keyboard LED value/key positional mismatch 2026-09-06 15:45:52 -05:00
jpage77 4f63756e15 RazerController: Add support for Huntsman V3 HE Magnetic Mini 2026-09-06 13:25:31 -05:00
Vangel Dior f72e99225d Fixd hid_error dlsym typo in libusb HID wrapper 2026-09-06 13:23:21 -05:00
Venatrix “Joe” Ritz 93b374ad9f TurtleBeachKP7: name the LEDs and split into three zones 2026-09-06 02:00:50 -05:00
Noocktall Klown S. (NKlownS) 2319f5c20d AlienwareController: add support, zone mapping, direction and EEPROM save for Dell G15 5520/5530 (AW-ELC) 2026-09-06 01:59:31 -05:00
JAO1988 7523e11eb5 Added ASRock Radeon RX 9070 XT Taichi 16GB OC 2026-09-06 01:55:18 -05:00
Adam Honse 523bdb96f8 Fix a crash from Apply All Devices 2026-09-05 18:38:34 -05:00
J-Man 75302d7219 Add ASUS ROG STRIX XG27ACDNG RGB detection 2026-09-05 16:51:15 -05:00
Venatrix “Joe” Ritz 56256a8054 NetworkServer: fix reversed format arguments in invalid-size log calls 2026-09-05 13:48:55 -05:00
Adam Honse ed3d7894c8 Update Realtek ARGB controller to the new configuration system 2026-09-04 21:48:39 -05:00
Daniel Clark dc14dff646 Fix reset to default in device specific settings for gigabyte motherboard usb controllers. 2026-09-04 21:11:28 -05:00
Adam Honse 706e2ab30f Make device editor the same size as zone editor 2026-09-04 19:50:09 -05:00
Ken Sanislo 3e494c884a Keep saved device configuration when controllers are remote 2026-09-04 19:40:03 -05:00
Daniel Clark 31a09bc728 Move Gigabyte USB Controller settings to Device Specific Settings. 2026-09-04 19:29:47 -05:00
Adam Honse 87b0b904c5 Add ordering support to device-specific configuration user interface 2026-09-04 19:28:27 -05:00
Ken Sanislo 07e1f2bb2a Logitech HID++ 2.0: drop the per-frame wire logs 2026-09-04 15:21:36 -05:00
Daniel Clark fd1bc449ae Update Gigabyte Motherboard USB RGB Controller 2026-09-04 09:31:50 -05:00
Adam Honse 1103a567da Keep plugin data from existing profile when saving over an existing profile, fixes #5837 2026-09-04 00:15:32 -05:00
Delnegend b420af5c42 ASRock GPU: Add Radeon RX 9060 XT Steel Legend and fix Windows ADL detection 2026-09-03 23:44:02 -05:00
Adam Honse d092f3b159 Remove colors_min/max from per-LED mode in NVIDIA Illumination controller, fixes #5836 2026-09-03 20:30:53 -05:00
Adam Honse 87af7c8dc2 Fix issues in mode set validity check - correct duplicate HAS_PERE_LED_COLOR, fix with MODE_SPECIFIC_COLOR, only check colors_min/max if mode specific color, fixes #5836 2026-09-03 20:30:07 -05:00
John Sideserf 1335a9b06c Add Gigabyte AORUS RTX 5080 MASTER ICE (0x418C) at 0x71, reject echo-bus probe responses 2026-09-03 18:46:28 -05:00
Ken Sanislo bf2a0fb8f1 HID LampArray: stop on a failed report descriptor read
hid_get_report_descriptor returns -1 on failure and the length was
stored unsigned, so the descriptor walk ran past the end of the stack
buffer. Windows reconstructs the descriptor from preparsed data and can
fail where Linux returns the kernel's copy. A failed read now leaves the
device with no lamps, the same as a descriptor with missing reports.
2026-09-03 11:11:36 -05:00
Piotr Kochan 657cc0d05d MSI 761-byte: add PRO B850M-A WIFI PZ 2026-09-03 07:13:35 -05:00
Valtekken 47eba889c2 Minor fixes for the Italian translation 2026-09-03 08:02:10 +00:00
Adam Honse 7fed68ccf1 Try notifying all to prevent lockups 2026-09-02 19:29:50 -05:00
Adam Honse 3e290907d5 Implement fair_mutex in i2c_smbus so that i2c controllers are given access to the bus in a more fair manner, which should help with high frame rates on slow buses 2026-09-02 19:12:26 -05:00
Ken Sanislo 999cbd2578 Logitech HID++ 2.0: place the G915 X top strip and G-keys 2026-09-02 14:45:04 -05:00
danielminter cf048edb6c Narrow the 0b05:19af Aura motherboard detector to its real usage page 2026-09-02 09:28:07 -05:00
Ken Sanislo a44f525078 Logitech HID++ 2.0: key the detector to the Logitech VID and the bus 2026-09-02 09:25:21 -05:00
Dmitry Kychanov 88af06182a Fix russian translations 2026-09-01 22:59:44 -05:00
Adam Honse dd35cb8cbf Update Keychron QMK controller to pull keyboard's real firmware version when connected over wireless dongle, display both dongle and keyboard version 2026-09-01 22:58:22 -05:00
Adam Honse cfc6081f9d Update Keychron QMK controller to pull keyboard's real VID when connected over wireless dongle (at least for ZMK keyboards that support full control over the wireless link) 2026-09-01 22:56:23 -05:00
Dmitry Kychanov 8f701ee147 Fix hotplugging in Logitech HID++ by using a lambda callback to un-list used IDs 2026-09-01 22:30:23 -05:00
Gent Semaj eb535f43c8 Fix AW3423DWF E_PIPE on init for newer firmware 2026-09-01 21:58:40 -05:00
JAO1988 864ea220da Added Gigabyte GTX 1080 8G Rev 2 and RX9060XT GPUs 2026-09-01 20:12:56 -04:00
Adam Honse a152927ec6 Fix warning in OpenRGBDialog.cpp 2026-09-01 11:42:11 -05:00
Adam Honse bc9c04c00b Fix warning in OpenRGBZoneEditorDialog.cpp 2026-09-01 11:41:26 -05:00
Adam Honse 648f190e22 Fix warnings in OpenRGBProfileEditorDialog.cpp 2026-09-01 11:39:09 -05:00
Adam Honse 47044213fd Fix warnings in OpenRGBDevicePage.cpp 2026-09-01 11:38:13 -05:00
Adam Honse da3f396a25 Fix warnings in ValveSteamMachineController_Windows.cpp 2026-09-01 11:36:32 -05:00
Adam Honse 0dff37baa9 Fix warnings in RGBController_EVGAX12.cpp 2026-09-01 11:32:59 -05:00
Adam Honse 44c7b9fc07 Fix warnings in RGBController_HIDLampArray.cpp 2026-09-01 11:31:28 -05:00
Adam Honse bfba7e99d0 Fix warning in RGBController_GigabyteRGBFusion2USB.cpp 2026-09-01 11:29:37 -05:00
Adam Honse cd02ba5d39 Fix warning in ClevoKeyboardController.cpp 2026-09-01 11:28:43 -05:00
Adam Honse bf03f70950 Use Fusion theme on MacOS 2026-09-01 11:24:25 -05:00
Daniel Clark c789351977 Fixes Keychron Patch Layouts (hopefully) 2026-09-01 07:43:58 -05:00
Ken Sanislo bac9cffb27 Logitech HID++ 2.0: fix effect modes, brightness and phantom LEDs on per-key keyboards 2026-09-01 07:30:40 -05:00
Adam Honse 544fd47756 Add some sanity checking around the per-LED direct mode in MSIMotherboard185Controller. Ensure the enable per-LED 185-byte packet gets sent before the large per-LED packets, skip sending packets if there are no LEDs configured 2026-09-01 00:53:59 -05:00
Adam Honse 206f211ccc More MSI installer cleanups 2026-08-31 22:57:16 -05:00
Adam Honse de7a8df31d Add the ability to register detectors that are disabled by default 2026-08-31 22:53:07 -05:00
Adam Honse 054e979fcf Fix missing text 2026-08-31 22:34:18 -05:00
Adam Honse d3e06b9124 Update CM Small ARGB name 2026-08-31 22:30:15 -05:00
Adam Honse b0c517ab9f Update CMSmallARGBController to match the changes made to CMARGBController 2026-08-31 22:17:14 -05:00
Adam Honse 7325e83e8c Clean up formatting on warning installer page 2026-08-31 21:46:18 -05:00
Adam Honse c40967989a MSI controller renames 2026-08-31 21:13:13 -05:00
Adam Honse 382b3e4d72 More MSI installer fixes 2026-08-31 21:12:42 -05:00
Adam Honse a8d46b32c2 Add Warning to installer 2026-08-31 20:36:32 -05:00
Venatrix “Joe” Ritz 72b7e5cf5b Govee: refresh Direct/Razer mode in KeepaliveThread 2026-08-31 12:31:30 -05:00
Venatrix “Joe” Ritz 5903e7e7c5 Govee: add H6046 RGBIC Gaming Light Bars support 2026-08-31 11:47:20 -05:00
Mathias Grün-Drebes 1198d3ed3c Fix use-after-free in RGBController_HIDLampArray destructor 2026-08-31 11:14:25 -05:00
homelab black d623e76d25 Fix server-host help message to show correct default IP 2026-08-31 00:52:11 -05:00
Adam Honse a1ff9c8e35 Update naming of PawnIO SMBus interfaces and add index field so that multiple buses can be distinguished 2026-08-30 21:21:09 -05:00
Adam Honse c3102bc724 Ignore interface check on Keychron QMK controller's detector as the Ultra series wireless dongles use interface 2 2026-08-30 16:40:36 -05:00
Richard van Liessum a9dea96147 Add Asus ROG Aura Monitor Light Bar and PG32UCDP support 2026-08-30 14:59:15 -05:00
Adam Honse e5823a0e10 Update udev generation to generate udev rules for PID-only and VID-only USB HID detectors 2026-08-30 02:30:45 -05:00
Adam Honse e5d3b76263 Fix issues with SetCustomMode generic implementation, it was not updating mode after setting 2026-08-30 02:04:47 -05:00
Adam Honse a757c04cf9 Fix the Keychron Q2 knob layout 2026-08-30 01:46:40 -05:00
Adam Honse 01c65c1d17 Fix the Keychron Q6 Ultra 8K layout 2026-08-30 01:43:33 -05:00
Adam Honse cfdd06e1f4 Update NZXT device list read timeout as the initial implementation was much too short for Smart Device V2 to fully detect 2026-08-30 01:02:40 -05:00
Adam Honse e2d0bee51a Update PawnIO Modules to release 0.2.11. The existing LedsValve.bin was already from this release 2026-08-30 00:12:10 -05:00
QuickMythril 280df42267 Fix EVGA X12 physical zone mapping 2026-08-30 00:01:11 -05:00
170 changed files with 11819 additions and 9699 deletions
+158
View File
@@ -0,0 +1,158 @@
/*---------------------------------------------------------*\
| AutoStart-Flatpak.cpp |
| |
| Autostart implementation for Linux via Flatpak Portal |
| |
| Adam Honse <[email protected]> 04 Sep 2026 |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "AutoStart-Flatpak.h"
#include <gio/gio.h>
AutoStart::AutoStart(std::string name)
{
InitAutoStart(name);
}
void AutoStart::InitAutoStart(std::string name)
{
app_name = name;
}
bool AutoStart::CallBackgroundPortal(bool enable, const AutoStartInfo& autostart_info)
{
GError* error = nullptr;
GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);
if(!connection)
{
if(error)
{
g_error_free(error);
}
return false;
}
/*-----------------------------------------------------*\
| FreeDesktop Background Portal parameters |
\*-----------------------------------------------------*/
const char* bus_name = "org.freedesktop.portal.Desktop";
const char* object_path = "/org/freedesktop/portal/desktop";
const char* interface_name = "org.freedesktop.portal.Background";
const char* method_name = "RequestBackground";
/*-----------------------------------------------------*\
| Build the options dictionary (vardict) required by |
| the Portal |
\*-----------------------------------------------------*/
GVariantBuilder options_builder;
g_variant_builder_init(&options_builder, G_VARIANT_TYPE_VARDICT);
/*-----------------------------------------------------*\
| Reason shown to the user in the system settings / |
| permission prompt |
\*-----------------------------------------------------*/
std::string reason_str = "Allow " + app_name + " to launch automatically at startup.";
g_variant_builder_add(&options_builder, "{sv}", "reason", g_variant_new_string(reason_str.c_str()));
/*-----------------------------------------------------*\
| Toggle the autostart feature state |
\*-----------------------------------------------------*/
g_variant_builder_add(&options_builder, "{sv}", "autostart", g_variant_new_boolean(enable));
if(enable)
{
/*-------------------------------------------------*\
| Pass command-line arguments to the background |
| request |
\*-------------------------------------------------*/
GVariantBuilder arg_builder;
g_variant_builder_init(&arg_builder, G_VARIANT_TYPE("as"));
/*-------------------------------------------------*\
| Add the primary executable path inside the |
| Flatpak sandbox |
\*-------------------------------------------------*/
g_variant_builder_add(&arg_builder, "s", GetExePath().c_str());
/*-------------------------------------------------*\
| Append any additional arguments provided by |
| OpenRGB's autostart config |
\*-------------------------------------------------*/
if(!autostart_info.args.empty())
{
g_variant_builder_add(&arg_builder, "s", autostart_info.args.c_str());
}
GVariant* commandline_args = g_variant_builder_end(&arg_builder);
g_variant_builder_add(&options_builder, "{sv}", "commandline", commandline_args);
}
/*-----------------------------------------------------*\
| An empty string window handle is used since this is a |
| background configuration request |
\*-----------------------------------------------------*/
const char* parent_window = "";
GVariant* options = g_variant_builder_end(&options_builder);
/*-----------------------------------------------------*\
| Bundle parameters: (s a{sv}) -> Parent window handle, |
| Options dictionary |
\*-----------------------------------------------------*/
GVariant* parameters = g_variant_new("(s@a{sv})", parent_window, options);
GVariant* reply;
reply = g_dbus_connection_call_sync(connection, bus_name, object_path, interface_name, method_name, parameters, G_VARIANT_TYPE("(o)"), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
g_object_unref(connection);
if(error)
{
g_error_free(error);
return false;
}
if(reply)
{
g_variant_unref(reply);
return true;
}
return false;
}
bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info)
{
return CallBackgroundPortal(true, autostart_info);
}
bool AutoStart::DisableAutoStart()
{
return CallBackgroundPortal(false);
}
bool AutoStart::IsAutoStartEnabled()
{
/*-----------------------------------------------------*\
| The FreeDesktop Background Portal does not provide a |
| stateless status getter. Sandbox permissions are |
| securely managed and persisted internally by the |
| host's portal service. To implement a true state |
| track here, OpenRGB will need to manage a local |
| boolean flag inside its own configuration files (e.g. |
| OpenRGB.json). |
\*-----------------------------------------------------*/
return false;
}
std::string AutoStart::GetExePath()
{
/*-----------------------------------------------------*\
| Flatpak applications always run from this specific |
| exported path hierarchy |
\*-----------------------------------------------------*/
return "/app/bin/openrgb";
}
+31
View File
@@ -0,0 +1,31 @@
/*---------------------------------------------------------*\
| AutoStart-Flatpak.h |
| |
| Autostart implementation for Linux via Flatpak Portal |
| |
| Adam Honse <[email protected]> 04 Sep 2026 |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "AutoStart.h"
class AutoStart : public AutoStartInterface
{
public:
AutoStart(std::string name);
bool DisableAutoStart();
bool EnableAutoStart(AutoStartInfo autostart_info);
bool IsAutoStartEnabled();
std::string GetExePath();
private:
void InitAutoStart(std::string name);
bool CallBackgroundPortal(bool enable, const AutoStartInfo& autostart_info = {});
std::string app_name;
};
+6
View File
@@ -40,9 +40,15 @@ protected:
#include "AutoStart-Windows.h"
#endif
#ifdef FLATPAK_BUILD
#include "AutoStart-Flatpak.h"
#endif
#ifdef __linux__
#ifndef FLATPAK_BUILD
#include "AutoStart-Linux.h"
#endif
#endif
#ifdef __APPLE__
#include "AutoStart-MacOS.h"
@@ -186,8 +186,8 @@ void ASRockGPUSMBusController::SetChannelColor(uint8_t channel_idx, uint8_t red,
red,
green,
blue,
0x80, // Brightness
0xFF, // Effect speed
0x80, // Effect speed
0xFF, // Brightness
0x00, // Effect direction
0x1A // Unknown constant
};
@@ -11,6 +11,7 @@
#include "ASRockGPUSMBusController.h"
#include "LogManager.h"
#include "RGBController_ASRockGPUSMBus.h"
#include "i2c_amd_gpu.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
@@ -18,15 +19,12 @@ DetectedControllers DetectASRockGPUSMBusControllers(i2c_smbus_interface* bus, ui
{
DetectedControllers detected_controllers;
LOG_DEBUG("[ASRock GPU] Checking GPU I2C bus for RGB controller at 0x%02X", address);
if(bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE) < 0)
if(bus->info.pci_vendor == AMD_GPU_VEN && !is_amd_gpu_i2c_bus(bus))
{
LOG_DEBUG("[ASRock GPU] No response at address 0x%02X", address);
return(detected_controllers);
}
LOG_DEBUG("[ASRock GPU] Device responded at 0x%02X, creating controller", address);
LOG_DEBUG("[ASRock GPU] Checking GPU I2C bus for RGB controller at 0x%02X", address);
ASRockGPUSMBusController* controller = new ASRockGPUSMBusController(bus, address, name);
@@ -43,4 +41,7 @@ DetectedControllers DetectASRockGPUSMBusControllers(i2c_smbus_interface* bus, ui
return(detected_controllers);
}
REGISTER_I2C_PCI_DETECTOR("ASRock Radeon RX 9070 XT Steel Legend", DetectASRockGPUSMBusControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, ASROCK_SUB_VEN, 0x5403, ASROCK_GPU_SMBUS_ADDRESS);
REGISTER_I2C_PCI_DETECTOR("ASRock Radeon RX 9070 XT Steel Legend", DetectASRockGPUSMBusControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, ASROCK_SUB_VEN, 0x5403, ASROCK_GPU_SMBUS_ADDRESS);
REGISTER_I2C_PCI_DETECTOR("ASRock Radeon RX 9070 XT Steel Legend Dark", DetectASRockGPUSMBusControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, ASROCK_SUB_VEN, 0x5414, ASROCK_GPU_SMBUS_ADDRESS);
REGISTER_I2C_PCI_DETECTOR("ASRock Radeon RX 9070 XT Taichi 16GB OC", DetectASRockGPUSMBusControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, ASROCK_SUB_VEN, 0x5401, ASROCK_GPU_SMBUS_ADDRESS);
REGISTER_I2C_PCI_DETECTOR("ASRock Radeon RX 9060 XT Steel Legend", DetectASRockGPUSMBusControllers, AMD_GPU_VEN, AMD_NAVI44_DEV, ASROCK_SUB_VEN, 0x5407, ASROCK_GPU_SMBUS_ADDRESS);
@@ -11,6 +11,17 @@
#include "RGBController_ASRockGPUSMBus.h"
/**------------------------------------------------------------------*\
@name ASRock GPU SMBus
@category GPU
@type I2C
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectASRockGPUSMBusControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_ASRockGPUSMBus::RGBController_ASRockGPUSMBus(ASRockGPUSMBusController* controller_ptr)
{
controller = controller_ptr;
@@ -33,6 +44,8 @@ RGBController_ASRockGPUSMBus::RGBController_ASRockGPUSMBus(ASRockGPUSMBusControl
RGBController_ASRockGPUSMBus::~RGBController_ASRockGPUSMBus()
{
Shutdown();
delete controller;
}
@@ -32,6 +32,7 @@ static const std::map<alienware_platform_id, uint8_t> zone_quirks_table =
{ 0x0C01, 4 }, // Dell G5 SE 5505
{ 0x0A01, 16 }, // Dell G7 15 7500
{ 0x0E03, 4 }, // Dell G15 5511
{ 0x0E07, 4 }, // Dell G15 5520
{ 0x0E0A, 4 } // Dell G15 5530
};
@@ -49,9 +50,21 @@ static const std::map<alienware_platform_id, std::vector<const char*>> zone_name
"Light Bar 7", "Light Bar 8", "Light Bar 9",
"Light Bar 10", "Light Bar 11", "Light Bar 12" } },
{ 0x0E03, { "Left", "Middle", "Right", "Numpad" } },
{ 0x0E07, { "Left", "Middle", "Right", "Numpad" } },
{ 0x0E0A, { "Left", "Middle", "Right", "Numpad" } }
};
/*---------------------------------------------------------*\
| Mapping the platform ID to the actual hardware zone IDs |
\*---------------------------------------------------------*/
static const std::map<alienware_platform_id, std::vector<uint8_t>> zone_ids_table =
{
{ 0x0C01, { 0x00, 0x01, 0x02, 0x03 } }, // Dell G5 SE 5505
{ 0x0E03, { 0x00, 0x01, 0x02, 0x03 } }, // Dell G15 5511
{ 0x0E07, { 0x10, 0x11, 0x12, 0x13 } }, // Dell G15 5520
{ 0x0E0A, { 0x10, 0x11, 0x12, 0x13 } } // Dell G15 5530
};
static void SendHIDReport(hid_device *dev, const unsigned char* usb_buf, size_t usb_buf_size)
{
using namespace std::chrono_literals;
@@ -138,6 +151,21 @@ AlienwareController::AlienwareController(hid_device* dev_handle, const hid_devic
}
}
/*-----------------------------------------------------*\
| Initialize hardware zone IDs |
\*-----------------------------------------------------*/
if(zone_ids_table.count(platform_id))
{
zone_ids = zone_ids_table.at(platform_id);
}
else
{
for(size_t i = 0; i < number_of_zones; i++)
{
zone_ids.push_back(static_cast<uint8_t>(i));
}
}
/*-----------------------------------------------------*\
| Set defaults for all zones |
| It doesn't seem possible to read the controller's |
@@ -155,6 +183,7 @@ AlienwareController::AlienwareController(hid_device* dev_handle, const hid_devic
zones[zone_idx].period = 2000;
zones[zone_idx].tempo = ALIENWARE_TEMPO_MAX;
zones[zone_idx].dim = 0;
zones[zone_idx].direction = 0;
}
/*-----------------------------------------------------*\
@@ -673,6 +702,15 @@ void AlienwareController::SetDim(uint8_t zone, uint8_t dim)
}
}
void AlienwareController::SetDirection(uint8_t zone, uint8_t direction)
{
if(zone < zones.size())
{
zones[zone].direction = direction;
dirty = true;
}
}
void AlienwareController::UpdateDim()
{
if(!dirty_dim)
@@ -688,7 +726,8 @@ void AlienwareController::UpdateDim()
for(size_t i = 0; i < zones.size(); i++)
{
dim_zone_map[zones[i].dim].emplace_back((uint8_t)i);
uint8_t hw_zone = (i < zone_ids.size()) ? zone_ids[i] : static_cast<uint8_t>(i);
dim_zone_map[zones[i].dim].emplace_back(hw_zone);
}
for(std::pair<const uint8_t, std::vector<uint8_t>> &pair : dim_zone_map)
@@ -715,7 +754,8 @@ bool AlienwareController::UpdateDirect()
for(size_t i = 0; i < zones.size(); i++)
{
color_zone_map[zones[i].color[0]].emplace_back((uint8_t)i);
uint8_t hw_zone = (i < zone_ids.size()) ? zone_ids[i] : static_cast<uint8_t>(i);
color_zone_map[zones[i].color[0]].emplace_back(hw_zone);
}
for(std::pair<const RGBColor, std::vector<uint8_t>> &pair : color_zone_map)
@@ -759,8 +799,9 @@ void AlienwareController::UpdateMode()
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
alienware_zone zone = zones[zone_idx];
uint8_t hw_zone = (zone_idx < zone_ids.size()) ? zone_ids[zone_idx] : static_cast<uint8_t>(zone_idx);
result = SelectZones({static_cast<uint8_t>(zone_idx)});
result = SelectZones({hw_zone});
if(!result)
{
@@ -783,18 +824,18 @@ void AlienwareController::UpdateMode()
case ALIENWARE_MODE_MORPH:
{
uint8_t zones[2] = { zone.mode, zone.mode };
uint8_t modes[2] = { zone.mode, zone.mode };
uint16_t periods[2] = { zone.period, zone.period };
uint16_t tempos[2] = { zone.tempo, zone.tempo };
RGBColor colors[2] = { zone.color[0], zone.color[1] };
result = MultiModeAction(zones, periods, tempos, colors, 2);
result = MultiModeAction(modes, periods, tempos, colors, 2);
}
break;
case ALIENWARE_MODE_SPECTRUM:
{
uint8_t zones[7] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
uint8_t modes[7] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH };
@@ -807,13 +848,13 @@ void AlienwareController::UpdateMode()
zone.tempo, zone.tempo,
zone.tempo };
result = MultiModeAction(zones, periods, tempos, rainbow_colors[0], 7);
result = MultiModeAction(modes, periods, tempos, rainbow_colors[0], 7);
}
break;
case ALIENWARE_MODE_RAINBOW:
{
uint8_t zones[7] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
uint8_t modes[7] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH };
@@ -826,18 +867,19 @@ void AlienwareController::UpdateMode()
zone.tempo, zone.tempo,
zone.tempo };
result = MultiModeAction(zones, periods, tempos, rainbow_colors[zone_idx], 7);
unsigned int color_idx = (zone.direction == MODE_DIRECTION_LEFT) ? (4 - 1 - (zone_idx % 4)) : (zone_idx % 4);
result = MultiModeAction(modes, periods, tempos, rainbow_colors[color_idx], 7);
}
break;
case ALIENWARE_MODE_BREATHING:
{
uint8_t zones[2] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH };
uint8_t modes[2] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH };
uint16_t periods[2] = { zone.period, zone.period };
uint16_t tempos[2] = { zone.tempo, zone.tempo };
RGBColor colors[2] = { zone.color[0], 0x0 };
result = MultiModeAction(zones, periods, tempos, colors, 2);
result = MultiModeAction(modes, periods, tempos, colors, 2);
}
break;
@@ -864,6 +906,117 @@ void AlienwareController::UpdateMode()
dirty = false;
}
void AlienwareController::SaveController()
{
/*-----------------------------------------------------*\
| Save current mode configuration to EEPROM slot 0x0061 |
\*-----------------------------------------------------*/
UserAnimation(ALIENWARE_COMMAND_USER_ANIM_REMOVE, ALIENWARE_ANIM_DEFAULT, 0);
bool result = UserAnimation(ALIENWARE_COMMAND_USER_ANIM_NEW, ALIENWARE_ANIM_DEFAULT, 0);
if(!result)
{
return;
}
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
alienware_zone zone = zones[zone_idx];
uint8_t hw_zone = (zone_idx < zone_ids.size()) ? zone_ids[zone_idx] : static_cast<uint8_t>(zone_idx);
result = SelectZones({hw_zone});
if(!result)
{
return;
}
switch (zone.mode)
{
case ALIENWARE_MODE_COLOR:
result = ModeAction(zone.mode, 2000, ALIENWARE_TEMPO_MAX, zone.color[0]);
break;
case ALIENWARE_MODE_PULSE:
result = ModeAction(zone.mode, zone.period, zone.tempo, zone.color[0]);
break;
case ALIENWARE_MODE_MORPH:
{
uint8_t modes[2] = { zone.mode, zone.mode };
uint16_t periods[2] = { zone.period, zone.period };
uint16_t tempos[2] = { zone.tempo, zone.tempo };
RGBColor colors[2] = { zone.color[0], zone.color[1] };
result = MultiModeAction(modes, periods, tempos, colors, 2);
}
break;
case ALIENWARE_MODE_SPECTRUM:
{
uint8_t modes[7] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH };
uint16_t periods[7] = { zone.period, zone.period,
zone.period, zone.period,
zone.period, zone.period,
zone.period };
uint16_t tempos[7] = { zone.tempo, zone.tempo,
zone.tempo, zone.tempo,
zone.tempo, zone.tempo,
zone.tempo };
result = MultiModeAction(modes, periods, tempos, rainbow_colors[0], 7);
}
break;
case ALIENWARE_MODE_RAINBOW:
{
uint8_t modes[7] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH,
ALIENWARE_MODE_MORPH };
uint16_t periods[7] = { zone.period, zone.period,
zone.period, zone.period,
zone.period, zone.period,
zone.period };
uint16_t tempos[7] = { zone.tempo, zone.tempo,
zone.tempo, zone.tempo,
zone.tempo, zone.tempo,
zone.tempo };
unsigned int color_idx = (zone.direction == MODE_DIRECTION_LEFT) ? (4 - 1 - (zone_idx % 4)) : (zone_idx % 4);
result = MultiModeAction(modes, periods, tempos, rainbow_colors[color_idx], 7);
}
break;
case ALIENWARE_MODE_BREATHING:
{
uint8_t modes[2] = { ALIENWARE_MODE_MORPH, ALIENWARE_MODE_MORPH };
uint16_t periods[2] = { zone.period, zone.period };
uint16_t tempos[2] = { zone.tempo, zone.tempo };
RGBColor colors[2] = { zone.color[0], 0x0 };
result = MultiModeAction(modes, periods, tempos, colors, 2);
}
break;
default:
result = false;
}
if(!result)
{
return;
}
}
UserAnimation(ALIENWARE_COMMAND_USER_ANIM_FINISH_SAVE, ALIENWARE_ANIM_DEFAULT, 0);
UserAnimation(ALIENWARE_COMMAND_USER_ANIM_DEFAULT, ALIENWARE_ANIM_DEFAULT, 0);
UserAnimation(ALIENWARE_COMMAND_USER_ANIM_STARTUP, ALIENWARE_ANIM_DEFAULT, 0);
}
void AlienwareController::UpdateController()
{
UpdateMode();
@@ -123,11 +123,13 @@ public:
void SetPeriod(uint8_t zone, uint16_t period);
void SetTempo(uint8_t zone, uint16_t tempo);
void SetDim(uint8_t zone, uint8_t dim);
void SetDirection(uint8_t zone, uint8_t direction);
AlienwareReport GetStatus(uint8_t subcommand);
void UpdateDim();
void UpdateMode();
void UpdateController();
void SaveController();
protected:
hid_device* dev;
@@ -140,6 +142,7 @@ private:
uint16_t period;
uint16_t tempo;
uint8_t dim;
uint8_t direction;
} alienware_zone;
typedef struct
@@ -153,6 +156,7 @@ private:
std::string serial_number;
std::string version;
std::vector<const char*> zone_names;
std::vector<uint8_t> zone_ids;
bool dirty;
bool dirty_dim;
@@ -39,7 +39,7 @@ RGBController_Alienware::RGBController_Alienware(AlienwareController* controller
mode Color;
Color.name = "Static";
Color.value = ALIENWARE_MODE_COLOR;
Color.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Color.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
Color.color_mode = MODE_COLORS_PER_LED;
Color.colors_min = 1;
Color.colors_max = 1;
@@ -51,13 +51,13 @@ RGBController_Alienware::RGBController_Alienware(AlienwareController* controller
mode Pulse;
Pulse.name = "Flashing";
Pulse.value = ALIENWARE_MODE_PULSE;
Pulse.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Pulse.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
Pulse.color_mode = MODE_COLORS_PER_LED;
Pulse.colors_min = 1;
Pulse.colors_max = 1;
Pulse.speed_min = ALIENWARE_TEMPO_MIN;
Pulse.speed_max = ALIENWARE_TEMPO_MAX;
Pulse.speed = ALIENWARE_TEMPO_MIN;
Pulse.speed_min = ALIENWARE_TEMPO_MAX;
Pulse.speed_max = 50;
Pulse.speed = 150;
Pulse.brightness_min = 100;
Pulse.brightness_max = 0;
Pulse.brightness = 0;
@@ -66,14 +66,16 @@ RGBController_Alienware::RGBController_Alienware(AlienwareController* controller
mode Morph;
Morph.name = "Morph";
Morph.value = ALIENWARE_MODE_MORPH;
Morph.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Morph.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
Morph.color_mode = MODE_COLORS_MODE_SPECIFIC;
Morph.colors_min = 2 * controller->GetZoneCount();
Morph.colors_max = Morph.colors_min;
Morph.colors.resize(Morph.colors_max);
Morph.speed_min = ALIENWARE_TEMPO_MIN;
Morph.speed_max = ALIENWARE_TEMPO_MAX;
Morph.speed = ALIENWARE_TEMPO_MIN;
Morph.colors_min = 2;
Morph.colors_max = 2 * controller->GetZoneCount();
Morph.colors.resize(2);
Morph.colors[0] = 0x0000FF;
Morph.colors[1] = 0xFF0000;
Morph.speed_min = ALIENWARE_TEMPO_MAX;
Morph.speed_max = 20;
Morph.speed = 100;
Morph.brightness_min = 100;
Morph.brightness_max = 0;
Morph.brightness = 0;
@@ -82,11 +84,11 @@ RGBController_Alienware::RGBController_Alienware(AlienwareController* controller
mode Spectrum;
Spectrum.name = "Spectrum Cycle";
Spectrum.value = ALIENWARE_MODE_SPECTRUM;
Spectrum.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Spectrum.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
Spectrum.color_mode = MODE_COLORS_NONE;
Spectrum.speed_min = ALIENWARE_TEMPO_SPECTRUM;
Spectrum.speed_max = ALIENWARE_TEMPO_MAX;
Spectrum.speed = ALIENWARE_TEMPO_SPECTRUM;
Spectrum.speed_min = ALIENWARE_TEMPO_MAX;
Spectrum.speed_max = ALIENWARE_TEMPO_SPECTRUM;
Spectrum.speed = 40;
Spectrum.brightness_min = 100;
Spectrum.brightness_max = 0;
Spectrum.brightness = 0;
@@ -95,11 +97,12 @@ RGBController_Alienware::RGBController_Alienware(AlienwareController* controller
mode Rainbow;
Rainbow.name = "Rainbow Wave";
Rainbow.value = ALIENWARE_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.speed_min = ALIENWARE_TEMPO_SPECTRUM;
Rainbow.speed_max = ALIENWARE_TEMPO_MAX;
Rainbow.speed = ALIENWARE_TEMPO_SPECTRUM;
Rainbow.speed_min = ALIENWARE_TEMPO_MAX;
Rainbow.speed_max = ALIENWARE_TEMPO_SPECTRUM;
Rainbow.speed = 40;
Rainbow.direction = MODE_DIRECTION_RIGHT;
Rainbow.brightness_min = 100;
Rainbow.brightness_max = 0;
Rainbow.brightness = 0;
@@ -108,13 +111,13 @@ RGBController_Alienware::RGBController_Alienware(AlienwareController* controller
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = ALIENWARE_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
Breathing.color_mode = MODE_COLORS_PER_LED;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.speed_min = ALIENWARE_TEMPO_MIN;
Breathing.speed_max = ALIENWARE_TEMPO_MAX;
Breathing.speed = ALIENWARE_TEMPO_MIN;
Breathing.speed_min = ALIENWARE_TEMPO_MAX;
Breathing.speed_max = 50;
Breathing.speed = 150;
Breathing.brightness_min = 100;
Breathing.brightness_max = 0;
Breathing.brightness = 0;
@@ -224,6 +227,7 @@ void RGBController_Alienware::DeviceUpdateMode()
uint16_t period = 0x07d0;
controller->SetMode(zone_idx, current_mode.value);
controller->SetDirection(zone_idx, current_mode.direction);
switch(current_mode_idx)
{
@@ -235,6 +239,7 @@ void RGBController_Alienware::DeviceUpdateMode()
break;
case ALIENWARE_MODE_PULSE:
period = std::max<uint16_t>(500, (uint16_t)(current_mode.speed * 10));
controller->SetPeriod(zone_idx, period);
controller->SetColor( zone_idx, colors[current_zone.start_idx]);
controller->SetTempo( zone_idx, current_mode.speed);
@@ -242,10 +247,22 @@ void RGBController_Alienware::DeviceUpdateMode()
break;
case ALIENWARE_MODE_MORPH:
controller->SetPeriod(zone_idx, period);
controller->SetColor( zone_idx, current_mode.colors[zone_idx * 2], current_mode.colors[(zone_idx * 2) + 1]);
controller->SetTempo( zone_idx, current_mode.speed);
controller->SetDim( zone_idx, modes[current_mode_idx].brightness);
{
RGBColor c1 = (current_mode.colors.size() >= 1) ? current_mode.colors[0] : 0x0000FF;
RGBColor c2 = (current_mode.colors.size() >= 2) ? current_mode.colors[1] : 0xFF0000;
if(current_mode.colors.size() >= (std::size_t)((zone_idx + 1) * 2))
{
c1 = current_mode.colors[zone_idx * 2];
c2 = current_mode.colors[(zone_idx * 2) + 1];
}
period = std::max<uint16_t>(400, (uint16_t)(current_mode.speed * 10));
controller->SetPeriod(zone_idx, period);
controller->SetColor( zone_idx, c1, c2);
controller->SetTempo( zone_idx, current_mode.speed);
controller->SetDim( zone_idx, modes[current_mode_idx].brightness);
}
break;
case ALIENWARE_MODE_SPECTRUM:
@@ -256,6 +273,7 @@ void RGBController_Alienware::DeviceUpdateMode()
break;
case ALIENWARE_MODE_BREATHING:
period = std::max<uint16_t>(500, (uint16_t)(current_mode.speed * 10));
controller->SetPeriod(zone_idx, period);
controller->SetColor( zone_idx, colors[current_zone.start_idx], 0x0);
controller->SetTempo( zone_idx, current_mode.speed);
@@ -282,3 +300,9 @@ void RGBController_Alienware::DeviceUpdateMode()
current_mode = new_current_mode;
}
}
void RGBController_Alienware::DeviceSaveMode()
{
controller->SaveController();
}
@@ -28,6 +28,7 @@ public:
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
void DeviceSaveMode();
private:
AlienwareController* controller;
@@ -40,11 +40,11 @@ std::vector<unsigned char> AlienwareAW3423DWFController::GetReportResponse()
void AlienwareAW3423DWFController::PerformLogin()
{
unsigned char init_packet[64] =
{
0x40, 0xE1, 0x01
};
SendControlPacket(init_packet, 4);
unsigned char init_packet[192] = {0x00};
init_packet[0] = 0x40;
init_packet[1] = 0xE1;
init_packet[2] = 0x01;
SendControlPacket(init_packet, 192);
std::vector<unsigned char> response = GetReportResponse();
@@ -417,7 +417,7 @@ REGISTER_HID_DETECTOR ("ASUS Aura Addressable", DetectAs
REGISTER_HID_DETECTOR ("ASUS Aura Addressable", DetectAsusAuraUSBAddressable, AURA_USB_VID, AURA_ADDRESSABLE_4_PID);
REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_1_PID);
REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_2_PID);
REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_3_PID);
REGISTER_HID_DETECTOR_PU("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_3_PID, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_4_PID);
REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_5_PID);
@@ -22,9 +22,12 @@
| Product ID |
\*---------------------------------------------------------*/
#define ASUS_ROG_STRIX_XG27AQDMG_PID 0x1BA3
#define ASUS_ROG_STRIX_XG27ACDNG_PID 0x1BC9
#define ASUS_ROG_STRIX_XG27UCG_PID 0x1BB4
#define ASUS_ROG_SWIFT_PG32UCDM_PID 0x1B2B
#define ASUS_ROG_SWIFT_PG32UCDMR_PID 0x1C9B
#define ASUS_ROG_SWIFT_PG32UCDP_PID 0x1BCA
#define ASUS_ROG_AURA_MONITOR_LIGHT_BAR_PID 0x1AC8
DetectedControllers DetectAsusMonitorControllers(hid_device_info* info, const std::string& name)
{
@@ -45,7 +48,13 @@ DetectedControllers DetectAsusMonitorControllers(hid_device_info* info, const st
}
REGISTER_HID_DETECTOR_IPU("Asus ROG STRIX XG27AQDMG", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_STRIX_XG27AQDMG_PID, 1, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_IPU("Asus ROG STRIX XG27ACDNG", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_STRIX_XG27ACDNG_PID, 1, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_IPU("Asus ROG STRIX XG27UCG", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_STRIX_XG27UCG_PID, 1, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_IPU("Asus ROG SWIFT PG32UCDM", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_SWIFT_PG32UCDM_PID, 1, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_IPU("Asus ROG SWIFT PG32UCDMR", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_SWIFT_PG32UCDMR_PID, 1, 0xFF72, 0x00A1);
REGISTER_HID_DETECTOR_IPU("Asus ROG SWIFT PG32UCDP", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_SWIFT_PG32UCDP_PID, 1, 0xFF72, 0x00A1);
/*---------------------------------------------------------*\
| ALB01 exposes the Aura HID collection on interface 2. |
\*---------------------------------------------------------*/
REGISTER_HID_DETECTOR_IPU("Asus ROG Aura Monitor Light Bar", DetectAsusMonitorControllers, ASUS_VID, ASUS_ROG_AURA_MONITOR_LIGHT_BAR_PID, 2, 0xFF72, 0x00A1);
@@ -335,7 +335,7 @@ void ClevoKeyboardController::SetEffect829x(unsigned char mode_value, const std:
{
for(size_t i = 0; i < colors.size() && i < 2; i++)
{
SendColorSlot829x(CLEVO_829X_CMD_SCAN_COLOR, CLEVO_829X_COLOR_SLOT_BASE + i, colors[i]);
SendColorSlot829x(CLEVO_829X_CMD_SCAN_COLOR, CLEVO_829X_COLOR_SLOT_BASE + (unsigned char)i, colors[i]);
}
}
@@ -18,71 +18,79 @@
| |
| Based on KEYBOARD_SIZE_TKL with numpad added and |
| navigation cluster adjusted to match Clevo's layout. |
| |
| Hardware LED indices (value field): |
| - Row 5 (F-keys): 105-124 |
| - Row 4 (numbers): 84-102 |
| - Row 3 (QWERTY): 63-81 |
| - Row 2 (home): 42-59 |
| - Row 1 (Z row): 22-39 |
| - Row 0 (modifiers): 0-18 |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| LED values in TKL order (fn_row + main + extras) |
| LED values, in physical (row, then column) order. |
| |
| This must match the order KeyboardLayoutManager assigns |
| default_values against: the structural keymap sorted by |
| (row, col) across main+fn_row+extras combined, NOT the |
| fn_row-then-main-then-extras order the zone tables below |
| are declared in. Getting this wrong silently misassigns |
| almost every key from Print Screen onward, not just a few.|
| |
| Values follow the key order in KeyboardLayoutManager.cpp. |
| For ANSI-only keys (not present on this ISO keyboard), |
| use 0 as a placeholder - they won't be displayed. |
| Numpad values are added via edit_keys. |
\*---------------------------------------------------------*/
static const std::vector<unsigned int> clevo_tkl_values =
{
/*---------------------------------------------------------*\
| Function row (keyboard_zone_fn_row) |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Row 0: fn_row + Print Screen/Scroll Lock/Pause |
\*-----------------------------------------------------*/
105, // Escape
106, 107, 108, 109, // F1-F4
110, 111, 112, 113, // F5-F8
114, 115, 116, 117, // F9-F12
118, // Print Screen
0, // Scroll Lock (removed via edit_keys)
0, // Pause (removed via edit_keys)
/*---------------------------------------------------------*\
| Main block - Row 1 (keyboard_zone_main) |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Row 1: numbers row + Insert/Home/Page Up |
\*-----------------------------------------------------*/
84, // Back tick
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, // 1-0
95, 96, // Minus, Equals
98, // Backspace
119, // Insert
121, // Home
122, // Page Up
/*---------------------------------------------------------*\
| Main block - Row 2 |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Row 2: Tab/QWERTY row + Delete/End/PageDown |
\*-----------------------------------------------------*/
63, // Tab
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, // Q-P
75, 76, // [ ]
0, // ANSI backslash (not on ISO)
120, // Delete
124, // End
123, // Page Down
/*---------------------------------------------------------*\
| Main block - Row 3 |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Row 3: Caps Lock/home row/Enter |
\*-----------------------------------------------------*/
42, // Caps Lock
44, 45, 46, 47, 48, 49, 50, 51, 52, // A-L
53, 54, // ; '
55, // ISO # (POUND)
77, // Enter (ANSI/ISO share same LED)
56, // Enter
/*---------------------------------------------------------*\
| Main block - Row 4 |
\*---------------------------------------------------------*/
22, // Left Shift
23, // ISO backslash
/*-----------------------------------------------------*\
| Row 4: Left Shift/ISO backslash/Z row + Up |
\*-----------------------------------------------------*/
21, // Left Shift
77, // ISO backslash
24, 25, 26, 27, 28, 29, 30, 31, 32, // Z-. (9 keys)
33, // /
35, // Right Shift
14, // Up
/*---------------------------------------------------------*\
| Main block - Row 5 |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Row 5: bottom modifier row + Left/Down/Right |
\*-----------------------------------------------------*/
0, // Left Ctrl
3, // Left Win
4, // Left Alt
@@ -91,24 +99,6 @@ static const std::vector<unsigned int> clevo_tkl_values =
0, // Right Fn (removed via edit_keys)
0, // Menu (removed via edit_keys)
12, // Right Ctrl
/*---------------------------------------------------------*\
| Extras - Navigation cluster (keyboard_zone_extras) |
\*---------------------------------------------------------*/
118, // Print Screen
0, // Scroll Lock (removed via edit_keys)
0, // Pause (removed via edit_keys)
119, // Insert
121, // Home
123, // Page Up
120, // Delete
122, // End
124, // Page Down
/*---------------------------------------------------------*\
| Extras - Arrow keys |
\*---------------------------------------------------------*/
14, // Up
13, // Left
18, // Down
15, // Right
@@ -13,11 +13,6 @@
#include "CMSmallARGBController.h"
#include "StringUtils.h"
cm_small_argb_headers cm_small_argb_header_data[1] =
{
{ "CM Small ARGB", 0x01, true, 12 }
};
CMSmallARGBController::CMSmallARGBController(hid_device* dev_handle, char *_path)
{
dev = dev_handle;
@@ -92,6 +87,24 @@ std::string CMSmallARGBController::GetSerial()
return(StringUtils::wstring_to_string(serial_string));
}
std::string CMSmallARGBController::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_SMALL_ARGB_FW0012)
{
return("0012");
}
else
{
return("Unsupported");
}
}
std::string CMSmallARGBController::GetLocation()
{
return("HID: " + location);
@@ -122,6 +135,11 @@ unsigned char CMSmallARGBController::GetLedSpeed()
return(current_speed);
}
unsigned char CMSmallARGBController::GetBrightness()
{
return(current_brightness);
}
bool CMSmallARGBController::GetRandomColours()
{
return(bool_random);
@@ -217,9 +235,9 @@ void CMSmallARGBController::SendUpdate()
hid_write(dev, buffer, buffer_size);
buffer[CM_SMALL_ARGB_COMMAND_BYTE] = 0x0b;
buffer[CM_SMALL_ARGB_FUNCTION_BYTE] = (false) ? 0x01 : 0x02; //This controls custom mode TODO
buffer[CM_SMALL_ARGB_ZONE_BYTE] = cm_small_argb_header_data[0].header;
buffer[CM_SMALL_ARGB_COMMAND_BYTE] = 0x0B;
buffer[CM_SMALL_ARGB_FUNCTION_BYTE] = 0x02;
buffer[CM_SMALL_ARGB_ZONE_BYTE] = 0x01;
buffer[CM_SMALL_ARGB_MODE_BYTE] = current_mode;
buffer[CM_SMALL_ARGB_SPEED_BYTE] = current_speed;
buffer[CM_SMALL_ARGB_COLOUR_INDEX_BYTE] = (bool_random) ? 0x00 : 0x10; //This looks to still be the colour index and controls random colours
@@ -39,16 +39,6 @@ enum
CM_SMALL_ARGB_BLUE_BYTE = 11,
};
struct cm_small_argb_headers
{
const char* name;
unsigned char header;
bool digital;
unsigned int count;
};
extern cm_small_argb_headers cm_small_argb_header_data[1];
enum
{
CM_SMALL_ARGB_MODE_SPECTRUM = 0x01, //Spectrum Mode
@@ -71,6 +61,8 @@ enum
CM_SMALL_ARGB_SPEED_FASTEST = 0x04, // Fastest speed
};
#define CM_SMALL_ARGB_FW0012 std::string("A202104052336")
class CMSmallARGBController
{
public:
@@ -80,12 +72,14 @@ public:
std::string GetDeviceName();
std::string GetSerial();
std::string GetLocation();
std::string GetVersion();
unsigned char GetMode();
unsigned char GetLedRed();
unsigned char GetLedGreen();
unsigned char GetLedBlue();
unsigned char GetLedSpeed();
unsigned char GetBrightness();
bool GetRandomColours();
void SetLedCount(int zone, int led_count);
@@ -27,22 +27,68 @@
RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmallARGBController* controller_ptr)
{
controller = controller_ptr;
unsigned char speed = controller->GetLedSpeed();
name = cm_small_argb_header_data[0].name;
name = controller->GetDeviceName();
vendor = "Cooler Master";
type = DEVICE_TYPE_LEDSTRIP;
description = controller->GetDeviceName();
version = "2.0 for FW0012";
description = "Cooler Master Small ARGB Controller Device";
version = controller->GetVersion();
serial = controller->GetSerial();
location = controller->GetLocation();
if(serial >= CM_SMALL_ARGB_FW0012)
SetupModes();
SetupZones();
/*-----------------------------------------------------*\
| Initialize the active mode to the device's current |
| mode |
\*-----------------------------------------------------*/
int device_mode = controller->GetMode();
for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++)
{
if(modes[mode_idx].value == device_mode)
{
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(controller->GetLedRed(), controller->GetLedGreen(), controller->GetLedBlue());
}
if(modes[mode_idx].flags & MODE_FLAG_HAS_SPEED)
{
modes[mode_idx].speed = controller->GetLedSpeed();
}
if(modes[mode_idx].flags & MODE_FLAG_HAS_BRIGHTNESS)
{
modes[mode_idx].brightness = controller->GetBrightness();
}
if(modes[mode_idx].flags & MODE_FLAG_HAS_RANDOM_COLOR)
{
modes[mode_idx].color_mode = controller->GetRandomColours() ? MODE_COLORS_RANDOM : MODE_COLORS_MODE_SPECIFIC;
}
break;
}
}
}
void RGBController_CMSmallARGBController::SetupModes()
{
/*-----------------------------------------------------*\
| The Small ARGB only supports Direct mode from FW0012 |
| onwards, older firmware does not accept direct mode |
| packets |
\*-----------------------------------------------------*/
//if(serial >= CM_SMALL_ARGB_FW0012)
{
mode Direct;
Direct.name = "Direct";
Direct.value = CM_SMALL_ARGB_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_REQUIRES_ENTIRE_DEVICE;
Direct.brightness_min = 0;
Direct.brightness_max = CM_SMALL_ARGB_BRIGHTNESS_MAX;
Direct.brightness = CM_SMALL_ARGB_BRIGHTNESS_MAX;
@@ -69,7 +115,7 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall
Reload.speed_min = CM_SMALL_ARGB_SPEED_SLOWEST;
Reload.speed_max = CM_SMALL_ARGB_SPEED_FASTEST;
Reload.color_mode = MODE_COLORS_RANDOM;
Reload.speed = speed;
Reload.speed = CM_SMALL_ARGB_SPEED_NORMAL;
modes.push_back(Reload);
mode Recoil;
@@ -85,7 +131,7 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall
Recoil.speed_min = CM_SMALL_ARGB_SPEED_SLOWEST;
Recoil.speed_max = CM_SMALL_ARGB_SPEED_FASTEST;
Recoil.color_mode = MODE_COLORS_RANDOM;
Recoil.speed = speed;
Recoil.speed = CM_SMALL_ARGB_SPEED_NORMAL;
modes.push_back(Recoil);
mode Breathing;
@@ -101,7 +147,7 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall
Breathing.speed_min = CM_SMALL_ARGB_SPEED_SLOWEST;
Breathing.speed_max = CM_SMALL_ARGB_SPEED_FASTEST;
Breathing.color_mode = MODE_COLORS_RANDOM;
Breathing.speed = speed;
Breathing.speed = CM_SMALL_ARGB_SPEED_NORMAL;
modes.push_back(Breathing);
mode Refill;
@@ -117,7 +163,7 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall
Refill.speed_min = CM_SMALL_ARGB_SPEED_SLOWEST;
Refill.speed_max = CM_SMALL_ARGB_SPEED_FASTEST;
Refill.color_mode = MODE_COLORS_RANDOM;
Refill.speed = speed;
Refill.speed = CM_SMALL_ARGB_SPEED_NORMAL;
modes.push_back(Refill);
mode Demo;
@@ -130,7 +176,7 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall
Demo.speed_min = CM_SMALL_ARGB_SPEED_SLOWEST;
Demo.speed_max = CM_SMALL_ARGB_SPEED_FASTEST;
Demo.color_mode = MODE_COLORS_NONE;
Demo.speed = speed;
Demo.speed = CM_SMALL_ARGB_SPEED_NORMAL;
modes.push_back(Demo);
mode Spectrum;
@@ -143,39 +189,19 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall
Spectrum.speed_min = CM_SMALL_ARGB_SPEED_SLOWEST;
Spectrum.speed_max = CM_SMALL_ARGB_SPEED_FASTEST;
Spectrum.color_mode = MODE_COLORS_NONE;
Spectrum.speed = speed;
Spectrum.speed = CM_SMALL_ARGB_SPEED_NORMAL;
modes.push_back(Spectrum);
/*-----------------------------------------------------*\
| Define Passthrough mode as requiring the entire |
| device, it hands control over to the motherboard |
\*-----------------------------------------------------*/
mode PassThru;
PassThru.name = "Pass Thru";
PassThru.value = CM_SMALL_ARGB_MODE_PASSTHRU;
PassThru.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE;
PassThru.color_mode = MODE_COLORS_NONE;
modes.push_back(PassThru);
SetupZones();
int temp_mode = controller->GetMode();
for(int mode_idx = 0; mode_idx < (int)modes.size() ; mode_idx++)
{
if(temp_mode == modes[mode_idx].value)
{
active_mode = mode_idx;
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_CMSmallARGBController::~RGBController_CMSmallARGBController()
@@ -248,7 +274,9 @@ void RGBController_CMSmallARGBController::SetupZones()
{
led new_led;
new_led.name = zones[zone_idx].name;
new_led.name.append(", LED " + std::to_string(lp_idx));
new_led.name.append(", LED ");
new_led.name.append(std::to_string(lp_idx + 1));
new_led.value = (unsigned int)zone_idx;
leds.push_back(new_led);
}
@@ -261,7 +289,7 @@ void RGBController_CMSmallARGBController::DeviceConfigureZone(int zone_idx)
{
if((size_t)zone_idx < zones.size())
{
controller->SetLedCount(cm_small_argb_header_data[zone_idx].header, zones[zone_idx].leds_count);
controller->SetLedCount(1, zones[zone_idx].leds_count);
SetupZones();
}
@@ -277,37 +305,79 @@ void RGBController_CMSmallARGBController::DeviceUpdateLEDs()
void RGBController_CMSmallARGBController::DeviceUpdateZoneLEDs(int zone)
{
if(serial >= CM_SMALL_ARGB_FW0012)
/*-----------------------------------------------------*\
| Only send direct packets while Direct mode is active. |
| Direct mode is only offered on FW0012 and newer, so |
| older firmware will never send direct packets here |
\*-----------------------------------------------------*/
if(modes[active_mode].value != CM_SMALL_ARGB_MODE_DIRECT)
{
controller->SetLedsDirect( zones[zone].colors, zones[zone].leds_count );
return;
}
controller->SetLedsDirect(zones[zone].colors, zones[zone].leds_count);
}
void RGBController_CMSmallARGBController::DeviceUpdateSingleLED(int led)
{
DeviceUpdateZoneLEDs(led);
/*-----------------------------------------------------*\
| Map the LED back to its zone and update that zone |
\*-----------------------------------------------------*/
unsigned int zone_idx = leds[led].value;
UpdateZoneLEDs(zone_idx);
}
void RGBController_CMSmallARGBController::SetCustomMode()
{
/*-------------------------------------------------*\
| The small ARGB may not support "Direct" mode |
| in which case this will select "Pass Thru" |
\*-------------------------------------------------*/
/*-----------------------------------------------------*\
| Direct mode is only supported on FW0012 and newer |
\*-----------------------------------------------------*/
if(serial >= CM_SMALL_ARGB_FW0012)
{
active_mode = 0;
/*-------------------------------------------------*\
| Search the mode list for Direct mode |
\*-------------------------------------------------*/
for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++)
{
if(modes[mode_idx].name == "Direct")
{
SetActiveMode((int)mode_idx);
break;
}
}
}
else
{
active_mode = 7;
/*-------------------------------------------------*\
| Direct mode is unsupported by the firmware, |
| fall back to Pass Thru |
\*-------------------------------------------------*/
for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++)
{
if(modes[mode_idx].value == CM_SMALL_ARGB_MODE_PASSTHRU)
{
SetActiveMode((int)mode_idx);
break;
}
}
}
}
void RGBController_CMSmallARGBController::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;
/*-----------------------------------------------------*\
| Set up mode parameters |
\*-----------------------------------------------------*/
bool random_colours = (modes[active_mode].color_mode == MODE_COLORS_RANDOM);
RGBColor colour = 0;
unsigned int speed = modes[active_mode].speed;
unsigned int brightness = modes[active_mode].brightness;
controller->SetMode( modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, colour, random_colours);
if(modes[active_mode].colors.size() > 0)
{
colour = modes[active_mode].colors[0];
}
controller->SetMode(modes[active_mode].value, speed, brightness, colour, random_colours);
}
@@ -18,7 +18,6 @@
#define CM_SMALL_ARGB_MIN_LEDS 4
#define CM_SMALL_ARGB_MAX_LEDS 48
#define CM_SMALL_ARGB_BRIGHTNESS_MAX 0xFF
#define CM_SMALL_ARGB_FW0012 "A202104052336"
class RGBController_CMSmallARGBController : public RGBController
{
@@ -26,7 +25,9 @@ public:
RGBController_CMSmallARGBController(CMSmallARGBController* controller_ptr);
~RGBController_CMSmallARGBController();
void SetupModes();
void SetupZones();
void DeviceConfigureZone(int zone_idx);
void DeviceUpdateLEDs();
@@ -35,9 +36,7 @@ public:
void SetCustomMode();
void DeviceUpdateMode();
private:
void Init_Controller();
int GetDeviceMode();
private:
CMSmallARGBController* controller;
};
@@ -327,9 +327,18 @@ DetectedControllers DetectCoolerMasterSmallARGB(hid_device_info* info, const std
if(dev)
{
CMSmallARGBController* controller = new CMSmallARGBController(dev, info->path);
RGBController_CMSmallARGBController* rgb_controller = new RGBController_CMSmallARGBController(controller);
detected_controllers.push_back(rgb_controller);
if(controller->GetVersion() != "Unsupported")
{
RGBController_CMSmallARGBController* rgb_controller = new RGBController_CMSmallARGBController(controller);
detected_controllers.push_back(rgb_controller);
}
else
{
LOG_ERROR("[CMSmallARGBController] Unsupported firmware version");
delete controller;
}
}
return(detected_controllers);
@@ -232,7 +232,7 @@ void CorsairLightingNodeController::SendFirmwareRequest()
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
actual = WriteAndRead(usb_buf);
actual = WriteAndRead(usb_buf, CORSAIR_LIGHTING_NODE_READ_TIMEOUT);
if(actual > 0)
{
@@ -81,6 +81,7 @@
#define CORSAIR_SCIMITAR_PRO_RGB_PID 0x1B3E
#define CORSAIR_SCIMITAR_ELITE_RGB_PID 0x1B8B
#define CORSAIR_SABRE_RGB_PID 0x1B2F
#define CORSAIR_SABRE_RGB_OPTICAL_PID 0x1B32
/*---------------------------------------------------------*\
| Mousepad product IDs |
@@ -215,6 +216,7 @@ REGISTER_HID_DETECTOR_IP("Corsair Scimitar RGB", DetectCorsairPeriphe
REGISTER_HID_DETECTOR_IP("Corsair Scimitar PRO RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_SCIMITAR_PRO_RGB_PID, 1, 0xFFC2);
REGISTER_HID_DETECTOR_IP("Corsair Scimitar Elite RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_SCIMITAR_ELITE_RGB_PID, 1, 0xFFC2);
REGISTER_HID_DETECTOR_IP("Corsair Sabre RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_SABRE_RGB_PID, 1, 0xFFC2);
REGISTER_HID_DETECTOR_IP("Corsair Sabre RGB Optical", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_SABRE_RGB_OPTICAL_PID, 1, 0xFFC2);
/*---------------------------------------------------------*\
| Mousemats |
@@ -29,6 +29,18 @@ CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_han
| If the PID is in the know wireless receivers list |
| switch the write_cmd to talk to the device and retry |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| Establish the packet size before talking to the device. |
\*---------------------------------------------------------*/
uint16_t report_size = GetOutputReportSize();
if(report_size >= CORSAIR_V2_WRITE_SIZE && report_size <= CORSAIR_V2_PACKET_SIZE)
{
pkt_sze = report_size;
}
LOG_DEBUG("[%s] Packet length set to %d", device_name.c_str(), pkt_sze);
unsigned int pid = GetAddressRetry(0x12);
switch(pid)
@@ -64,14 +76,12 @@ CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_han
| the device being set up. |
\*---------------------------------------------------------*/
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
memset(buffer, 0, pkt_sze);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_GET;
buffer[3] = 0x11;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
uint16_t result = hid_read_timeout(dev, buffer, CORSAIR_V2_PACKET_SIZE, CORSAIR_V2_TIMEOUT);
result++;
pkt_sze = std::max(result, (uint16_t)CORSAIR_V2_WRITE_SIZE);
LOG_DEBUG("[%s] Packet length set to %d", device_name.c_str(), pkt_sze);
hid_write(dev, buffer, pkt_sze);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
/*---------------------------------------------------------*\
| NB: If the device is not found in the device list |
@@ -108,22 +118,115 @@ CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_han
return;
}
/*---------------------------------------------------------*\
| Check lighting control endpoints |
| If lighting control endpoint 2 is unavailable |
| then use endpoint 1. |
\*---------------------------------------------------------*/
if(light_ctrl == CORSAIR_V2_LIGHT_CTRL2)
}
/*---------------------------------------------------------*\
| Check lighting control endpoints |
| If lighting control endpoint 2 is unavailable |
| then use endpoint 1. |
\*---------------------------------------------------------*/
uint16_t CorsairPeripheralV2Controller::GetOutputReportSize()
{
unsigned char descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
int length = hid_get_report_descriptor(dev, descriptor, sizeof(descriptor));
if(length <= 0)
{
result = StartTransaction(0);
if(result > 0)
{
light_ctrl = CORSAIR_V2_LIGHT_CTRL1;
StartTransaction(0);
}
StopTransaction(0);
LOG_DEBUG("[%s] Lighting Endpoint set to %02X", device_name.c_str(), light_ctrl);
return 0;
}
unsigned int report_size = 0;
unsigned int report_count = 0;
int index = 0;
while(index < length)
{
unsigned char item = descriptor[index];
unsigned char tag = item & 0xFC;
unsigned char item_size = item & 0x03;
/*---------------------------------------------------------*\
| A size field of 3 means four data bytes follow. |
\*---------------------------------------------------------*/
if(item_size == 3)
{
item_size = 4;
}
if(index + 1 + item_size > length)
{
break;
}
unsigned int value = 0;
for(unsigned char byte = 0; byte < item_size; byte++)
{
value |= (unsigned int)descriptor[index + 1 + byte] << (8 * byte);
}
switch(tag)
{
case 0x74: /* Report Size */
report_size = value;
break;
case 0x94: /* Report Count */
report_count = value;
break;
case 0x90: /* Output */
if(report_size > 0 && report_count > 0)
{
return (uint16_t)(((report_size * report_count) / 8) + 1);
}
break;
}
index += 1 + item_size;
}
return 0;
}
void CorsairPeripheralV2Controller::DetectLightingEndpoint()
{
/*---------------------------------------------------------*\
| A device that cannot be read from cannot be probed; those |
| carry the endpoint they need already set. |
\*---------------------------------------------------------*/
if(skip_reads)
{
return;
}
/*---------------------------------------------------------*\
| Lighting control 1 is the plain lighting resource and |
| takes colour block data. A device that answers |
| invalid or unsupported for it wants the alternate |
| lighting resource, which takes RGB triplets. |
\*---------------------------------------------------------*/
light_ctrl = CORSAIR_V2_LIGHT_CTRL1;
unsigned char result = StartTransaction(0);
/*---------------------------------------------------------*\
| A handle left open by an earlier session answers failed; |
| close it and open it again. |
\*---------------------------------------------------------*/
if(result == CORSAIR_V2_ERR_FAILED)
{
StopTransaction(0);
result = StartTransaction(0);
}
if(result == CORSAIR_V2_ERR_INVALID || result == CORSAIR_V2_ERR_NOT_SUPPORTED)
{
light_ctrl = CORSAIR_V2_LIGHT_CTRL2;
StartTransaction(0);
}
StopTransaction(0);
LOG_DEBUG("[%s] Lighting Endpoint set to %02X", device_name.c_str(), light_ctrl);
}
CorsairPeripheralV2Controller::~CorsairPeripheralV2Controller()
@@ -191,9 +294,9 @@ std::string CorsairPeripheralV2Controller::GetSerialString()
void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
memset(buffer, 0, pkt_sze);
/*---------------------------------------------------------*\
| Set Mode |
@@ -203,19 +306,19 @@ void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode)
buffer[3] = CORSAIR_V2_VALUE_MODE;
buffer[5] = mode;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
hid_write(dev, buffer, pkt_sze);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
}
}
void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
memset(buffer, 0, pkt_sze);
/*---------------------------------------------------------*\
| The Corsair command is the same for each initialisation |
@@ -227,11 +330,11 @@ void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1)
buffer[3] = opt1;
buffer[5] = 0x00;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
hid_write(dev, buffer, pkt_sze);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
}
}
@@ -270,18 +373,18 @@ unsigned int CorsairPeripheralV2Controller::GetAddressRetry(uint8_t address)
unsigned int CorsairPeripheralV2Controller::GetAddress(uint8_t address)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
uint8_t read[CORSAIR_V2_WRITE_SIZE];
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
uint8_t read[CORSAIR_V2_PACKET_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
memset(read, 0, CORSAIR_V2_WRITE_SIZE);
memset(buffer, 0, pkt_sze);
memset(read, 0, pkt_sze);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_GET;
buffer[3] = address;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
hid_read_timeout(dev, read, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
hid_write(dev, buffer, pkt_sze);
hid_read_timeout(dev, read, pkt_sze, CORSAIR_V2_TIMEOUT);
unsigned int temp = (unsigned int)(read[6] << 24 | read[5] << 16 | read[4] << 8 | read[3]);
LOG_DEBUG("[%s] GetAddress %02X - %02X %02X - %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(),
@@ -299,20 +402,20 @@ unsigned int CorsairPeripheralV2Controller::GetAddress(uint8_t address)
unsigned char CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
memset(buffer, 0, pkt_sze);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_START_TX;
buffer[3] = opt1;
buffer[4] = light_ctrl;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
hid_write(dev, buffer, pkt_sze);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
}
return buffer[2];
@@ -320,20 +423,20 @@ unsigned char CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1)
void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
memset(buffer, 0, pkt_sze);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_STOP_TX;
buffer[3] = 0x01;
buffer[4] = opt1;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
hid_write(dev, buffer, pkt_sze);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
}
}
@@ -347,6 +450,11 @@ void CorsairPeripheralV2Controller::ClearPacketBuffer()
uint8_t result = 0;
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
/*---------------------------------------------------------*\
| Draining expects to find nothing, so the last read here |
| always waits out the timeout. Keep it short: this runs |
| before every LED update. |
\*---------------------------------------------------------*/
do
{
result = hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
@@ -356,6 +464,8 @@ void CorsairPeripheralV2Controller::ClearPacketBuffer()
void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
{
std::lock_guard<std::mutex> lock(device_mutex);
const uint8_t offset1 = 8;
const uint8_t offset2 = 4;
uint16_t remaining = data_size;
@@ -389,7 +499,7 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
if(!skip_reads)
{
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
}
remaining -= copy_bytes;
@@ -414,7 +524,7 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
if(!skip_reads)
{
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT);
}
remaining -= copy_bytes;
@@ -426,6 +536,8 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
void CorsairPeripheralV2Controller::UpdateHWMode(uint16_t mode, corsair_v2_color /*color_mode*/, uint8_t /*speed*/,
uint8_t /*direction*/, uint8_t /*brightness*/, std::vector<RGBColor> /*colors*/)
{
std::lock_guard<std::mutex> lock(device_mutex);
/*---------------------------------------------------------*\
| If we are switching to `Direct` mode |
| set device in software mode |
@@ -12,6 +12,7 @@
#pragma once
#include <string>
#include <mutex>
#include <vector>
#include <hidapi.h>
#include "LogManager.h"
@@ -21,13 +22,33 @@
#define NA 0xFFFFFFFF
#define HID_MAX_STR 255
#define CORSAIR_V2_TIMEOUT 50
/*---------------------------------------------------------*\
| A jumbo packet device answers a 1KB command in well over |
| 50ms. Missing the reply leaves it queued and the next |
| write to the device then fails outright, so this has to |
| be generous. A reply that does arrive is returned as |
| soon as it lands, so this only costs time on failure. |
\*---------------------------------------------------------*/
#define CORSAIR_V2_TIMEOUT 500
#define CORSAIR_V2_TIMEOUT_SHORT 3
#define CORSAIR_V2_VALUE_MODE 3
#define CORSAIR_V2_WRITE_WIRED_ID 8
#define CORSAIR_V2_WRITE_WIRELESS_ID 9
#define CORSAIR_V2_WRITE_SIZE 65
#define CORSAIR_V2_PACKET_SIZE 1024
/*---------------------------------------------------------*\
| Largest packet the protocol uses: 1024 payload bytes |
| plus the leading report ID. pkt_sze is measured |
| against this, and every stack buffer handed to hidapi |
| with pkt_sze is this size, so the two must agree. |
\*---------------------------------------------------------*/
#define CORSAIR_V2_PACKET_SIZE 1025
/*---------------------------------------------------------*\
| Error codes the device returns in byte 2 of a reply. |
\*---------------------------------------------------------*/
#define CORSAIR_V2_ERR_INVALID 0x01
#define CORSAIR_V2_ERR_FAILED 0x03
#define CORSAIR_V2_ERR_NOT_SUPPORTED 0x06
#define CORSAIR_V2_LIGHT_CTRL1 1
#define CORSAIR_V2_LIGHT_CTRL2 34 /* 0x22 */
@@ -113,6 +134,27 @@ protected:
std::string device_name;
uint8_t light_ctrl = CORSAIR_V2_LIGHT_CTRL2;
/*---------------------------------------------------------*\
| Works out which lighting control endpoint the device |
| accepts. Must be called only once the device has been |
| put into software render mode: endpoint 2 rejects the |
| transaction while the device is still driving its own |
| lighting, which would pick endpoint 1 for a device that |
| does not support it. |
\*---------------------------------------------------------*/
void DetectLightingEndpoint();
/*---------------------------------------------------------*\
| Size of one output report, plus the leading report ID. |
| Read from the HID report descriptor before anything is |
| sent: these devices come in a 64 byte and a 1024 byte |
| flavour, and sending a short packet to a 1024 byte |
| endpoint wedges it until the device is reset, so the |
| size has to be known before the first write rather than |
| inferred from a reply. Returns 0 if it cannot be read. |
\*---------------------------------------------------------*/
uint16_t GetOutputReportSize();
private:
void ClearPacketBuffer();
unsigned int GetAddress(uint8_t address);
@@ -122,6 +164,16 @@ private:
hid_device* dev;
/*---------------------------------------------------------*\
| Serialises device transactions. |
| The RGB controllers run a keepalive thread that writes |
| LEDs independently of the caller, and a Corsair block |
| write spans several packets. Letting two of those |
| interleave on one HID handle corrupts the transaction |
| and leaves the device unresponsive until it is reset. |
\*---------------------------------------------------------*/
std::mutex device_mutex;
uint8_t write_cmd = CORSAIR_V2_WRITE_WIRED_ID;
uint16_t pkt_sze = CORSAIR_V2_WRITE_SIZE;
bool skip_reads = false;
@@ -92,6 +92,7 @@ DetectedControllers DetectCorsairV2SoftwareControllers(hid_device_info* info, co
REGISTER_HID_DETECTOR_IP("Corsair K55 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K55_RGB_PRO_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K57 RGB (Wired)", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K57_RGB_WIRED_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO SE", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_SE_PID, 1, 0xFF42);
REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO Low Profile", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_LP_PID, 1, 0xFF42);
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);
@@ -901,7 +901,7 @@ static const corsair_v2_device k57_rgb_wired_device =
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 21 Columns |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k60_rgb_pro_zone =
{
@@ -928,12 +928,34 @@ static const corsair_v2_device k60_rgb_pro_device =
&corsair_K60_layout
};
/*-------------------------------------------------------------*\
| Corsair K60 RGB Pro SE 1B1C:1B8D |
| |
| Initial implementation reuses K60 RGB Pro zone/layout |
\*-------------------------------------------------------------*/
static const corsair_v2_device k60_rgb_pro_se_device =
{
CORSAIR_K60_RGB_PRO_SE_PID,
DEVICE_TYPE_KEYBOARD,
6,
21,
{
&k60_rgb_pro_zone,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
},
&corsair_K60_layout
};
/*-------------------------------------------------------------*\
| Corsair K60 RGB Pro Low Profile 1B1C:1BAD |
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 21 Columns |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k60_rgb_pro_lp_zone =
{
@@ -966,7 +988,7 @@ static const corsair_v2_device k60_rgb_pro_lp_device =
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 21 Columns |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k60_rgb_pro_tkl_zone =
{
@@ -1016,7 +1038,7 @@ static const corsair_v2_device k60_rgb_pro_tkl_device_w =
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 21 Columns |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k70_core_rgb_zone =
{
@@ -1145,14 +1167,14 @@ static const corsair_v2_device k70_rgb_tkl_cs_device =
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 21 Columns |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k70_rgb_pro_zone =
{
ZONE_EN_KEYBOARD,
ZONE_TYPE_MATRIX,
7,
21
22
};
static const corsair_v2_device k70_rgb_pro_device =
@@ -1160,7 +1182,7 @@ static const corsair_v2_device k70_rgb_pro_device =
CORSAIR_K70_RGB_PRO_PID,
DEVICE_TYPE_KEYBOARD,
7,
21,
22,
{
&k70_rgb_pro_zone,
nullptr,
@@ -1177,14 +1199,14 @@ static const corsair_v2_device k70_rgb_pro_device =
| |
| Zone "Keyboard" |
| Matrix |
| 6 Rows, 21 Columns |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_device k70_rgb_pro_v2_device =
{
CORSAIR_K70_RGB_PRO_V2_PID,
DEVICE_TYPE_KEYBOARD,
7,
21,
22,
{
&k70_rgb_pro_zone,
nullptr,
@@ -1193,7 +1215,8 @@ static const corsair_v2_device k70_rgb_pro_v2_device =
nullptr,
nullptr
},
&corsair_k70_pro_layout
&corsair_k70_pro_layout,
193
};
/*-------------------------------------------------------------*\
@@ -1625,6 +1648,7 @@ const corsair_v2_device* corsair_v2_device_list_data[] =
&k55_rgb_pro_device,
&k57_rgb_wired_device,
&k60_rgb_pro_device,
&k60_rgb_pro_se_device,
&k60_rgb_pro_lp_device,
&k60_rgb_pro_tkl_device_b,
&k60_rgb_pro_tkl_device_w,
@@ -63,6 +63,15 @@ typedef struct
uint8_t cols;
const corsair_v2_zone* zones[CORSAIR_ZONES_MAX];
keyboard_keymap_overlay_values* layout_new;
/*-------------------------------------------------------*\
| Number of LED slots the device expects in a direct |
| lighting write. The keymap only covers the keys that |
| exist, but the device wants its full slot count and |
| ignores a short write, so the buffer map is padded up |
| to this. Left 0 where the count is not known, which |
| keeps the keymap derived size. |
\*-------------------------------------------------------*/
uint16_t hw_led_count;
} corsair_v2_device;
/*-----------------------------------------------------*\
@@ -72,6 +81,7 @@ typedef struct
#define CORSAIR_K57_RGB_WIRED_PID 0x1B6E
#define CORSAIR_K57_RGB_WIRELESS_PID 0x1B62
#define CORSAIR_K60_RGB_PRO_PID 0x1BA0
#define CORSAIR_K60_RGB_PRO_SE_PID 0x1B8D
#define CORSAIR_K60_RGB_PRO_LP_PID 0x1BAD
#define CORSAIR_K60_RGB_PRO_TKL_B_PID 0x1BC7
#define CORSAIR_K60_RGB_PRO_TKL_W_PID 0x1BED
@@ -16,6 +16,12 @@ CorsairPeripheralV2HWController::CorsairPeripheralV2HWController(hid_device* dev
{
SetRenderMode(CORSAIR_V2_MODE_SW);
LightingControl(0x5F);
/*---------------------------------------------------------*\
| Only now that the device is in software render mode can |
| its lighting control endpoint be probed reliably. |
\*---------------------------------------------------------*/
DetectLightingEndpoint();
}
CorsairPeripheralV2HWController::~CorsairPeripheralV2HWController()
@@ -16,6 +16,12 @@ CorsairPeripheralV2SWController::CorsairPeripheralV2SWController(hid_device* dev
{
SetRenderMode(CORSAIR_V2_MODE_SW);
LightingControl(0x5F);
/*---------------------------------------------------------*\
| Only now that the device is in software render mode can |
| its lighting control endpoint be probed reliably. |
\*---------------------------------------------------------*/
DetectLightingEndpoint();
}
CorsairPeripheralV2SWController::~CorsairPeripheralV2SWController()
@@ -66,21 +66,32 @@ RGBController_CorsairV2HW::RGBController_CorsairV2HW(CorsairPeripheralV2Controll
| to not revert back into rainbow mode. Start a thread |
| to continuously send a keepalive packet every 50 sec |
\*-----------------------------------------------------*/
/*-----------------------------------------------------*\
| Start the keepalive clock before the thread runs. |
| A default constructed time_point sits at the clock |
| epoch, which is always older than the update |
| period, so the thread would otherwise fire a write |
| on its first pass - during detection, racing |
| whatever the caller is doing. |
\*-----------------------------------------------------*/
last_update_time = std::chrono::steady_clock::now();
keepalive_thread_run = true;
keepalive_thread = new std::thread(&RGBController_CorsairV2HW::KeepaliveThread, this);
}
RGBController_CorsairV2HW::~RGBController_CorsairV2HW()
{
Shutdown();
/*-----------------------------------------------------*\
| Close keepalive thread |
| Close keepalive thread first, so that it cannot issue |
| a write while the device is being shut down. |
\*-----------------------------------------------------*/
keepalive_thread_run = false;
keepalive_thread->join();
delete keepalive_thread;
Shutdown();
delete controller;
}
@@ -198,6 +209,15 @@ void RGBController_CorsairV2HW::SetupZones()
SetupColors();
/*---------------------------------------------------------*\
| Pad out to the slot count the device expects. A write |
| that is short of it is ignored by the hardware. |
\*---------------------------------------------------------*/
if(corsair->hw_led_count > max_led_value)
{
max_led_value = corsair->hw_led_count;
}
/*---------------------------------------------------------*\
| Create a buffer map of pointers which contains the |
| layout order of colors the device expects. |
@@ -53,21 +53,32 @@ RGBController_CorsairV2SW::RGBController_CorsairV2SW(CorsairPeripheralV2Controll
| to not revert back into rainbow mode. Start a thread |
| to continuously send a keepalive packet every 50 sec |
\*-----------------------------------------------------*/
/*-----------------------------------------------------*\
| Start the keepalive clock before the thread runs. |
| A default constructed time_point sits at the clock |
| epoch, which is always older than the update |
| period, so the thread would otherwise fire a write |
| on its first pass - during detection, racing |
| whatever the caller is doing. |
\*-----------------------------------------------------*/
last_update_time = std::chrono::steady_clock::now();
keepalive_thread_run = true;
keepalive_thread = new std::thread(&RGBController_CorsairV2SW::KeepaliveThread, this);
}
RGBController_CorsairV2SW::~RGBController_CorsairV2SW()
{
Shutdown();
/*-----------------------------------------------------*\
| Close keepalive thread |
| Close keepalive thread first, so that it cannot issue |
| a write while the device is being shut down. |
\*-----------------------------------------------------*/
keepalive_thread_run = false;
keepalive_thread->join();
delete keepalive_thread;
Shutdown();
delete controller;
}
@@ -185,6 +196,15 @@ void RGBController_CorsairV2SW::SetupZones()
SetupColors();
/*---------------------------------------------------------*\
| Pad out to the slot count the device expects. A write |
| that is short of it is ignored by the hardware. |
\*---------------------------------------------------------*/
if(corsair->hw_led_count > max_led_value)
{
max_led_value = corsair->hw_led_count;
}
/*---------------------------------------------------------*\
| Create a buffer map of pointers which contains the |
| layout order of colors the device expects. |
@@ -26,6 +26,13 @@
#define EVGA_X12_READ_DELAY_MS 5
#define EVGA_X12_WRITE_ATTEMPTS 3
static const unsigned int EVGA_X12_LED_TO_FIRMWARE_SLOT[EVGA_X12_LED_COUNT] =
{
EVGA_X12_FIRMWARE_SLOT_HEAD_LEFT,
EVGA_X12_FIRMWARE_SLOT_WHEEL,
EVGA_X12_FIRMWARE_SLOT_LOGO,
};
EVGAX12Controller::EVGAX12Controller(hid_device* dev_handle, const hid_device_info& info, const std::string& dev_name)
{
dev = dev_handle;
@@ -73,7 +80,8 @@ EVGAX12LightingState EVGAX12Controller::GetLightingState()
{
for(unsigned int led_idx = 0; led_idx < EVGA_X12_LED_COUNT; led_idx++)
{
state.modes[led_idx] = packet[4 + led_idx];
unsigned int firmware_slot = EVGA_X12_LED_TO_FIRMWARE_SLOT[led_idx];
state.modes[led_idx] = packet[4 + firmware_slot];
}
}
@@ -83,7 +91,8 @@ EVGAX12LightingState EVGAX12Controller::GetLightingState()
{
for(unsigned int led_idx = 0; led_idx < EVGA_X12_LED_COUNT; led_idx++)
{
unsigned int offset = 4 + (led_idx * 4);
unsigned int firmware_slot = EVGA_X12_LED_TO_FIRMWARE_SLOT[led_idx];
unsigned int offset = 4 + (firmware_slot * 4);
state.brightness[led_idx] = packet[offset];
state.colors[led_idx] = ToRGBColor(packet[offset + 1], packet[offset + 2], packet[offset + 3]);
}
@@ -109,7 +118,8 @@ bool EVGAX12Controller::SetModeReport(unsigned char mode)
for(unsigned int led_idx = 0; led_idx < EVGA_X12_LED_COUNT; led_idx++)
{
packet[4 + led_idx] = mode;
unsigned int firmware_slot = EVGA_X12_LED_TO_FIRMWARE_SLOT[led_idx];
packet[4 + firmware_slot] = mode;
}
return(SendReport(packet));
@@ -155,14 +165,19 @@ bool EVGAX12Controller::SetStaticReport(const std::vector<RGBColor>& colors, uns
packet[2] = EVGA_X12_DIRECTION_SET;
packet[3] = EVGA_X12_COMMAND_STATIC;
for(unsigned int firmware_slot = 0; firmware_slot < EVGA_X12_FIRMWARE_SLOT_COUNT; firmware_slot++)
{
packet[20 + firmware_slot] = EVGA_X12_START_WITH_PROFILE;
}
for(unsigned int led_idx = 0; led_idx < EVGA_X12_LED_COUNT; led_idx++)
{
unsigned int offset = 4 + (led_idx * 4);
unsigned int firmware_slot = EVGA_X12_LED_TO_FIRMWARE_SLOT[led_idx];
unsigned int offset = 4 + (firmware_slot * 4);
packet[offset] = brightness;
packet[offset + 1] = RGBGetRValue(colors[led_idx]);
packet[offset + 2] = RGBGetGValue(colors[led_idx]);
packet[offset + 3] = RGBGetBValue(colors[led_idx]);
packet[20 + led_idx] = EVGA_X12_START_WITH_PROFILE;
}
for(unsigned int attempt = 0; attempt < EVGA_X12_WRITE_ATTEMPTS; attempt++)
@@ -180,9 +195,9 @@ bool EVGAX12Controller::SetStaticReport(const std::vector<RGBColor>& colors, uns
{
bool matches = true;
for(unsigned int led_idx = 0; led_idx < EVGA_X12_LED_COUNT; led_idx++)
for(unsigned int firmware_slot = 0; firmware_slot < EVGA_X12_FIRMWARE_SLOT_COUNT; firmware_slot++)
{
unsigned int offset = 4 + (led_idx * 4);
unsigned int offset = 4 + (firmware_slot * 4);
if(std::memcmp(&packet[offset], &reply[offset], 4) != 0)
{
@@ -20,7 +20,8 @@
#define EVGA_X12_REPORT_ID 0x07
#define EVGA_X12_REPORT_SIZE 40
#define EVGA_X12_LED_COUNT 4
#define EVGA_X12_LED_COUNT 3
#define EVGA_X12_FIRMWARE_SLOT_COUNT 4
#define EVGA_X12_BRIGHTNESS_MIN 0
#define EVGA_X12_BRIGHTNESS_MAX 255
@@ -30,12 +31,16 @@ enum
EVGA_X12_MODE_STATIC = 1,
};
/*---------------------------------------------------------*\
| HEAD_LEFT drives both physical side lights. HEAD_RIGHT |
| is writable and readable, but has no physical emitter. |
\*---------------------------------------------------------*/
enum
{
EVGA_X12_LED_HEAD_LEFT = 0,
EVGA_X12_LED_HEAD_RIGHT = 1,
EVGA_X12_LED_WHEEL = 2,
EVGA_X12_LED_LOGO = 3,
EVGA_X12_FIRMWARE_SLOT_HEAD_LEFT = 0,
EVGA_X12_FIRMWARE_SLOT_HEAD_RIGHT = 1,
EVGA_X12_FIRMWARE_SLOT_WHEEL = 2,
EVGA_X12_FIRMWARE_SLOT_LOGO = 3,
};
struct EVGAX12LightingState
@@ -41,14 +41,14 @@ RGBController_EVGAX12::RGBController_EVGAX12(EVGAX12Controller* controller_ptr)
Direct.brightness_max = EVGA_X12_BRIGHTNESS_MAX;
Direct.brightness = EVGA_X12_BRIGHTNESS_MAX;
Direct.color_mode = MODE_COLORS_PER_LED;
direct_mode_index = modes.size();
direct_mode_index = (unsigned int)modes.size();
modes.push_back(Direct);
mode Off;
Off.name = "Off";
Off.value = EVGA_X12_MODE_OFF;
Off.color_mode = MODE_COLORS_NONE;
off_mode_index = modes.size();
off_mode_index = (unsigned int)modes.size();
modes.push_back(Off);
active_mode = direct_mode_index;
@@ -98,8 +98,7 @@ void RGBController_EVGAX12::SetupZones()
{
const char* zone_names[EVGA_X12_LED_COUNT] =
{
"Left Head",
"Right Head",
"Side",
"Scroll Wheel",
"Logo",
};
@@ -1,102 +0,0 @@
/*---------------------------------------------------------*\
| GainwardGPUControllerDetect.cpp |
| |
| Detector for Gainward GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| KundaPanda 04 Jan 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DetectionManager.h"
#include "GainwardGPUv1Controller.h"
#include "GainwardGPUv2Controller.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
#include "RGBController_GainwardGPUv1.h"
#include "RGBController_GainwardGPUv2.h"
bool TestForGainwardGPUController(i2c_smbus_interface* bus, uint8_t i2c_addr)
{
bool pass = false;
switch(i2c_addr)
{
/*-------------------------------------------------*\
| V1 Controller |
\*-------------------------------------------------*/
case 0x08:
pass = bus->i2c_smbus_write_quick(i2c_addr, I2C_SMBUS_WRITE);
break;
/*-------------------------------------------------*\
| V2 Controller |
\*-------------------------------------------------*/
case 0x49:
/*---------------------------------------------*\
| This detection might need some modifications |
| Reading 0x6F*0x73 and comparing to 0x64 might |
| be a possibility |
\*---------------------------------------------*/
s32 data = bus->i2c_smbus_read_byte_data(i2c_addr, 0x0);
s32 mode_data = bus->i2c_smbus_read_byte_data(i2c_addr, 0xe0);
pass = (data == 0x0) && (mode_data < 0x5);
break;
}
return(pass);
}
DetectedControllers DetectGainwardGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
DetectedControllers detected_controllers;
if(TestForGainwardGPUController(bus, i2c_addr))
{
switch(i2c_addr)
{
/*---------------------------------------------*\
| V1 Controller |
\*---------------------------------------------*/
case 0x08:
{
GainwardGPUv1Controller* controller = new GainwardGPUv1Controller(bus, i2c_addr, name);
RGBController_GainwardGPUv1* rgb_controller = new RGBController_GainwardGPUv1(controller);
detected_controllers.push_back(rgb_controller);
}
break;
/*---------------------------------------------*\
| V2 Controller |
\*---------------------------------------------*/
case 0x49:
{
GainwardGPUv2Controller* controller = new GainwardGPUv2Controller(bus, i2c_addr, name);
RGBController_GainwardGPUv2* rgb_controller = new RGBController_GainwardGPUv2(controller);
detected_controllers.push_back(rgb_controller);
}
break;
}
}
return(detected_controllers);
}
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1080 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080_PHOENIX, 0x08);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1080 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080TI_PHOENIX, 0x08);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1660 SUPER Ghost", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1660S_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 2070 SUPER Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 2080 Phoenix GS", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2080_A_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3060 Pegasus 12G", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3070_PHANTOM, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070TI_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080TI_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3090_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Ti Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3090TI_PHANTOM, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 4080 Phantom GS", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4080_PHANTOM_GS_SUB_DEV, 0x49);
@@ -1,78 +0,0 @@
/*---------------------------------------------------------*\
| GainwardGPUv1Controller.cpp |
| |
| Driver for Gainward v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "GainwardGPUv1Controller.h"
GainwardGPUv1Controller::GainwardGPUv1Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id dev, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
}
GainwardGPUv1Controller::~GainwardGPUv1Controller()
{
}
std::string GainwardGPUv1Controller::GetDeviceLocation()
{
std::string return_string(bus->info.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 GainwardGPUv1Controller::GetDeviceName()
{
return(name);
}
unsigned char GainwardGPUv1Controller::GetLEDRed()
{
return(GainwardGPURegisterRead(GAINWARD_RED_REGISTER));
}
unsigned char GainwardGPUv1Controller::GetLEDGreen()
{
return(GainwardGPURegisterRead(GAINWARD_GREEN_REGISTER));
}
unsigned char GainwardGPUv1Controller::GetLEDBlue()
{
return(GainwardGPURegisterRead(GAINWARD_BLUE_REGISTER));
}
void GainwardGPUv1Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue)
{
GainwardGPURegisterWrite(GAINWARD_RED_REGISTER, red);
GainwardGPURegisterWrite(GAINWARD_GREEN_REGISTER, green);
GainwardGPURegisterWrite(GAINWARD_BLUE_REGISTER, blue);
GainwardGPURegisterWrite(GAINWARD_06_REGISTER, 0xFF);
}
void GainwardGPUv1Controller::SetMode()
{
}
unsigned char GainwardGPUv1Controller::GainwardGPURegisterRead(unsigned char reg)
{
return(bus->i2c_smbus_read_byte_data(dev, reg));
}
void GainwardGPUv1Controller::GainwardGPURegisterWrite(unsigned char reg, unsigned char val)
{
bus->i2c_smbus_write_byte_data(dev, reg, val);
}
@@ -1,115 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_GainwardGPUv1.cpp |
| |
| RGBController for Gainward v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_GainwardGPUv1.h"
int RGBController_GainwardGPUv1::GetDeviceMode()
{
active_mode = 1;
return(active_mode);
}
/**------------------------------------------------------------------*\
@name Gainward GPU v1
@category GPU
@type I2C
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectGainwardGPUControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_GainwardGPUv1::RGBController_GainwardGPUv1(GainwardGPUv1Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Gainward";
type = DEVICE_TYPE_GPU;
description = "Gainward GPU V1 Device";
location = controller->GetDeviceLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = 1;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_GainwardGPUv1::~RGBController_GainwardGPUv1()
{
Shutdown();
delete controller;
}
void RGBController_GainwardGPUv1::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zone |
\*---------------------------------------------------------*/
zone gainward_gpu_zone;
gainward_gpu_zone.name = "GPU";
gainward_gpu_zone.type = ZONE_TYPE_SINGLE;
gainward_gpu_zone.leds_min = 1;
gainward_gpu_zone.leds_max = 1;
gainward_gpu_zone.leds_count = 1;
zones.push_back(gainward_gpu_zone);
/*---------------------------------------------------------*\
| Set up LED |
\*---------------------------------------------------------*/
led gainward_gpu_led;
gainward_gpu_led.name = "GPU";
leds.push_back(gainward_gpu_led);
SetupColors();
/*---------------------------------------------------------*\
| Initialize color |
\*---------------------------------------------------------*/
unsigned char red = controller->GetLEDRed();
unsigned char grn = controller->GetLEDGreen();
unsigned char blu = controller->GetLEDBlue();
colors[0] = ToRGBColor(red, grn, blu);
}
void RGBController_GainwardGPUv1::DeviceUpdateLEDs()
{
for(std::size_t led = 0; led < colors.size(); led++)
{
unsigned char red = RGBGetRValue(colors[led]);
unsigned char grn = RGBGetGValue(colors[led]);
unsigned char blu = RGBGetBValue(colors[led]);
controller->SetLEDColors(red, grn, blu);
}
}
void RGBController_GainwardGPUv1::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_GainwardGPUv1::DeviceUpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_GainwardGPUv1::DeviceUpdateMode()
{
}
@@ -1,97 +0,0 @@
/*---------------------------------------------------------*\
| GainwardGPUv2Controller.cpp |
| |
| Driver for Gainward v2 GPU |
| |
| KundaPanda 04 Jan 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "GainwardGPUv2Controller.h"
GainwardGPUv2Controller::GainwardGPUv2Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id dev, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
}
GainwardGPUv2Controller::~GainwardGPUv2Controller() = default;
std::string GainwardGPUv2Controller::GetDeviceLocation()
{
std::string return_string(bus->info.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 GainwardGPUv2Controller::GetDeviceName()
{
return(name);
}
unsigned char GainwardGPUv2Controller::GetLEDRed()
{
return(bus->i2c_smbus_read_byte_data(dev, GAINWARD_V2_RED_REGISTER));
}
unsigned char GainwardGPUv2Controller::GetLEDGreen()
{
return(bus->i2c_smbus_read_byte_data(dev, GAINWARD_V2_GREEN_REGISTER));
}
unsigned char GainwardGPUv2Controller::GetLEDBlue()
{
return(bus->i2c_smbus_read_byte_data(dev, GAINWARD_V2_BLUE_REGISTER));
}
void GainwardGPUv2Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue, unsigned char color_register)
{
switch (color_register)
{
default:
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_RED_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_GREEN_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BLUE_REGISTER, blue);
break;
case GAINWARD_V2_COLOR_REGISTER_SECONDARY:
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_RED_SECONDARY_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_GREEN_SECONDARY_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BLUE_SECONDARY_REGISTER, blue);
break;
case GAINWARD_V2_COLOR_REGISTER_TERTIARY:
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_RED_TERTIARY_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_GREEN_TERTIARY_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BLUE_TERTIARY_REGISTER, blue);
break;
}
}
void GainwardGPUv2Controller::SetMode(unsigned char mode, unsigned char speed, unsigned char static_mode)
{
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_MODE_REGISTER, mode);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_STATIC_CONTROL_REGISTER, static_mode);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_SPEED_REGISTER, speed);
}
void GainwardGPUv2Controller::SetDirection(unsigned char direction)
{
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_MODE_DIRECTION_REGISTER, direction);
}
void GainwardGPUv2Controller::SetBreathingSpeed(unsigned int speed)
{
unsigned char lower = speed & 0xFF;
unsigned char upper = (speed >> 2 * 4) & 0xFF;
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BREATHE_SPEED_REGISTER_A, lower);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BREATHE_SPEED_SECONDARY_REGISTER_A, lower);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BREATHE_SPEED_REGISTER_B, upper);
bus->i2c_smbus_write_byte_data(dev, GAINWARD_V2_BREATHE_SPEED_SECONDARY_REGISTER_B, upper);
}
@@ -1,101 +0,0 @@
/*---------------------------------------------------------*\
| GainwardGPUv2Controller.h |
| |
| Driver for Gainward v2 GPU |
| |
| KundaPanda 04 Jan 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
typedef unsigned char gainward_gpu_dev_id;
/*---------------------------------------------------------------------------------*\
| Newer Gainward models seem to use addresses very similar to those used by EVGA |
\*-------------------------------------------------------------------------------**/
enum
{
/* RGB Registers */
GAINWARD_V2_RED_REGISTER = 0x6C, /* Red Register */
GAINWARD_V2_GREEN_REGISTER = 0x6D, /* Green Register */
GAINWARD_V2_BLUE_REGISTER = 0x6E, /* Blue Register */
GAINWARD_V2_RED_SECONDARY_REGISTER = 0x70, /* Red Register 2 */
GAINWARD_V2_GREEN_SECONDARY_REGISTER = 0x71, /* Green Register 2 */
GAINWARD_V2_BLUE_SECONDARY_REGISTER = 0x72, /* Blue Register 2 */
GAINWARD_V2_RED_TERTIARY_REGISTER = 0xE4, /* Red Register 3 */
GAINWARD_V2_GREEN_TERTIARY_REGISTER = 0xE5, /* Green Register 3 */
GAINWARD_V2_BLUE_TERTIARY_REGISTER = 0xE6, /* Blue Register 3 */
GAINWARD_V2_MODE_REGISTER = 0xE0, /* Mode Register */
/* Direct mode switch register
* 0x1 Software control
* 0x22 Breathing */
GAINWARD_V2_STATIC_CONTROL_REGISTER = 0x60,
GAINWARD_V2_BREATHE_SPEED_REGISTER_A = 0x62, /* Lower part of speed control for breathe effect */
GAINWARD_V2_BREATHE_SPEED_REGISTER_B = 0x63, /* Upper part of speed control for breathe effect */
GAINWARD_V2_BREATHE_SPEED_SECONDARY_REGISTER_A = 0x64, /* Lower part of speed control for breathe effect - prob. secondary color */
GAINWARD_V2_BREATHE_SPEED_SECONDARY_REGISTER_B = 0x65, /* Upper part of speed control for breathe effect - prob. secondary color */
/* Mode direction Register
* 0x0
* 0x1 */
GAINWARD_V2_MODE_DIRECTION_REGISTER = 0xE1,
/* Mode speed Register
* 0x0 MAX
* 0xF MIN */
GAINWARD_V2_SPEED_REGISTER = 0xE2,
};
enum
{
/* Manual color selection using primary registers */
GAINWARD_V2_MODE_STATIC = 0x00,
/* Rainbow cycling with direction and speed controls */
GAINWARD_V2_MODE_CYCLE = 0x01,
/* One strobing color running around the fan
* Color using primary registers, direction and speed control */
GAINWARD_V2_MODE_STROBE = 0x02,
};
enum
{
GAINWARD_V2_COLOR_REGISTER_PRIMARY,
GAINWARD_V2_COLOR_REGISTER_SECONDARY,
GAINWARD_V2_COLOR_REGISTER_TERTIARY,
};
enum
{
/* Software controlled direct mode */
GAINWARD_V2_STATIC_SOFTWARE = 0x01,
/* GPU controlled direct mode with breathing effect */
GAINWARD_V2_STATIC_BREATHING = 0x22,
};
class GainwardGPUv2Controller
{
public:
GainwardGPUv2Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id, std::string dev_name);
~GainwardGPUv2Controller();
std::string GetDeviceLocation();
std::string GetDeviceName();
unsigned char GetLEDRed();
unsigned char GetLEDGreen();
unsigned char GetLEDBlue();
void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue, unsigned char color_register = GAINWARD_V2_COLOR_REGISTER_PRIMARY);
void SetMode(unsigned char mode, unsigned char speed, unsigned char direct_mode = GAINWARD_V2_STATIC_SOFTWARE);
void SetBreathingSpeed(unsigned int speed);
void SetDirection(unsigned char direction);
private:
i2c_smbus_interface * bus;
gainward_gpu_dev_id dev;
std::string name;
};
@@ -1,187 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_GainwardGPUv2.cpp |
| |
| RGBController for Gainward v2 GPU |
| |
| KundaPanda 04 Jan 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_GainwardGPUv2.h"
/**------------------------------------------------------------------*\
@name Gainward GPU v2
@category GPU
@type I2C
@save :x:
@direct :x:
@effects :white_check_mark:
@detectors DetectGainwardGPUControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_GainwardGPUv2::RGBController_GainwardGPUv2(GainwardGPUv2Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Gainward";
type = DEVICE_TYPE_GPU;
description = "Gainward GPU V2 Device";
location = controller->GetDeviceLocation();
mode Static;
Static.name = "Static";
Static.value = GAINWARD_V2_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Static.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Static);
mode Breathe;
Breathe.name = "Breathing";
Breathe.value = GAINWARD_V2_MODE_STATIC;
Breathe.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Breathe.speed_max = 0x000a;
Breathe.speed_min = 0x1324;
Breathe.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathe.colors_min = 2;
Breathe.colors_max = 2;
Breathe.colors.resize(2);
modes.push_back(Breathe);
mode RainbowWave;
RainbowWave.name = "Rainbow Wave";
RainbowWave.value = GAINWARD_V2_MODE_CYCLE;
RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
RainbowWave.speed_max = 0x0;
RainbowWave.speed_min = 0xF;
RainbowWave.color_mode = MODE_COLORS_NONE;
modes.push_back(RainbowWave);
mode Strobe;
Strobe.name = "Strobe";
Strobe.value = GAINWARD_V2_MODE_STROBE;
Strobe.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Strobe.color_mode = MODE_COLORS_MODE_SPECIFIC;
Strobe.colors_min = 1;
Strobe.colors_max = 1;
Strobe.colors.resize(1);
Strobe.speed_max = 0x0;
Strobe.speed_min = 0xF;
modes.push_back(Strobe);
SetupZones();
/*-------------------------*\
| Initialize active mode |
\*-------------------------*/
active_mode = 0;
}
RGBController_GainwardGPUv2::~RGBController_GainwardGPUv2()
{
Shutdown();
delete controller;
}
void RGBController_GainwardGPUv2::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zone |
\*---------------------------------------------------------*/
zone gainward_gpu_zone;
gainward_gpu_zone.name = "GPU";
gainward_gpu_zone.type = ZONE_TYPE_SINGLE;
gainward_gpu_zone.leds_min = 1;
gainward_gpu_zone.leds_max = 1;
gainward_gpu_zone.leds_count = 1;
zones.push_back(gainward_gpu_zone);
/*---------------------------------------------------------*\
| Set up LED |
\*---------------------------------------------------------*/
led gainward_gpu_led;
gainward_gpu_led.name = "GPU";
leds.push_back(gainward_gpu_led);
SetupColors();
/*---------------------------------------------------------*\
| Initialize color |
\*---------------------------------------------------------*/
unsigned char red = controller->GetLEDRed();
unsigned char grn = controller->GetLEDGreen();
unsigned char blu = controller->GetLEDBlue();
colors[0] = ToRGBColor(red, grn, blu);
}
void RGBController_GainwardGPUv2::DeviceUpdateLEDs()
{
for(unsigned int color : colors)
{
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
controller->SetLEDColors(red, grn, blu);
controller->SetMode(GAINWARD_V2_MODE_STATIC, 0x2);
}
}
void RGBController_GainwardGPUv2::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_GainwardGPUv2::DeviceUpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_GainwardGPUv2::DeviceUpdateMode()
{
mode current_mode = modes[(unsigned int)active_mode];
switch (active_mode)
{
case 1:
{
controller->SetBreathingSpeed(current_mode.speed);
unsigned char r1 = RGBGetRValue(current_mode.colors[0]);
unsigned char g1 = RGBGetGValue(current_mode.colors[0]);
unsigned char b1 = RGBGetBValue(current_mode.colors[0]);
controller->SetLEDColors(r1, g1, b1);
unsigned char r2 = RGBGetRValue(current_mode.colors[1]);
unsigned char g2 = RGBGetGValue(current_mode.colors[1]);
unsigned char b2 = RGBGetBValue(current_mode.colors[1]);
controller->SetLEDColors(r2, g2, b2, GAINWARD_V2_COLOR_REGISTER_SECONDARY);
controller->SetMode(GAINWARD_V2_MODE_STATIC, 0x2, GAINWARD_V2_STATIC_BREATHING);
}
break;
/*---------------------------------------------*\
| Case 3 intentionally falls through to case 2 |
\*---------------------------------------------*/
case 3:
{
unsigned char r = RGBGetRValue(current_mode.colors[0]);
unsigned char g = RGBGetGValue(current_mode.colors[0]);
unsigned char b = RGBGetBValue(current_mode.colors[0]);
controller->SetLEDColors(r, g, b, GAINWARD_V2_COLOR_REGISTER_TERTIARY);
}
case 2:
controller->SetMode((unsigned char)(current_mode.value), (unsigned char)(current_mode.speed));
controller->SetDirection(current_mode.direction);
break;
default:
controller->SetMode((unsigned char)(current_mode.value), (unsigned char)(current_mode.speed));
break;
}
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_GainwardGPUv2.h |
| |
| RGBController for Gainward v2 GPU |
| |
| KundaPanda 04 Jan 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "GainwardGPUv2Controller.h"
class RGBController_GainwardGPUv2 : public RGBController
{
public:
RGBController_GainwardGPUv2(GainwardGPUv2Controller* controller_ptr);
~RGBController_GainwardGPUv2();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
GainwardGPUv2Controller* controller;
};
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| GigabyteRGBFusion2BlackwellGPUControllerDetect.cpp |
| |
| Detector for Gigabyte RGB Fusion 2 Blackwell GPU |
@@ -130,8 +130,8 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 XTREME WATERFORCE",
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);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE WB", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_WB_32G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090_MASTER_32G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER ICE", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090_MASTER_ICE_32G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 D V2 MASTER ICE", DetectGigabyteRGBFusion2BlackwellAorusMaster5090DV2IceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090D_V2_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090D_V2_MASTER_ICE_24G_SUB_DEV, 0x75);
@@ -139,6 +139,7 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 D V2 MASTER ICE",
/*---------------------------------------------------------*\
| AMD GPUs |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9060 GAMING OC 8G", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI44_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9060XT_GAMING_OC_8G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9060 XT GAMING", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI44_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9060XT_GAMING_16G_SUB_DEV, 0x75);
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);
@@ -52,8 +52,12 @@ bool TestForGigabyteRGBFusion2GPUController(i2c_smbus_interface* bus, unsigned c
//Note that GeForce RTX 4080 Gigabyte AORUS MASTER 16G exposes two i2c bus with writable address 0x71 but one respond
//0x00 0x00 0x00 0x00 so it should be the one controlling the LCD screen. So we skip this bus
//All seen responses start with 0xAB, so we check for this.
if(res < 0 || data_readpkt[0] != 0xAB)
//All seen responses start with 0xAB, so we check for this. A DDC/EDID
//style bus can echo the written command byte back for every read, so an
//all-0xAB response is a mirror, not a controller; every real controller
//seen so far follows 0xAB with version bytes (see table above).
if(res < 0 || data_readpkt[0] != 0xAB ||
(data_readpkt[1] == 0xAB && data_readpkt[2] == 0xAB && data_readpkt[3] == 0xAB))
{
// Assemble C-string with respons for debugging
std::string text = "";
@@ -140,7 +144,8 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 GAMING OC",
REGISTER_I2C_PCI_DETECTOR("Gigabyte Geforce RTX 4070 Aero OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_AERO_OC_12G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_GAMING_OC_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER Aero OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_AERO_OC_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER Eagle OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_EAGLE_OC_ICE_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER Eagle OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_EAGLE_OC_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER Eagle OC ICE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_EAGLE_OC_ICE_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti GAMING", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_OC_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_OC_12G_SUB_DEV2, 0x71);
@@ -162,6 +167,7 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4090 GAMING OC",
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 4090 MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX4090_MASTER_24G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 D MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5090D_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090D_MASTER_32G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_GAMING_OC_16G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER ICE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_ICE_16G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5090D_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090_MASTER_32G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER ICE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090_MASTER_ICE_32G_SUB_DEV, 0x71);
@@ -183,8 +189,9 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XT GAMING OC",
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 MASTER rev 2.0", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX6900XT_MASTER_SUB_DEV, 0x70);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6900 XT MASTER rev 2.0", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX6900XT_MASTER_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 Radeon RX 9060 XT GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI44_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9060XT_GAMING_OC_8G_SUB_DEV, 0x73);
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);
@@ -4,8 +4,8 @@
| Gigabyte Fusion 2 USB Device layouts and |
| and mapping to the device IDs stored on chip |
| |
| megadjc 31 Jul 2025 |
| chrism 29 Aug 2025 |
| megadjc 03 Sep 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
@@ -19,16 +19,16 @@
static const gb_fusion2_zone common_d_led_zone =
{
HDR_D_LED1,
0,
1024,
RGBFUSION2_DLED_LEDS_MIN,
RGBFUSION2_DLED_LEDS_MAX,
"D_LED"
};
static const gb_fusion2_zone common_gc_usb_d_led_zone =
{
LED1,
0,
1024,
RGBFUSION2_DLED_LEDS_MIN,
RGBFUSION2_DLED_LEDS_MAX,
"D_LED"
};
@@ -36,48 +36,48 @@ static const gb_fusion2_zone common_gc_usb_d_led_zone =
static const gb_fusion2_zone common_d_led1_zone =
{
HDR_D_LED1,
0,
1024,
RGBFUSION2_DLED_LEDS_MIN,
RGBFUSION2_DLED_LEDS_MAX,
"D_LED1"
};
static const gb_fusion2_zone common_dled1_dled2_zone =
{
HDR_D_LED1,
0,
1024,
RGBFUSION2_DLED_LEDS_MIN,
RGBFUSION2_DLED_LEDS_MAX,
"D_LED1/D_LED2"
};
static const gb_fusion2_zone common_argb_v2_1_zone =
{
HDR_D_LED1,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_1"
};
static const gb_fusion2_zone alt_argb_v2_1_zone =
{
LED3,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_1"
};
static const gb_fusion2_zone common_argb_v2_1_3_zone =
{
HDR_D_LED1,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_1/ARGB_V2_3"
};
static const gb_fusion2_zone common_d_led2_zone =
{
HDR_D_LED2,
0,
1024,
RGBFUSION2_DLED_LEDS_MIN,
RGBFUSION2_DLED_LEDS_MAX,
"D_LED2"
};
@@ -85,47 +85,47 @@ static const gb_fusion2_zone common_d_led2_aux_zone =
{
HDR_D_LED2,
2,
1024,
RGBFUSION2_DLED_LEDS_MAX,
"D_LED2 + Aux"
};
static const gb_fusion2_zone common_argb_v2_2_zone =
{
HDR_D_LED2,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_2"
};
static const gb_fusion2_zone alt_argb_v2_2_zone =
{
LED4,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_2"
};
static const gb_fusion2_zone common_argb_v2_3_1_zone =
{
HDR_D_LED1,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_3"
};
static const gb_fusion2_zone common_argb_v2_3_zone =
{
HDR_D_LED3,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_3"
};
static const gb_fusion2_zone common_argb_v2_4_zone =
{
HDR_D_LED4,
0,
1024,
RGBFUSION2_57XX_LEDS_MIN,
RGBFUSION2_57XX_LEDS_MAX,
"ARGB_V2_4"
};
@@ -4,8 +4,8 @@
| Gigabyte Fusion 2 USB Device layouts and |
| and mapping to the device IDs stored on chip |
| |
| megadjc 31 Jul 2025 |
| chrism 29 Aug 2025 |
| megadjc 03 Sep 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
@@ -54,6 +54,8 @@ enum GB_FUSION2_LED_IDX
HDR_D_LED4 = 8,
HDR_D_LED3_ARGB = 0x62,
HDR_D_LED4_ARGB = 0x63,
ONBOARD1_ARGB = 0x64,
ONBOARD2_ARGB = 0x65,
};
/*-------------------------------------------------*\
@@ -4,7 +4,7 @@
| Driver for Gigabyte Aorus RGB Fusion 2 USB motherboard |
| |
| jackun 08 Jan 2020 |
| megadjc 31 Jul 2025 |
| megadjc 03 Sep 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -55,6 +55,27 @@ static LEDCount LedCountToEnum(unsigned int c)
}
}
static LEDCount LedCountFromEnum(uint8_t count){
switch(count & 0x0F)
{
case LEDS_32:
return LEDS_32;
case LEDS_64:
return LEDS_64;
case LEDS_256:
return LEDS_256;
case LEDS_512:
return LEDS_512;
case LEDS_1024:
default:
return LEDS_1024;
}
}
RGBFusion2USBController::RGBFusion2USBController(hid_device* handle, const char* path, std::string mb_name, uint16_t pid): dev(handle), product_id(pid)
{
name = mb_name;
@@ -96,9 +117,12 @@ bool RGBFusion2USBController::RefreshHardwareInfo()
}
std::memcpy(&report, buffer, sizeof(IT8297Report));
report_loaded = true;
device_num = report.device_num;
description = std::string(report.str_product, 28);
report_loaded = true;
device_num = report.device_num;
fw_id = report.fw_ver >> 24;
description = std::string(report.str_product, 28);
if(std::string::iterator nul = std::find(description.begin(), description.end(), '\0');
nul != description.end())
{
@@ -122,10 +146,12 @@ bool RGBFusion2USBController::RefreshHardwareInfo()
chip_id = text;
}
D_LED1_count = LedCountToEnum(report.curr_led_count_low & 0x0F);
D_LED2_count = LedCountToEnum((report.curr_led_count_low >> 4) & 0x0F);
D_LED3_count = LedCountToEnum(report.curr_led_count_high & 0x0F);
D_LED4_count = LedCountToEnum((report.curr_led_count_high >> 4) & 0x0F);
ARGB_count[0] = LedCountFromEnum(report.argb01_count & 0x0F);
ARGB_count[1] = LedCountFromEnum((report.argb01_count >> 4) & 0x0F);
ARGB_count[2] = LedCountFromEnum(report.argb23_count & 0x0F);
ARGB_count[3] = LedCountFromEnum((report.argb23_count >> 4) & 0x0F);
ARGB_count[4] = LedCountFromEnum(report.argb45_count & 0x0F);
ARGB_count[5] = LedCountFromEnum((report.argb45_count >> 4) & 0x0F);
cal_data.dled[0] = report.cal_strip0;
cal_data.dled[1] = report.cal_strip1;
@@ -148,26 +174,26 @@ bool RGBFusion2USBController::RefreshHardwareInfo()
std::memcpy(&cali, buffer2, sizeof(IT5711Calibration));
cali_loaded = true;
cal_data.dled[2] = cali.cal_strip2;
cal_data.dled[3] = cali.cal_strip3;
cal_data.spare[2] = cali.cal_spare2;
cal_data.spare[3] = cali.cal_spare3;
cal_data.dled[2] = cali.cal_strip2;
cal_data.dled[3] = cali.cal_strip3;
cal_data.dled[4] = cali.cal_strip4;
cal_data.dled[5] = cali.cal_strip5;
}
else
{
cal_data.dled[2] = 0;
cal_data.dled[3] = 0;
cal_data.spare[2] = 0;
cal_data.spare[3] = 0;
cali_loaded = false;
cal_data.dled[2] = 0;
cal_data.dled[3] = 0;
cal_data.dled[4] = 0;
cal_data.dled[5] = 0;
cali_loaded = false;
}
}
else
{
cal_data.dled[2] = 0;
cal_data.dled[3] = 0;
cal_data.spare[2] = 0;
cal_data.spare[3] = 0;
cal_data.dled[2] = 0;
cal_data.dled[3] = 0;
cal_data.dled[4] = 0;
cal_data.dled[5] = 0;
}
return report_loaded;
@@ -181,14 +207,16 @@ std::string RGBFusion2USBController::DecodeCalibrationBuffer(uint32_t value) con
return out;
}
uint8_t bo_b = value & 0xFF;
uint8_t bo_g = (value >> 8 ) & 0xFF;
uint8_t bo_r = (value >> 16) & 0xFF;
uint8_t bo_b = value & 0xFF;
uint8_t bo_g = (value >> 8 ) & 0xFF;
uint8_t bo_r = (value >> 16) & 0xFF;
uint8_t bo_reserved = (value >> 24) & 0xFF;
bool in_range = (bo_r < 3 && bo_g < 3 && bo_b < 3);
bool distinct = (bo_r != bo_g && bo_r != bo_b && bo_g != bo_b);
bool reserved_clear = (bo_reserved == 0);
bool in_range = (bo_r < 3 && bo_g < 3 && bo_b < 3);
bool distinct = (bo_r != bo_g && bo_r != bo_b && bo_g != bo_b);
if(in_range && distinct)
if(reserved_clear && in_range && distinct)
{
out[bo_r] = 'R';
out[bo_g] = 'G';
@@ -196,7 +224,7 @@ std::string RGBFusion2USBController::DecodeCalibrationBuffer(uint32_t value) con
return out;
}
return "BAD";
return "INVALID";
}
uint32_t RGBFusion2USBController::EncodeCalibrationBuffer(const std::string& rgb_order)
@@ -248,17 +276,31 @@ EncodedCalibration RGBFusion2USBController::GetCalibration(bool refresh_from_hw)
if(product_id == 0x5711)
{
out.dled[2] = DecodeCalibrationBuffer(cal_data.dled[2]);
out.dled[3] = DecodeCalibrationBuffer(cal_data.dled[3]);
out.spare[2] = DecodeCalibrationBuffer(cal_data.spare[2]);
out.spare[3] = DecodeCalibrationBuffer(cal_data.spare[3]);
if(cali_loaded)
{
out.dled[2] = DecodeCalibrationBuffer(cal_data.dled[2]);
out.dled[3] = DecodeCalibrationBuffer(cal_data.dled[3]);
out.dled[4] = DecodeCalibrationBuffer(cal_data.dled[4]);
out.dled[5] = DecodeCalibrationBuffer(cal_data.dled[5]);
}
else
{
/*-------------------------------------------------*\
| CC61 was not available, so these values are |
| unknown rather than OFF. |
\*-------------------------------------------------*/
out.dled[2] = "INVALID";
out.dled[3] = "INVALID";
out.dled[4] = "INVALID";
out.dled[5] = "INVALID";
}
}
else
{
out.dled[2] = "OFF";
out.dled[3] = "OFF";
out.spare[2] = "OFF";
out.spare[3] = "OFF";
out.dled[2] = "OFF";
out.dled[3] = "OFF";
out.dled[4] = "OFF";
out.dled[5] = "OFF";
}
return out;
@@ -271,34 +313,72 @@ bool RGBFusion2USBController::SetCalibration(const EncodedCalibration& cal, bool
return false;
}
if(EncodeCalibrationBuffer(cal.dled[0]) == cal_data.dled[0]
&& EncodeCalibrationBuffer(cal.dled[1]) == cal_data.dled[1]
&& EncodeCalibrationBuffer(cal.mainboard) == cal_data.mainboard
&& EncodeCalibrationBuffer(cal.spare[0]) == cal_data.spare[0]
&& EncodeCalibrationBuffer(cal.spare[1]) == cal_data.spare[1]
&& (product_id != 0x5711
|| (EncodeCalibrationBuffer(cal.dled[2]) == cal_data.dled[2]
&& EncodeCalibrationBuffer(cal.dled[3]) == cal_data.dled[3]
&& EncodeCalibrationBuffer(cal.spare[2]) == cal_data.spare[2]
&& EncodeCalibrationBuffer(cal.spare[3]) == cal_data.spare[3])))
/*---------------------------------------------------------*\
| A calibration write contains the complete calibration |
| payload. Do not write from incomplete hardware state. |
\*---------------------------------------------------------*/
if(!report_loaded || (product_id == 0x5711 && !cali_loaded))
{
return true;
return false;
}
/*---------------------------------------------------------*\
| Preserve malformed/unavailable values rather than |
| converting them to zero. Unknown strings are treated the |
| same way so stale configuration cannot erase calibration. |
\*---------------------------------------------------------*/
auto encode_or_preserve = [&](const std::string& rgb_order, uint32_t current) -> uint32_t
{
std::string key = rgb_order;
std::transform(key.begin(), key.end(), key.begin(),
[](unsigned char c){ return char(std::toupper(c)); });
if(key == "INVALID" || key == "BAD" || key.empty())
{
return current;
}
if(key == "OFF" || key == "0")
{
return 0u;
}
if(GigabyteCalibrationsLookup.find(key) == GigabyteCalibrationsLookup.end())
{
return current;
}
return EncodeCalibrationBuffer(key);
};
CMD_0x33 desired;
desired.c.d_strip_c0 = EncodeCalibrationBuffer(cal.dled[0]);
desired.c.d_strip_c1 = EncodeCalibrationBuffer(cal.dled[1]);
desired.c.rgb_cali = EncodeCalibrationBuffer(cal.mainboard);
desired.c.c_spare0 = EncodeCalibrationBuffer(cal.spare[0]);
desired.c.c_spare1 = EncodeCalibrationBuffer(cal.spare[1]);
desired.c.d_strip_c0 = encode_or_preserve(cal.dled[0], cal_data.dled[0]);
desired.c.d_strip_c1 = encode_or_preserve(cal.dled[1], cal_data.dled[1]);
desired.c.rgb_cali = encode_or_preserve(cal.mainboard, cal_data.mainboard);
desired.c.c_spare0 = encode_or_preserve(cal.spare[0], cal_data.spare[0]);
desired.c.c_spare1 = encode_or_preserve(cal.spare[1], cal_data.spare[1]);
if(product_id == 0x5711)
{
desired.c.d_strip_c2 = EncodeCalibrationBuffer(cal.dled[2]);
desired.c.d_strip_c3 = EncodeCalibrationBuffer(cal.dled[3]);
desired.c.c_spare2 = EncodeCalibrationBuffer(cal.spare[2]);
desired.c.c_spare3 = EncodeCalibrationBuffer(cal.spare[3]);
desired.c.d_strip_c2 = encode_or_preserve(cal.dled[2], cal_data.dled[2]);
desired.c.d_strip_c3 = encode_or_preserve(cal.dled[3], cal_data.dled[3]);
desired.c.d_strip_c4 = encode_or_preserve(cal.dled[4], cal_data.dled[4]);
desired.c.d_strip_c5 = encode_or_preserve(cal.dled[5], cal_data.dled[5]);
}
if(desired.c.d_strip_c0 == cal_data.dled[0]
&& desired.c.d_strip_c1 == cal_data.dled[1]
&& desired.c.rgb_cali == cal_data.mainboard
&& desired.c.c_spare0 == cal_data.spare[0]
&& desired.c.c_spare1 == cal_data.spare[1]
&& (product_id != 0x5711
|| (desired.c.d_strip_c2 == cal_data.dled[2]
&& desired.c.d_strip_c3 == cal_data.dled[3]
&& desired.c.d_strip_c4 == cal_data.dled[4]
&& desired.c.d_strip_c5 == cal_data.dled[5])))
{
return true;
}
int rc = SendPacket(desired.buffer);
@@ -309,7 +389,7 @@ bool RGBFusion2USBController::SetCalibration(const EncodedCalibration& cal, bool
ResetController();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
SaveCalState();
SaveLightingStateToFlash();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
cal_data.dled[0] = desired.c.d_strip_c0;
@@ -320,40 +400,70 @@ bool RGBFusion2USBController::SetCalibration(const EncodedCalibration& cal, bool
if(product_id == 0x5711)
{
cal_data.dled[2] = desired.c.d_strip_c2;
cal_data.dled[3] = desired.c.d_strip_c3;
cal_data.spare[2] = desired.c.c_spare2;
cal_data.spare[3] = desired.c.c_spare3;
cal_data.dled[2] = desired.c.d_strip_c2;
cal_data.dled[3] = desired.c.d_strip_c3;
cal_data.dled[4] = desired.c.d_strip_c4;
cal_data.dled[5] = desired.c.d_strip_c5;
}
else
{
cal_data.dled[2] = 0u;
cal_data.dled[3] = 0u;
cal_data.spare[2] = 0u;
cal_data.spare[3] = 0u;
cal_data.dled[2] = 0u;
cal_data.dled[3] = 0u;
cal_data.dled[4] = 0u;
cal_data.dled[5] = 0u;
}
return true;
}
void RGBFusion2USBController::SetLedCount(unsigned int c0, unsigned int c1, unsigned int c2, unsigned int c3)
void RGBFusion2USBController::SetLedCount(
unsigned int c0,
unsigned int c1,
unsigned int c2,
unsigned int c3,
unsigned int c4,
unsigned int c5)
{
LEDCount new_d1 = LedCountToEnum(c0);
LEDCount new_d2 = LedCountToEnum(c1);
LEDCount new_d3 = LedCountToEnum(c2);
LEDCount new_d4 = LedCountToEnum(c3);
LEDCount new_count[6] =
{
LedCountToEnum(c0),
LedCountToEnum(c1),
LedCountToEnum(c2),
LedCountToEnum(c3),
LedCountToEnum(c4),
LedCountToEnum(c5)
};
if(new_d1 == D_LED1_count && new_d2 == D_LED2_count && new_d3 == D_LED3_count && new_d4 == D_LED4_count)
bool changed = false;
for(unsigned int i = 0; i < 6; i++)
{
if(new_count[i] != ARGB_count[i])
{
changed = true;
break;
}
}
if(!changed)
{
return;
}
D_LED1_count = new_d1;
D_LED2_count = new_d2;
D_LED3_count = new_d3;
D_LED4_count = new_d4;
for(unsigned int i = 0; i < 6; i++)
{
ARGB_count[i] = new_count[i];
}
SendCCReport(0x34, (new_d2 << 4) | new_d1, (new_d4 << 4) | new_d3);
unsigned char buffer[FUSION2_USB_BUFFER_SIZE] = {0};
buffer[0] = report_id;
buffer[1] = 0x34;
buffer[2] = (new_count[1] << 4) | new_count[0];
buffer[3] = (new_count[3] << 4) | new_count[2];
buffer[4] = (new_count[5] << 4) | new_count[4];
SendPacket(buffer);
}
/*---------------------------------------------------------*\
@@ -371,7 +481,7 @@ bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
bitmask = 0x01;
break;
case 0x5711:
bitmask = 0x01 | 0x02 | 0x08 | 0x10;
bitmask = 0x01 | 0x02 | 0x08 | 0x10 | 0x20 | 0x40;
break;
default:
bitmask = 0x01 | 0x02;
@@ -395,6 +505,14 @@ bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
case HDR_D_LED4_ARGB:
bitmask = 0x10;
break;
case LED10:
case ONBOARD1_ARGB:
bitmask = 0x20;
break;
case LED11:
case ONBOARD2_ARGB:
bitmask = 0x40;
break;
default:
bitmask = 0x01;
break;
@@ -416,17 +534,17 @@ bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable)
}
/*---------------------------------------------------------*\
| Persist LED config data |
| Enable LED Lighting Persistence |
\*---------------------------------------------------------*/
bool RGBFusion2USBController::SaveLEDState(bool e)
bool RGBFusion2USBController::SetPersistentLightingEnabled(bool e)
{
return SendCCReport(0x47, e ? 1 : 0);
}
/*---------------------------------------------------------*\
| Persist calibration |
| Save lighting state to flash |
\*---------------------------------------------------------*/
bool RGBFusion2USBController::SaveCalState()
bool RGBFusion2USBController::SaveLightingStateToFlash()
{
return SendCCReport(0x5E, 0);
}
@@ -440,7 +558,7 @@ bool RGBFusion2USBController::EnableBeat(bool e)
}
/*---------------------------------------------------------*\
| Set Lamp Array mode (MSDL) |
| Set Lamp Array mode |
\*---------------------------------------------------------*/
bool RGBFusion2USBController::EnableLampArray(bool enable)
{
@@ -461,6 +579,16 @@ std::string RGBFusion2USBController::GetDeviceDescription()
return(description);
}
uint8_t RGBFusion2USBController::GetFWID()
{
return(fw_id);
}
uint8_t RGBFusion2USBController::GetFWRevision()
{
return((report.fw_ver >> 16) & 0xFF);
}
std::string RGBFusion2USBController::GetFWVersion()
{
return(version);
@@ -512,6 +640,12 @@ void RGBFusion2USBController::SetStripColors(unsigned int hdr, RGBColor* colors,
case HDR_D_LED4_ARGB:
byteorder = cal_data.dled[3];
break;
case ONBOARD1_ARGB:
byteorder = cal_data.dled[4];
break;
case ONBOARD2_ARGB:
byteorder = cal_data.dled[5];
break;
default:
byteorder = cal_data.dled[0];
break;
@@ -618,7 +752,7 @@ void RGBFusion2USBController::SetLEDEffect(int led, int mode, unsigned int speed
pkt.e.effect_param0 = 7;
break;
case EFFECT_WAVE:
pkt.e.period0 = (((speed + 1)^2) + (speed + 1) + 10) * 5 / 2;
pkt.e.period0 = ((speed + 1) * (speed + 1) + (speed + 1) + 10) * 5 / 2;
pkt.e.effect_param0 = 7;
pkt.e.effect_param1 = 1;
break;
@@ -719,7 +853,8 @@ void RGBFusion2USBController::ResetController()
| Check controller for gen2 ARGB support |
| Checks for supported device number |
| Then checks for supported controllers |
| Then checks for supported feature bit (SaveLEDState) |
| Then checks for supported feature bit |
| (SetPersistentLighting) |
| Finally checks for strip detection value. |
\*---------------------------------------------------------*/
bool RGBFusion2USBController::SupportsGen2() const
@@ -829,10 +964,10 @@ bool RGBFusion2USBController::ScanGen2Strips(uint8_t enabled_headers)
dst.totalLeds = total_leds;
SetLedCount(0, 0, 0, 0);
SetLedCount(0, 0, 0, 0, 0, 0);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
SaveLEDState(false);
SetPersistentLightingEnabled(false);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
@@ -842,7 +977,7 @@ bool RGBFusion2USBController::ScanGen2Strips(uint8_t enabled_headers)
/*---------------------------------------------------------*\
| Check controller for persistent state support |
\*---------------------------------------------------------*/
bool RGBFusion2USBController::SupportsSaveLEDState() const
bool RGBFusion2USBController::SupportsSetPersistentLighting() const
{
return(report_loaded && (report.support_cmd_flag & 0x01));
}
@@ -4,7 +4,7 @@
| Driver for Gigabyte Aorus RGB Fusion 2 USB motherboard |
| |
| jackun 08 Jan 2020 |
| megadjc 31 Jul 2025 |
| megadjc 03 Sep 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -20,6 +20,14 @@
#include "GigabyteFusion2USB_Devices.h"
#define FUSION2_USB_BUFFER_SIZE 64
#define RGBFUSION2_DLED_LEDS_MIN 0
#define RGBFUSION2_DLED_LEDS_MAX 1024
/*--------------------------------------------------------*\
| IT57xx only supports 256 LED strings |
\*--------------------------------------------------------*/
#define RGBFUSION2_57XX_LEDS_MIN 0
#define RGBFUSION2_57XX_LEDS_MAX 256
/*--------------------------------------------------------*\
| Gen2 scan/info opcode base |
@@ -73,8 +81,8 @@ struct LEDs
\*---------------------------------------------------------*/
struct CalibrationData
{
uint32_t dled[4] = {0, 0, 0, 0};
uint32_t spare[4] = {0, 0, 0, 0};
uint32_t dled[6] = {0, 0, 0, 0, 0, 0};
uint32_t spare[2] = {0, 0};
uint32_t mainboard = 0;
};
@@ -83,8 +91,8 @@ struct CalibrationData
\*---------------------------------------------------------*/
struct EncodedCalibration
{
std::string dled[4];
std::string spare[4];
std::string dled[6];
std::string spare[2];
std::string mainboard;
};
@@ -176,6 +184,12 @@ union PktRGB
case HDR_D_LED4:
header = HDR_D_LED4_ARGB;
break;
case LED10:
header = ONBOARD1_ARGB;
break;
case LED11:
header = ONBOARD2_ARGB;
break;
default:
header = HDR_D_LED1_ARGB;
break;
@@ -271,9 +285,9 @@ struct IT8297Report
uint8_t device_num;
uint8_t strip_detect;
uint32_t fw_ver;
uint8_t curr_led_count_high;
uint8_t curr_led_count_low;
uint8_t strip_ctrl_length1;
uint8_t argb01_count;
uint8_t argb23_count;
uint8_t argb45_count;
uint8_t support_cmd_flag;
char str_product[28];
uint32_t cal_spare0;
@@ -293,8 +307,8 @@ struct IT5711Calibration
uint8_t reserved[3];
uint32_t cal_strip2;
uint32_t cal_strip3;
uint32_t cal_spare2;
uint32_t cal_spare3;
uint32_t cal_strip4;
uint32_t cal_strip5;
uint8_t padding[44];
};
@@ -315,8 +329,8 @@ union CMD_0x33
uint32_t c_spare1 = 0;
uint32_t d_strip_c2 = 0;
uint32_t d_strip_c3 = 0;
uint32_t c_spare2 = 0;
uint32_t c_spare3 = 0;
uint32_t d_strip_c4 = 0;
uint32_t d_strip_c5 = 0;
uint8_t reserved[25];
} c;
@@ -336,14 +350,15 @@ public:
bool ApplyEffect(bool batch_commit = false);
bool SetCalibration(const EncodedCalibration& cal, bool refresh_from_hw);
void SetLedCount(unsigned int c0, unsigned int c1, unsigned int c2, unsigned int c3);
void SetLedCount(unsigned int c0, unsigned int c1, unsigned int c2, unsigned int c3, unsigned int c4, unsigned int c5);
void SetLEDEffect(int led, int mode, unsigned int speed, unsigned char brightness, bool random, uint32_t* color);
bool SetStripBuiltinEffectState(int hdr, bool enable);
void SetStripColors(unsigned int hdr, RGBColor * colors, unsigned int num_colors, int single_led = -1);
bool SupportsGen2() const;
bool ScanGen2Strips(uint8_t hdr_mask);
bool SaveLEDState(bool enable);
bool SupportsSaveLEDState() const;
bool SupportsSetPersistentLighting() const;
bool SetPersistentLightingEnabled(bool enable);
bool SaveLightingStateToFlash();
EncodedCalibration GetCalibration(bool refresh_from_hw = false);
std::string GetDeviceName();
@@ -351,6 +366,8 @@ public:
std::string GetDeviceDescription();
std::string GetDeviceLocation();
std::string GetFWVersion();
uint8_t GetFWID();
uint8_t GetFWRevision();
uint16_t GetProductID();
std::string GetSerial();
std::vector<Gen2StripInfo> ExportGen2Strips() const;
@@ -363,13 +380,13 @@ private:
uint32_t EncodeCalibrationBuffer(const std::string& rgb_order);
bool RefreshHardwareInfo();
void ResetController();
bool SaveCalState();
bool SendCCReport(uint8_t a, uint8_t b, uint8_t c = 0);
bool SendReport(uint8_t id, uint8_t a, uint8_t b, uint8_t c = 0);
int SendPacket(unsigned char* packet);
hid_device* dev;
uint8_t device_num;
uint8_t fw_id = 0;
uint16_t product_id;
uint32_t effect_zone_mask = 0;
int mode;
@@ -384,8 +401,5 @@ private:
int report_id = 0xCC;
bool report_loaded = false;
bool cali_loaded = false;
LEDCount D_LED1_count;
LEDCount D_LED2_count;
LEDCount D_LED3_count;
LEDCount D_LED4_count;
LEDCount ARGB_count[6];
};
@@ -5,7 +5,7 @@
| motherboard |
| |
| jackun 08 Jan 2020 |
| megadjc 31 Jul 2025 |
| megadjc 03 Sep 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
File diff suppressed because it is too large Load Diff
@@ -5,7 +5,7 @@
| motherboard |
| |
| jackun 08 Jan 2020 |
| megadjc 31 Jul 2025 |
| megadjc 03 Sep 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -13,35 +13,16 @@
#pragma once
#include <map>
#include "RGBController.h"
#include "GigabyteFusion2USB_Devices.h"
#include "GigabyteRGBFusion2USBController.h"
#include "SettingsManager.h"
#define RGBFUSION2_DIGITAL_LEDS_MIN 0
#define RGBFUSION2_DIGITAL_LEDS_MAX 1024
#define RGBFUSION2_BRIGHTNESS_MIN 0
#define RGBFUSION2_BRIGHTNESS_MAX 255
#define RGBFUSION2_SPEED_MIN 9
#define RGBFUSION2_SPEED_MID 4
#define RGBFUSION2_SPEED_MAX 0
#define GET_JSON_VAL_ELSE_OFF(obj, key) obj.contains(key) ? obj.at(key).get<std::string>() : std::string("OFF")
template<typename K, typename V>
static std::map<V, K> reverse_map(const std::map<K, V>& map)
{
std::map<V, K> reversed_map;
for(const std::pair<K, V> entry : map)
{
reversed_map[entry.second] = entry.first;
}
return reversed_map;
}
class RGBController_RGBFusion2USB: public RGBController
{
public:
@@ -59,6 +40,8 @@ public:
void DeviceUpdateMode();
void DeviceUpdateZoneMode(int zone);
void DeviceSaveMode() override;
void DeviceConfigureDevice() override;
void DeviceUpdateDeviceSpecificConfiguration() override;
private:
std::string detector_name;
@@ -67,6 +50,9 @@ private:
uint8_t device_num;
RGBColor null_color = 0;
bool supports_gen2 = 0;
uint8_t gen2_enabled_headers = 0;
bool entire_device_effect_active = false;
bool persist_lighting_on_exit = false;
/*---------------------------------------------------------*\
| The intial value of device_index should point to the |
| layout for the generic_device |
@@ -75,6 +61,8 @@ private:
uint16_t product_id = 0;
uint32_t effects_mask = 0;
void Init_Controller();
void InitDeviceSpecificConfiguration();
void ApplyDeviceSpecificConfiguration(bool setup_zones);
int GetLED_Zone(int led_idx);
/*---------------------------------------------------------*\
@@ -84,16 +72,4 @@ private:
gb_fusion2_layout instance_zones{};
std::vector<gb_fusion2_zone*> allocated_zones;
nlohmann::json WriteCalJsonFrom(
const EncodedCalibration& src);
void FillMissingWith(
nlohmann::json& dst,
const EncodedCalibration& fb);
nlohmann::json BuildCustomLayoutJson(
const gb_fusion2_device* layout,
const RvrseLedHeaders& reverseLookup);
void LoadCustomLayoutFromJson(
const nlohmann::json& json_custom,
const FwdLedHeaders& forwardLookup,
gb_fusion2_device* layout);
};
@@ -16,22 +16,45 @@
using namespace std::chrono_literals;
struct GoveeHardwareInfo
/*---------------------------------------------------------*\
| A device's zone shape is picked from this fixed set of |
| known layouts rather than special-cased by SKU string, so |
| adding a device that fits an existing shape is a one-line |
| table entry rather than a new code path. |
| |
| LINEAR single strip, no matrix |
| SERPENTINE matrix wired bottom-to-top, alternating |
| scan direction each row (e.g. H6022) |
| SPLIT_BARS two disconnected bars either side of a gap, |
| e.g. two light bars flanking a monitor |
\*---------------------------------------------------------*/
enum GoveeZoneLayout
{
unsigned int led_count;
unsigned int matrix_row_len; // 0 = linear
bool supports_razer;
GOVEE_ZONE_LINEAR,
GOVEE_ZONE_SERPENTINE,
GOVEE_ZONE_SPLIT_BARS,
};
struct GoveeDeviceInfo
{
unsigned int led_count;
GoveeZoneLayout layout;
unsigned int matrix_row_len; // SERPENTINE only: LEDs per row
unsigned int gap_columns; // SPLIT_BARS only: empty columns between the two bars
bool supports_razer;
};
const unsigned int GOVEE_FALLBACK_LED_COUNT = 1;
#define GOVEE_MATRIX_LED_NONE 0xFFFFFFFF
static std::map<std::string, GoveeHardwareInfo> govee_hardware_info
static std::map<std::string, GoveeDeviceInfo> govee_device_info
{
{ "H6022", { 132, 12, true } }, // Govee Smart Table Lamp 2
{ "H612F", { 12, 0, true } }, // Govee Strip Light S (3m)
{ "H619A", { 20, 0, true } }, // Govee RGBIC Led Strip Lights
{ "H70B1", { 20, 0, true } }, // Govee LED Curtain Lights
{ "H607C", { 174, 0, true } }, // Govee Floor Lamp 2
{ "H6022", { 132, GOVEE_ZONE_SERPENTINE, 12, 0, true } }, // Govee Smart Table Lamp 2
{ "H6046", { 20, GOVEE_ZONE_SPLIT_BARS, 0, 10, true } }, // Govee RGBIC Gaming Light Bars - two 10-LED bars, right then left
{ "H612F", { 12, GOVEE_ZONE_LINEAR, 0, 0, true } }, // Govee Strip Light S (3m)
{ "H619A", { 20, GOVEE_ZONE_LINEAR, 0, 0, true } }, // Govee RGBIC Led Strip Lights
{ "H70B1", { 20, GOVEE_ZONE_LINEAR, 0, 0, true } }, // Govee LED Curtain Lights
{ "H607C", { 174, GOVEE_ZONE_LINEAR, 0, 0, true } }, // Govee Floor Lamp 2
};
enum
@@ -98,10 +121,10 @@ RGBController_Govee::~RGBController_Govee()
void RGBController_Govee::SetupZones()
{
GoveeHardwareInfo hw = { GOVEE_FALLBACK_LED_COUNT, 0, false };
GoveeDeviceInfo hw = { GOVEE_FALLBACK_LED_COUNT, GOVEE_ZONE_LINEAR, 0, 0, false };
std::map<std::string, GoveeHardwareInfo>::iterator it = govee_hardware_info.find(controller->GetSku());
if(it != govee_hardware_info.end())
std::map<std::string, GoveeDeviceInfo>::iterator it = govee_device_info.find(controller->GetSku());
if(it != govee_device_info.end())
{
hw = it->second;
razer_supported = hw.supports_razer;
@@ -112,45 +135,90 @@ void RGBController_Govee::SetupZones()
strip.leds_min = hw.led_count;
strip.leds_max = hw.led_count;
if(hw.matrix_row_len == 0)
switch(hw.layout)
{
strip.name = "Govee Strip";
strip.type = ZONE_TYPE_LINEAR;
}
else
{
strip.name = "Govee Matrix";
strip.type = ZONE_TYPE_MATRIX;
unsigned int width = hw.matrix_row_len;
unsigned int height = hw.led_count / width;
strip.matrix_map.height = height;
strip.matrix_map.width = width;
strip.matrix_map.map.resize(hw.led_count);
/*-------------------------------------------------*\
| On H6022, LEDs indexed bottom to top, alternating |
| clockwise and counterclockwise for each row. |
\*-------------------------------------------------*/
for(unsigned int y = 0; y < height; y++)
case GOVEE_ZONE_LINEAR:
{
/*---------------------------------------------*\
| LEDs numbered bottom to top, opposite of |
| matrix clockwise and counterclockwise for |
| each row. |
\*---------------------------------------------*/
unsigned int led_y = (height - 1) - y;
strip.name = "Govee Strip";
strip.type = ZONE_TYPE_LINEAR;
break;
}
for(unsigned int x = 0; x < width; x++)
case GOVEE_ZONE_SPLIT_BARS:
{
strip.name = "Light Bars";
strip.type = ZONE_TYPE_MATRIX;
unsigned int bar_leds = hw.led_count / 2;
unsigned int width = hw.gap_columns + 2;
unsigned int height = bar_leds;
strip.matrix_map.Set(height, width, NULL);
/*-------------------------------------------------*\
| The two bars stand either side of a monitor, so |
| the left bar takes the first column and the right |
| bar the last one. The columns between them are |
| empty and represent the gap across the desk, |
| which keeps horizontal effects moving at the same |
| rate as they appear to the eye. |
\*-------------------------------------------------*/
for(unsigned int y = 0; y < height; y++)
{
/*-----------------------------------------*\
| LED is right-to-left for even rows, |
| including first one |
\*-----------------------------------------*/
unsigned int led_x = led_y & 1 ? x : (width - 1) - x;
strip.matrix_map.map[y * width + x] = led_y * width + led_x;
for(unsigned int x = 0; x < width; x++)
{
strip.matrix_map.map[(y * width) + x] = GOVEE_MATRIX_LED_NONE;
}
strip.matrix_map.map[(y * width)] = bar_leds + y;
strip.matrix_map.map[(y * width) + (width - 1)] = y;
}
break;
}
case GOVEE_ZONE_SERPENTINE:
default:
{
strip.name = "Govee Matrix";
strip.type = ZONE_TYPE_MATRIX;
/*-------------------------------------------------*\
| matrix_row_len is only meaningful for this layout |
| - guard a table entry that forgets to set it so a |
| bad row degrades to a single column instead of |
| dividing by zero. |
\*-------------------------------------------------*/
unsigned int width = (hw.matrix_row_len > 0) ? hw.matrix_row_len : 1;
unsigned int height = hw.led_count / width;
strip.matrix_map.height = height;
strip.matrix_map.width = width;
strip.matrix_map.map.resize(hw.led_count);
/*-------------------------------------------------*\
| LEDs indexed bottom to top, alternating clockwise |
| and counterclockwise for each row (e.g. H6022). |
\*-------------------------------------------------*/
for(unsigned int y = 0; y < height; y++)
{
/*---------------------------------------------*\
| LEDs numbered bottom to top, opposite of |
| matrix clockwise and counterclockwise for |
| each row. |
\*---------------------------------------------*/
unsigned int led_y = (height - 1) - y;
for(unsigned int x = 0; x < width; x++)
{
/*-----------------------------------------*\
| LED is right-to-left for even rows, |
| including first one |
\*-----------------------------------------*/
unsigned int led_x = led_y & 1 ? x : (width - 1) - x;
strip.matrix_map.map[y * width + x] = led_y * width + led_x;
}
}
break;
}
}
zones.push_back(strip);
@@ -158,7 +226,25 @@ void RGBController_Govee::SetupZones()
for(std::size_t led_idx = 0; led_idx < strip.leds_count; led_idx++)
{
led strip_led;
strip_led.name = "Govee LED " + std::to_string(led_idx);
if(hw.layout == GOVEE_ZONE_SPLIT_BARS)
{
unsigned int bar_leds = hw.led_count / 2;
if(led_idx < bar_leds)
{
strip_led.name = "Right Bar LED " + std::to_string(led_idx + 1);
}
else
{
strip_led.name = "Left Bar LED " + std::to_string(led_idx - (bar_leds - 1));
}
}
else
{
strip_led.name = "Govee LED " + std::to_string(led_idx);
}
leds.push_back(strip_led);
}
@@ -288,6 +374,23 @@ void RGBController_Govee::KeepaliveThread()
{
UpdateStatic(true);
}
else if(modes[active_mode].value == GOVEE_MODE_DIRECT)
{
/*-----------------------------------------------------*\
| Direct/per-LED mode has no other periodic refresh - |
| SendRazerEnable() only fires once, at mode entry. |
| Re-assert it here so a long gap between real updates |
| (e.g. idle time between plugin-driven alerts) can't |
| let the device's external-control session time out |
| and fall back to its own firmware default. |
\*-----------------------------------------------------*/
if(razer_supported)
{
controller->SendRazerEnable();
}
DeviceUpdateLEDs();
}
}
std::this_thread::sleep_for(10s);
@@ -31,7 +31,7 @@ HIDLampArrayController::HIDLampArrayController(hid_device *dev_handle, const cha
unsigned int pos = 0;
unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
unsigned char report_id = 0;
unsigned int size = hid_get_report_descriptor(dev, report_descriptor, sizeof(report_descriptor));
int size = hid_get_report_descriptor(dev, report_descriptor, sizeof(report_descriptor));
unsigned int usage = 0;
unsigned char usage_page = 0;
@@ -40,7 +40,18 @@ HIDLampArrayController::HIDLampArrayController(hid_device *dev_handle, const cha
\*-----------------------------------------------------*/
std::unordered_map<unsigned int, unsigned int> usage_to_report_id;
while(pos < size)
/*-----------------------------------------------------*\
| A failed descriptor read returns -1; treated as a |
| length it walks off the end of the buffer. |
\*-----------------------------------------------------*/
if(size < 0)
{
LampArray.LampCount = 0;
LampArray.LampArrayKind = HID_LAMPARRAY_KIND_UNDEFINED;
return;
}
while(pos < (unsigned int)size)
{
get_hid_item_size(report_descriptor, size, pos, &data_len, &key_size);
@@ -83,6 +83,8 @@ RGBController_HIDLampArray::RGBController_HIDLampArray(HIDLampArrayController* c
RGBController_HIDLampArray::~RGBController_HIDLampArray()
{
Shutdown();
delete controller;
}
@@ -194,7 +196,7 @@ static const char *HIDUsageIDsToKeyNames[HID_KEYBOARD_USAGE_IDS_COUNT] =
KEY_EN_NUMPAD_0, // Keypad 0 and Insert
KEY_EN_NUMPAD_PERIOD, // Keypad . and Delete
KEY_EN_BACK_SLASH, // Keyboard Non-US \ and |
KEY_EN_UNUSED, // Keyboard Application
KEY_EN_MENU, // Keyboard Application
KEY_EN_POWER, // Keyboard Power
KEY_EN_NUMPAD_EQUAL, // Keypad =
KEY_EN_F13, // Keyboard F13
@@ -258,6 +260,16 @@ static const char *HIDUsageIDsToKeyNames[HID_KEYBOARD_USAGE_IDS_COUNT] =
KEY_EN_UNUSED, // Keyboard Clear/Again
KEY_EN_UNUSED, // Keyboard CrSel/Props
KEY_EN_UNUSED, // Keyboard ExSel
KEY_EN_UNUSED, // A5 Reserved
KEY_EN_UNUSED, // A6 Reserved
KEY_EN_UNUSED, // A7 Reserved
KEY_EN_UNUSED, // A8 Reserved
KEY_EN_UNUSED, // A9 Reserved
KEY_EN_UNUSED, // AA Reserved
KEY_EN_UNUSED, // AB Reserved
KEY_EN_UNUSED, // AC Reserved
KEY_EN_UNUSED, // AD Reserved
KEY_EN_UNUSED, // AE Reserved
KEY_EN_UNUSED, // AF Reserved
KEY_EN_UNUSED, // Keypad 00
KEY_EN_UNUSED, // Keypad 000
@@ -305,6 +317,7 @@ static const char *HIDUsageIDsToKeyNames[HID_KEYBOARD_USAGE_IDS_COUNT] =
KEY_EN_UNUSED, // Keypad Octal
KEY_EN_UNUSED, // Keypad Decimal
KEY_EN_UNUSED, // Keypad Hexadecimal
KEY_EN_UNUSED, // DE Reserved
KEY_EN_UNUSED, // DF Reserved
KEY_EN_LEFT_CONTROL, // Keyboard LeftControl
KEY_EN_LEFT_SHIFT, // Keyboard LeftShift
@@ -334,8 +347,8 @@ void RGBController_HIDLampArray::SetupZones()
columns.insert(controller->GetLamps()[lamp_idx].PositionXInMicrometers);
}
new_zone.matrix_map.height = rows.size();
new_zone.matrix_map.width = columns.size();
new_zone.matrix_map.height = (unsigned int)rows.size();
new_zone.matrix_map.width = (unsigned int)columns.size();
new_zone.matrix_map.map.resize(rows.size() * columns.size());
memset(new_zone.matrix_map.map.data(), 0xFF, (new_zone.matrix_map.map.size() * sizeof(unsigned int)));
@@ -346,7 +359,7 @@ void RGBController_HIDLampArray::SetupZones()
size_t idx = std::distance(columns.begin(), columns.find(controller->GetLamps()[lamp_idx].PositionXInMicrometers));
size_t idy = std::distance(rows.begin(), rows.find(controller->GetLamps()[lamp_idx].PositionYInMicrometers));
new_zone.matrix_map.map[idx + idy * new_zone.matrix_map.width] = lamp_idx;
new_zone.matrix_map.map[idx + idy * new_zone.matrix_map.width] = (unsigned int)lamp_idx;
}
zones.push_back(new_zone);
@@ -355,9 +368,11 @@ void RGBController_HIDLampArray::SetupZones()
{
led new_led;
if(controller->GetLamps()[lamp_idx].LampKey < HID_KEYBOARD_USAGE_IDS_COUNT)
unsigned char lamp_key = controller->GetLamps()[lamp_idx].LampKey;
if(lamp_key < HID_KEYBOARD_USAGE_IDS_COUNT && HIDUsageIDsToKeyNames[lamp_key] != nullptr)
{
new_led.name = HIDUsageIDsToKeyNames[controller->GetLamps()[lamp_idx].LampKey];
new_led.name = HIDUsageIDsToKeyNames[lamp_key];
}
else
{
@@ -371,7 +386,7 @@ void RGBController_HIDLampArray::SetupZones()
void RGBController_HIDLampArray::DeviceUpdateLEDs()
{
unsigned int leds_to_go = leds.size();
unsigned int leds_to_go = (unsigned int)leds.size();
while(leds_to_go > 0)
{
@@ -387,7 +402,7 @@ void RGBController_HIDLampArray::DeviceUpdateLEDs()
for(unsigned int led_frame_idx = 0; led_frame_idx < leds_this_frame; led_frame_idx++)
{
unsigned short led_idx = (leds.size() - leds_to_go) + led_frame_idx;
unsigned short led_idx = (unsigned short)((leds.size() - leds_to_go) + led_frame_idx);
LampIds[led_frame_idx] = led_idx;
UpdateColors[led_frame_idx].RedChannel = RGBGetRValue(colors[led_idx]);
UpdateColors[led_frame_idx].GreenChannel = RGBGetGValue(colors[led_idx]);
@@ -85,7 +85,7 @@ void RGBController_HyperXMicrophoneV2::SetupZones()
Mic.leds_min = HYPERX_QUADCAST_2S_TOTAL_LEDS;
Mic.leds_max = HYPERX_QUADCAST_2S_TOTAL_LEDS;
Mic.leds_count = HYPERX_QUADCAST_2S_TOTAL_LEDS;
Mic.matrix_map.Set(HYPERX_QUADCAST_2S_MATRIX_WIDTH, HYPERX_QUADCAST_2S_MATRIX_HEIGHT, led_mapping);
Mic.matrix_map.Set(HYPERX_QUADCAST_2S_MATRIX_HEIGHT, HYPERX_QUADCAST_2S_MATRIX_WIDTH, led_mapping);
for(unsigned int i = 0; i < HYPERX_QUADCAST_2S_TOTAL_LEDS; i ++)
{
@@ -20,9 +20,6 @@
#include "LogitechG213Controller.h"
#include "LogitechG600Controller.h"
#include "LogitechG933Controller.h"
#include "LogitechG810Controller.h"
#include "LogitechGProKeyboardController.h"
#include "LogitechG910Controller.h"
#include "LogitechG815Controller.h"
#include "LogitechG915Controller.h"
#include "LogitechGLightsyncController.h"
@@ -32,9 +29,6 @@
#include "RGBController_LogitechG213.h"
#include "RGBController_LogitechG600.h"
#include "RGBController_LogitechG933.h"
#include "RGBController_LogitechG810.h"
#include "RGBController_LogitechGProKeyboard.h"
#include "RGBController_LogitechG910.h"
#include "RGBController_LogitechG815.h"
#include "RGBController_LogitechG915.h"
#include "RGBController_LogitechGLightsync.h"
@@ -61,12 +55,6 @@ using namespace std::chrono_literals;
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define LOGITECH_G213_PID 0xC336
#define LOGITECH_G512_PID 0xC342
#define LOGITECH_G512_RGB_PID 0xC33C
#define LOGITECH_G610_1_PID 0xC333
#define LOGITECH_G610_2_PID 0xC338
#define LOGITECH_G810_1_PID 0xC331
#define LOGITECH_G810_2_PID 0xC337
#define LOGITECH_G813_PID 0xC232
#define LOGITECH_G815_PID 0xC33F
#define LOGITECH_G915_WIRED_PID 0xC33E
@@ -74,9 +62,6 @@ using namespace std::chrono_literals;
#define LOGITECH_G915_RECEIVER_2_PID 0xC547
#define LOGITECH_G915TKL_WIRED_PID 0xC343
#define LOGITECH_G915TKL_RECEIVER_PID 0xC545
#define LOGITECH_G910_ORION_SPARK_PID 0xC32B
#define LOGITECH_G910_PID 0xC335
#define LOGITECH_GPRO_KEYBOARD_1_PID 0xC339
/*---------------------------------------------------------*\
| Mouse product IDs |
@@ -172,112 +157,6 @@ DetectedControllers DetectLogitechKeyboardG213(hid_device_info* info, const std:
return(detected_controllers);
}
DetectedControllers DetectLogitechKeyboardG810(hid_device_info* info, const std::string& name)
{
/*-----------------------------------------------------*\
| Logitech keyboards use two different usages, one for |
| 20-byte packets and one for 64-byte packets. Usage |
| 0x0602 for 20 byte, usage 0x0604 for 64 byte, both |
| are on usage page 0xFF43 |
\*-----------------------------------------------------*/
DetectedControllers detected_controllers;
hid_device* dev_usage_0x0602 = nullptr;
hid_device* dev_usage_0x0604 = nullptr;
hid_device_info* info_temp = info;
while(info_temp)
{
if(info_temp->vendor_id == info->vendor_id // constant LOGITECH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->interface_number == info->interface_number // constant 1
&& info_temp->usage_page == info->usage_page) // constant 0xFF43
{
if(info_temp->usage == 0x0602)
{
dev_usage_0x0602 = hid_open_path(info_temp->path);
}
else if(info_temp->usage == 0x0604)
{
dev_usage_0x0604 = hid_open_path(info_temp->path);
}
}
if(dev_usage_0x0602 && dev_usage_0x0604)
{
break;
}
info_temp = info_temp->next;
}
if(dev_usage_0x0602 && dev_usage_0x0604)
{
LogitechG810Controller* controller = new LogitechG810Controller(dev_usage_0x0602, dev_usage_0x0604, info->path, name);
RGBController_LogitechG810* rgb_controller = new RGBController_LogitechG810(controller);
detected_controllers.push_back(rgb_controller);
}
else
{
// Not all of them could be opened, do some cleanup
hid_close(dev_usage_0x0602);
hid_close(dev_usage_0x0604);
}
return(detected_controllers);
}
DetectedControllers DetectLogitechKeyboardG910(hid_device_info* info, const std::string& name)
{
/*-----------------------------------------------------*\
| Logitech keyboards use two different usages, one for |
| 20-byte packets and one for 64-byte packets. Usage |
| 0x0602 for 20 byte, usage 0x0604 for 64 byte, both |
| are on usage page 0xFF43 |
\*-----------------------------------------------------*/
DetectedControllers detected_controllers;
hid_device* dev_usage_0x0602 = nullptr;
hid_device* dev_usage_0x0604 = nullptr;
hid_device_info* info_temp = info;
while(info_temp)
{
if(info_temp->vendor_id == info->vendor_id // constant LOGITECH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->interface_number == info->interface_number // constant 1
&& info_temp->usage_page == info->usage_page) // constant 0xFF43
{
if(info_temp->usage == 0x0602)
{
dev_usage_0x0602 = hid_open_path(info_temp->path);
}
else if(info_temp->usage == 0x0604)
{
dev_usage_0x0604 = hid_open_path(info_temp->path);
}
}
if(dev_usage_0x0602 && dev_usage_0x0604)
{
break;
}
info_temp = info_temp->next;
}
if(dev_usage_0x0602 && dev_usage_0x0604)
{
LogitechG910Controller* controller = new LogitechG910Controller(dev_usage_0x0602, dev_usage_0x0604, info->path, name);
RGBController_LogitechG910* rgb_controller = new RGBController_LogitechG910(controller);
detected_controllers.push_back(rgb_controller);
}
else
{
// Not all of them could be opened, do some cleanup
hid_close(dev_usage_0x0602);
hid_close(dev_usage_0x0604);
}
return(detected_controllers);
}
DetectedControllers DetectLogitechKeyboardG815(hid_device_info* info, const std::string& name)
{
/*-----------------------------------------------------*\
@@ -431,8 +310,9 @@ DetectedControllers DetectLogitechKeyboardG915Receiver2(hid_device_info* info, c
{
/*-----------------------------------------*\
| G915 X family: the unified HID++ 2.0 |
| controller handles it. Skip so the C547 |
| detector claims it. |
| controller handles it. Skip so the |
| unified detector, registered after this |
| one, claims it. |
\*-----------------------------------------*/
LOG_DEBUG("[LogitechControllerDetect] 0xC547 G915 X -> unified controller, skipping legacy");
hid_close(dev);
@@ -493,59 +373,6 @@ DetectedControllers DetectLogitechKeyboardG915Wired(hid_device_info* info, const
return(detected_controllers);
}
DetectedControllers DetectLogitechKeyboardGPro(hid_device_info* info, const std::string& name)
{
/*-----------------------------------------------------*\
| Logitech keyboards use two different usages, one for |
| 20-byte packets and one for 64-byte packets. Usage |
| 0x0602 for 20 byte, usage 0x0604 for 64 byte, both |
| are on usage page 0xFF43 |
\*-----------------------------------------------------*/
DetectedControllers detected_controllers;
hid_device* dev_usage_0x0602 = nullptr;
hid_device* dev_usage_0x0604 = nullptr;
hid_device_info* info_temp = info;
while(info_temp)
{
if(info_temp->vendor_id == info->vendor_id // constant LOGITECH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->interface_number == info->interface_number // constant 1
&& info_temp->usage_page == info->usage_page) // constant 0xFF43
{
if(info_temp->usage == 0x0602)
{
dev_usage_0x0602 = hid_open_path(info_temp->path);
}
else if(info_temp->usage == 0x0604)
{
dev_usage_0x0604 = hid_open_path(info_temp->path);
}
}
if(dev_usage_0x0602 && dev_usage_0x0604)
{
break;
}
info_temp = info_temp->next;
}
if(dev_usage_0x0602 && dev_usage_0x0604)
{
LogitechGProKeyboardController* controller = new LogitechGProKeyboardController(dev_usage_0x0602, dev_usage_0x0604, name);
RGBController_LogitechGProKeyboard* rgb_controller = new RGBController_LogitechGProKeyboard(controller);
detected_controllers.push_back(rgb_controller);
}
else
{
// Not all of them could be opened, do some cleanup
hid_close(dev_usage_0x0602);
hid_close(dev_usage_0x0604);
}
return(detected_controllers);
}
/*---------------------------------------------------------*\
| Logitech Mice |
\*---------------------------------------------------------*/
@@ -998,6 +825,16 @@ static bool HIDPP20ClaimDevice(const std::string& device_id)
return hidpp20_claimed_devices.insert(device_id).second;
}
/*---------------------------------------------------------*\
| Free the device claim when the device is unplugged |
\*---------------------------------------------------------*/
static bool HIDPP20UnclaimDevice(const std::string& device_id)
{
std::lock_guard<std::mutex> lock(hidpp20_registry_mutex);
return hidpp20_claimed_devices.erase(device_id);
}
/*---------------------------------------------------------*\
| Watchers own threads and a node handle, so they have to |
| be stopped before the process exits. |
@@ -1380,7 +1217,7 @@ static bool HIDPP20LookupTarget(const std::string& node_path, uint8_t index, HID
| lighting; both leave the target on file, so a device |
| that was asleep is built when its dongle reports it. |
\*---------------------------------------------------------*/
static RGBController_LogitechHIDPP20* HIDPP20BuildController(const HIDPP20BuildTarget& target)
static RGBController_LogitechHIDPP20* HIDPP20BuildController(const HIDPP20BuildTarget& target, const std::string& device_id="")
{
HIDPP20BuildClaim claim(target.node_path, target.index);
@@ -1466,7 +1303,7 @@ static RGBController_LogitechHIDPP20* HIDPP20BuildController(const HIDPP20BuildT
{
controller->Initialize();
RGBController_LogitechHIDPP20* rgb_controller = new RGBController_LogitechHIDPP20(controller);
RGBController_LogitechHIDPP20* rgb_controller = new RGBController_LogitechHIDPP20(controller, [device_id](){HIDPP20UnclaimDevice(device_id);});
/*-------------------------------------------------*\
| Reader and power threads from the start, so we |
@@ -1569,7 +1406,7 @@ static DetectedControllers HIDPP20Create(hid_device_info* info, const std::strin
HIDPP20RecordTarget(target);
RGBController_LogitechHIDPP20* rgb_controller = HIDPP20BuildController(target);
RGBController_LogitechHIDPP20* rgb_controller = HIDPP20BuildController(target, device_id);
if(rgb_controller != nullptr)
{
@@ -1684,29 +1521,6 @@ DetectedControllers DetectLogitechHIDPP20(hid_device_info* info, const std::stri
return(detected);
}
/*-------------------------------------------------------------------------------------------------------------------------------------*\
| Unified HID++ 2.0: generic detection. These run only for devices with no *enabled* VID/PID-specific detector, disabling a legacy |
| controller in Settings hands its hardware over on the next detection. That is the migration path: no code change, and no risk to a |
| device whose legacy controller stays enabled. |
| |
| The registrations cover every legacy transport signature: |
| any interface, 0xFF00 usage 2 standard HID++ long report (modern keyboards/mice, receivers, G915 family, wired Lightspeed mice). |
| Usage 2 is the collection we write to, on Windows, the only one that accepts our writes. |
| any interface, 0xFF43 any usage keyboards (G213/G512/G610/G810/G813/G815/G910/G Pro), the G560 speaker, the |
| G933 headset, and Bluetooth nodes. Not interface-keyed: a Bluetooth node |
| reports interface -1, which is also HID_INTERFACE_ANY, so it can never match. |
| interface 1, 0xFF00 any usage older mice whose HID++ collection is not the usage-2 one |
| any interface, 0xFFA0 usage 1 Centurion (G522, PRO X 2) |
| |
| Not covered, deliberately: the G600 (page 0xFF80) and the X56 (own VID) are not HID++ 2.0. A matching non-HID++ node costs one failed |
| probe, ProbeIdentity changes nothing on the device. Receivers are recognized at runtime: the device probe fails and the pairing table |
| answers; paired slots follow the same enabled/disabled rule (hidpp20_legacy_wireless_pids). |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_PU_ONLY ("Logitech HID++ 2.0", DetectLogitechHIDPP20, 0xFF00, 2);
REGISTER_HID_DETECTOR_P_ONLY ("Logitech HID++ 2.0", DetectLogitechHIDPP20, 0xFF43);
REGISTER_HID_DETECTOR_IP_ONLY ("Logitech HID++ 2.0", DetectLogitechHIDPP20, 1, 0xFF00);
REGISTER_HID_DETECTOR_PU_ONLY ("Logitech HID++ 2.0", DetectLogitechHIDPP20, 0xFFA0, 1);
REGISTER_CUSTOM_UDEV_RULE(logitech_hidpp20, "Logitech HID++ 2.0", "SUBSYSTEM==\"hidraw\", ATTRS{idVendor}==\"046d\", TAG+=\"uaccess\", TAG+=\"Logitech_HID_20\"\nSUBSYSTEM==\"usb\", ATTR{idVendor}==\"046d\", TAG+=\"uaccess\", TAG+=\"Logitech_HID_20\"");
REGISTER_CUSTOM_UDEV_RULE(logitech_g560, "Logitech G560 Lightsync Speaker", "SUBSYSTEMS==\"usb|hidraw\", ATTRS{idVendor}==\"046d\", ATTRS{idProduct}==\"0a78\", TAG+=\"uaccess\", TAG+=\"Logitech_G560_Lightsync_Speaker\"");
@@ -1714,35 +1528,14 @@ REGISTER_CUSTOM_UDEV_RULE(logitech_g560, "Logitech G560 Lightsync Speaker", "SUB
| Keyboards |
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_IPU("Logitech G213", DetectLogitechKeyboardG213, LOGITECH_VID, LOGITECH_G213_PID, 1, 0xFF43, 0x0602);
REGISTER_HID_DETECTOR_IP ("Logitech G512", DetectLogitechKeyboardG810, LOGITECH_VID, LOGITECH_G512_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G512 RGB", DetectLogitechKeyboardG810, LOGITECH_VID, LOGITECH_G512_RGB_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G610 Orion", DetectLogitechKeyboardG810, LOGITECH_VID, LOGITECH_G610_1_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G610 Orion", DetectLogitechKeyboardG810, LOGITECH_VID, LOGITECH_G610_2_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G810 Orion Spectrum", DetectLogitechKeyboardG810, LOGITECH_VID, LOGITECH_G810_1_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G810 Orion Spectrum", DetectLogitechKeyboardG810, LOGITECH_VID, LOGITECH_G810_2_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G813 RGB Mechanical Gaming Keyboard", DetectLogitechKeyboardG815, LOGITECH_VID, LOGITECH_G813_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G815 RGB Mechanical Gaming Keyboard", DetectLogitechKeyboardG815, LOGITECH_VID, LOGITECH_G815_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G910 Orion Spark", DetectLogitechKeyboardG910, LOGITECH_VID, LOGITECH_G910_ORION_SPARK_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G910 Orion Spectrum", DetectLogitechKeyboardG910, LOGITECH_VID, LOGITECH_G910_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech G Pro RGB Mechanical Gaming Keyboard", DetectLogitechKeyboardGPro, LOGITECH_VID, LOGITECH_GPRO_KEYBOARD_1_PID, 1, 0xFF43);
REGISTER_HID_DETECTOR_IPU("Logitech G915 Wireless RGB Mechanical Gaming Keyboard", DetectLogitechKeyboardG915, LOGITECH_VID, LOGITECH_G915_RECEIVER_PID, 2, 0xFF00, 2);
REGISTER_HID_DETECTOR_IPU("Logitech G915 Wireless RGB Mechanical Gaming Keyboard (Receiver 2)", DetectLogitechKeyboardG915Receiver2, LOGITECH_VID, LOGITECH_G915_RECEIVER_2_PID, 2, 0xFF00, 2);
REGISTER_HID_DETECTOR_IPU("Logitech G915 Wireless RGB Mechanical Gaming Keyboard (Wired)", DetectLogitechKeyboardG915Wired, LOGITECH_VID, LOGITECH_G915_WIRED_PID, 2, 0xFF00, 2);
REGISTER_HID_DETECTOR_IPU("Logitech G915TKL Wireless RGB Mechanical Gaming Keyboard", DetectLogitechKeyboardG915, LOGITECH_VID, LOGITECH_G915TKL_RECEIVER_PID, 2, 0xFF00, 2);
REGISTER_HID_DETECTOR_IPU("Logitech G915TKL Wireless RGB Mechanical Gaming Keyboard (Wired)", DetectLogitechKeyboardG915Wired, LOGITECH_VID, LOGITECH_G915TKL_WIRED_PID, 2, 0xFF00, 2);
/*---------------------------------------------------------*\
| C547 carve-out: the legacy G915 Receiver 2 registration |
| above makes C547 a VID/PID-specific match, which |
| suppresses the generic HID++ 2.0 detector for every C547 |
| node, including receivers with non-G915 devices paired. |
| This specific entry runs after the G915 detector |
| (registration order); when that returns nothing, the |
| unified pairing-table enumeration takes the receiver. |
| Literal PID: the macro token-pastes the object name and |
| LOGITECH_G915_RECEIVER_2_PID is already used above. |
\*---------------------------------------------------------*/
REGISTER_HID_DETECTOR_IPU("Logitech HID++ 2.0 (C547 receiver)", DetectLogitechHIDPP20, LOGITECH_VID, 0xC547, 2, 0xFF00, 2);
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
| Mice |
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -1973,3 +1766,31 @@ REGISTER_HID_DETECTOR_IPU("Logitech G733 Gaming Headset",
REGISTER_HID_DETECTOR_IPU("Logitech G733 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G733_2_PID, 3, 0xFF43, 514);
REGISTER_HID_DETECTOR_IPU("Logitech G733 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G733_3_PID, 3, 0xFF43, 514);
REGISTER_HID_DETECTOR_IPU("Logitech G935 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G935_PID, 3, 0xFF43, 514);
/*-------------------------------------------------------------------------------------------------------------------------------------*\
| Unified HID++ 2.0. Keyed to the Logitech VID, so these are specific detectors and no generic detector runs on a Logitech node; |
| HID LampArray in particular, which the official app publishes as a virtual device for older boards. Registered last on purpose: |
| specific detectors run in registration order and the first to return a controller wins, so a legacy controller keeps its device |
| while its detector is enabled, and disabling it in Settings hands the device over on the next detection. |
| |
| USB, every legacy transport signature: |
| 0xFF00 usage 2 standard HID++ long report (modern keyboards/mice, receivers, G915 family, wired Lightspeed mice). |
| Usage 2 is the collection we write to, on Windows, the only one that accepts our writes. |
| 0xFF43 any usage keyboards (G213/G512/G610/G810/G813/G815/G910/G Pro), the G560 speaker, the G933 headset |
| interface 1, 0xFF00 any usage older mice whose HID++ collection is not the usage-2 one. No bus key: an interface number |
| only exists on USB. |
| 0xFFA0 usage 1 Centurion (G522, PRO X 2) |
| Bluetooth, which reports no interface number: |
| 0xFF43 any usage G-series keyboards (G515) |
| 0xFF00 usage 2 mice, the collection Solaar drives them on |
| |
| Not covered, deliberately: the G600 (page 0xFF80) and the X56 (own VID) are not HID++ 2.0. A matching non-HID++ node costs one failed |
| probe, ProbeIdentity changes nothing on the device. Receivers are recognized at runtime: the device probe fails and the pairing table |
| answers; paired slots follow the same enabled/disabled rule (hidpp20_legacy_wireless_pids). |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_BPU("Logitech HID++ 2.0", DetectLogitechHIDPP20, LOGITECH_VID, HID_PID_ANY, HID_API_BUS_USB, 0xFF00, 2);
REGISTER_HID_DETECTOR_BP ("Logitech HID++ 2.0", DetectLogitechHIDPP20, LOGITECH_VID, HID_PID_ANY, HID_API_BUS_USB, 0xFF43);
REGISTER_HID_DETECTOR_IP ("Logitech HID++ 2.0", DetectLogitechHIDPP20, LOGITECH_VID, HID_PID_ANY, 1, 0xFF00);
REGISTER_HID_DETECTOR_BPU("Logitech HID++ 2.0", DetectLogitechHIDPP20, LOGITECH_VID, HID_PID_ANY, HID_API_BUS_USB, 0xFFA0, 1);
REGISTER_HID_DETECTOR_BP ("Logitech HID++ 2.0", DetectLogitechHIDPP20, LOGITECH_VID, HID_PID_ANY, HID_API_BUS_BLUETOOTH, 0xFF43);
REGISTER_HID_DETECTOR_BPU("Logitech HID++ 2.0", DetectLogitechHIDPP20, LOGITECH_VID, HID_PID_ANY, HID_API_BUS_BLUETOOTH, 0xFF00, 2);
@@ -1,198 +0,0 @@
/*---------------------------------------------------------*\
| LogitechG810Controller.cpp |
| |
| Driver for Logitech G810 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 11 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "LogitechG810Controller.h"
#include "StringUtils.h"
LogitechG810Controller::LogitechG810Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, char* path, std::string dev_name)
{
dev_pkt_0x11 = dev_handle_0x11;
dev_pkt_0x12 = dev_handle_0x12;
location = path;
name = dev_name;
}
LogitechG810Controller::~LogitechG810Controller()
{
hid_close(dev_pkt_0x11);
hid_close(dev_pkt_0x12);
}
std::string LogitechG810Controller::GetLocationString()
{
return("HID: " + location);
}
std::string LogitechG810Controller::GetNameString()
{
return(name);
}
std::string LogitechG810Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void LogitechG810Controller::Commit()
{
SendCommit();
}
void LogitechG810Controller::SetDirect
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
)
{
SendDirectFrame(zone, frame_count, frame_data);
}
void LogitechG810Controller::SetMode
(
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
SendMode(LOGITECH_G810_ZONE_MODE_KEYBOARD, mode, speed, red, green, blue);
SendMode(LOGITECH_G810_ZONE_MODE_LOGO, mode, speed, red, green, blue);
SendCommit();
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void LogitechG810Controller::SendCommit()
{
unsigned char usb_buf[20];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Commit packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x11;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0C;
usb_buf[0x03] = 0x5D;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x11, usb_buf, 20);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
void LogitechG810Controller::SendDirectFrame
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
)
{
unsigned char usb_buf[64];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Lighting Control packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x12;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0C;
usb_buf[0x03] = 0x3D;
usb_buf[0x05] = zone;
usb_buf[0x07] = frame_count;
/*-----------------------------------------------------*\
| Copy in frame data |
\*-----------------------------------------------------*/
memcpy(&usb_buf[0x08], frame_data, frame_count * 4);
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x12, usb_buf, 64);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
void LogitechG810Controller::SendMode
(
unsigned char zone,
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[20];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Lighting Control packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x11;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0D;
usb_buf[0x03] = 0x3D;
usb_buf[0x04] = zone;
usb_buf[0x05] = mode;
usb_buf[0x06] = red;
usb_buf[0x07] = green;
usb_buf[0x08] = blue;
speed = 100 * speed;
if(mode == LOGITECH_G810_MODE_CYCLE)
{
usb_buf[0x0B] = speed >> 8;
usb_buf[0x0C] = speed & 0xFF;
usb_buf[0x0D] = 0x64;
}
else if(mode == LOGITECH_G810_MODE_BREATHING)
{
usb_buf[0x09] = speed >> 8;
usb_buf[0x0A] = speed & 0xFF;
usb_buf[0x0C] = 0x64;
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x11, usb_buf, 20);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
@@ -1,104 +0,0 @@
/*---------------------------------------------------------*\
| LogitechG810Controller.h |
| |
| Driver for Logitech G810 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 11 Jun 2020 |
| |
| 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"
enum
{
LOGITECH_G810_ZONE_MODE_KEYBOARD = 0x00,
LOGITECH_G810_ZONE_MODE_LOGO = 0x01,
};
enum
{
LOGITECH_G810_ZONE_DIRECT_KEYBOARD = 0x01,
LOGITECH_G810_ZONE_DIRECT_MEDIA = 0x02,
LOGITECH_G810_ZONE_DIRECT_LOGO = 0x10,
LOGITECH_G810_ZONE_DIRECT_INDICATORS = 0x40,
};
enum
{
LOGITECH_G810_MODE_OFF = 0x00,
LOGITECH_G810_MODE_STATIC = 0x01,
LOGITECH_G810_MODE_BREATHING = 0x02,
LOGITECH_G810_MODE_CYCLE = 0x03,
LOGITECH_G810_MODE_WAVE = 0x04,
};
/*---------------------------------------------------------------------------------------------*\
| Speed is 1000 for fast and 20000 for slow. |
| Values are multiplied by 100 later to give lots of GUI steps. |
\*---------------------------------------------------------------------------------------------*/
enum
{
LOGITECH_G810_SPEED_SLOWEST = 0xC8, /* Slowest speed */
LOGITECH_G810_SPEED_NORMAL = 0x32, /* Normal speed */
LOGITECH_G810_SPEED_FASTEST = 0x0A, /* Fastest speed */
};
class LogitechG810Controller
{
public:
LogitechG810Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, char* path, std::string dev_name);
~LogitechG810Controller();
std::string GetLocationString();
std::string GetNameString();
std::string GetSerialString();
void Commit();
void SetDirect
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
);
void SetMode
(
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
private:
hid_device* dev_pkt_0x11;
hid_device* dev_pkt_0x12;
std::string location;
std::string name;
void SendDirectFrame
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
);
void SendMode
(
unsigned char zone,
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SendCommit();
};
@@ -1,380 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_LogitechG810.cpp |
| |
| RGBController for Logitech G810 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 12 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_LogitechG810.h"
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[7][23] =
{ { 111, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 116, 114, 115, NA, 113, NA, 112, 110, NA, NA, NA },
{ 37, NA, 54, 55, 56, 57, NA, 58, 59, 60, 61, NA, 62, 63, 64, 65, 66, 67, 68, 109, 108, 107, 106 },
{ 49, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, NA, 41, 42, 38, NA, 69, 70, 71, 79, 80, 81, 82 },
{ 39, NA, 16, 22, 4, 17, NA, 19, 24, 20, 8, 14, 15, 43, 44, 45, 72, 73, 74, 91, 92, 93, 83 },
{ 53, NA, 0, 18, 3, 5, NA, 6, 7, 9, 10, 11, 47, 48, 46, 36, NA, NA, NA, 88, 89, 90, NA },
{ 99, 96, 25, 23, 2, 21, NA, 1, NA, 13, 12, 50, 51, 52, 103, NA, NA, 78, NA, 85, 86, 87, 84 },
{ 98, 101, 100, NA, NA, NA, NA, 40, NA, NA, NA, NA, 104, 105, 97, 102, 76, 77, 75, 94, NA, 95, NA } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
117,
};
typedef struct
{
const char * name;
const unsigned char zone;
const unsigned char idx;
} led_type;
static const led_type led_names[] =
{
/* Key Label Zone, Index */
{ KEY_EN_A, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x04 },
{ KEY_EN_B, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x05 },
{ KEY_EN_C, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x06 },
{ KEY_EN_D, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x07 },
{ KEY_EN_E, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x08 },
{ KEY_EN_F, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x09 },
{ KEY_EN_G, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x0A },
{ KEY_EN_H, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x0B },
{ KEY_EN_I, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x0C },
{ KEY_EN_J, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x0D },
{ KEY_EN_K, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x0E },
{ KEY_EN_L, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x0F },
{ KEY_EN_M, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x10 },
{ KEY_EN_N, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x11 },
{ KEY_EN_O, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x12 },
{ KEY_EN_P, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x13 },
{ KEY_EN_Q, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x14 },
{ KEY_EN_R, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x15 },
{ KEY_EN_S, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x16 },
{ KEY_EN_T, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x17 },
{ KEY_EN_U, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x18 },
{ KEY_EN_V, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x19 },
{ KEY_EN_W, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x1A },
{ KEY_EN_X, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x1B },
{ KEY_EN_Y, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x1C },
{ KEY_EN_Z, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x1D },
{ KEY_EN_1, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x1E },
{ KEY_EN_2, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x1F },
{ KEY_EN_3, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x20 },
{ KEY_EN_4, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x21 },
{ KEY_EN_5, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x22 },
{ KEY_EN_6, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x23 },
{ KEY_EN_7, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x24 },
{ KEY_EN_8, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x25 },
{ KEY_EN_9, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x26 },
{ KEY_EN_0, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x27 },
{ KEY_EN_ANSI_ENTER, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x28 },
{ KEY_EN_ESCAPE, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x29 },
{ KEY_EN_BACKSPACE, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x2A },
{ KEY_EN_TAB, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x2B },
{ KEY_EN_SPACE, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x2C },
{ KEY_EN_MINUS, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x2D },
{ KEY_EN_EQUALS, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x2E },
{ KEY_EN_LEFT_BRACKET, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x2F },
{ KEY_EN_RIGHT_BRACKET, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x30 },
{ KEY_EN_ANSI_BACK_SLASH, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x31 },//ANSI only
{ KEY_EN_POUND, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x32 },//ISO only
{ KEY_EN_SEMICOLON, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x33 },
{ KEY_EN_QUOTE, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x34 },
{ KEY_EN_BACK_TICK, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x35 },
{ KEY_EN_COMMA, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x36 },
{ KEY_EN_PERIOD, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x37 },
{ KEY_EN_FORWARD_SLASH, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x38 },
{ KEY_EN_CAPS_LOCK, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x39 },
{ KEY_EN_F1, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x3A },
{ KEY_EN_F2, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x3B },
{ KEY_EN_F3, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x3C },
{ KEY_EN_F4, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x3D },
{ KEY_EN_F5, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x3E },
{ KEY_EN_F6, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x3F },
{ KEY_EN_F7, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x40 },
{ KEY_EN_F8, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x41 },
{ KEY_EN_F9, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x42 },
{ KEY_EN_F10, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x43 },
{ KEY_EN_F11, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x44 },
{ KEY_EN_F12, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x45 },
{ KEY_EN_PRINT_SCREEN, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x46 },
{ KEY_EN_SCROLL_LOCK, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x47 },
{ KEY_EN_PAUSE_BREAK, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x48 },
{ KEY_EN_INSERT, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x49 },
{ KEY_EN_HOME, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x4A },
{ KEY_EN_PAGE_UP, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x4B },
{ KEY_EN_DELETE, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x4C },
{ KEY_EN_END, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x4D },
{ KEY_EN_PAGE_DOWN, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x4E },
{ KEY_EN_RIGHT_ARROW, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x4F },
{ KEY_EN_LEFT_ARROW, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x50 },
{ KEY_EN_DOWN_ARROW, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x51 },
{ KEY_EN_UP_ARROW, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x52 },
{ KEY_EN_NUMPAD_LOCK, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x53 },
{ KEY_EN_NUMPAD_DIVIDE, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x54 },
{ KEY_EN_NUMPAD_TIMES, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x55 },
{ KEY_EN_NUMPAD_MINUS, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x56 },
{ KEY_EN_NUMPAD_PLUS, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x57 },
{ KEY_EN_NUMPAD_ENTER, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x58 },
{ KEY_EN_NUMPAD_1, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x59 },
{ KEY_EN_NUMPAD_2, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x5A },
{ KEY_EN_NUMPAD_3, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x5B },
{ KEY_EN_NUMPAD_4, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x5C },
{ KEY_EN_NUMPAD_5, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x5D },
{ KEY_EN_NUMPAD_6, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x5E },
{ KEY_EN_NUMPAD_7, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x5F },
{ KEY_EN_NUMPAD_8, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x60 },
{ KEY_EN_NUMPAD_9, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x61 },
{ KEY_EN_NUMPAD_0, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x62 },
{ KEY_EN_NUMPAD_PERIOD, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x63 },
{ KEY_EN_ISO_BACK_SLASH, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x64 },//ISO only
{ KEY_EN_MENU, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0x65 },
{ KEY_EN_LEFT_CONTROL, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE0 },
{ KEY_EN_LEFT_SHIFT, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE1 },
{ KEY_EN_LEFT_ALT, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE2 },
{ KEY_EN_LEFT_WINDOWS, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE3 },
{ KEY_EN_RIGHT_CONTROL, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE4 },
{ KEY_EN_RIGHT_SHIFT, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE5 },
{ KEY_EN_RIGHT_ALT, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE6 },
{ KEY_EN_RIGHT_WINDOWS, LOGITECH_G810_ZONE_DIRECT_KEYBOARD, 0xE7 },
{ KEY_EN_MEDIA_NEXT, LOGITECH_G810_ZONE_DIRECT_MEDIA, 0xB5 },
{ KEY_EN_MEDIA_PREVIOUS, LOGITECH_G810_ZONE_DIRECT_MEDIA, 0xB6 },
{ KEY_EN_MEDIA_STOP, LOGITECH_G810_ZONE_DIRECT_MEDIA, 0xB7 },
{ KEY_EN_MEDIA_PLAY_PAUSE, LOGITECH_G810_ZONE_DIRECT_MEDIA, 0xCD },
{ KEY_EN_MEDIA_MUTE, LOGITECH_G810_ZONE_DIRECT_MEDIA, 0xE2 },
{ "Logo", LOGITECH_G810_ZONE_DIRECT_LOGO, 0x01 },
{ "Lighting", LOGITECH_G810_ZONE_DIRECT_INDICATORS, 0x01 },
{ "Game Mode", LOGITECH_G810_ZONE_DIRECT_INDICATORS, 0x02 },
{ "Caps Lock Indicator", LOGITECH_G810_ZONE_DIRECT_INDICATORS, 0x03 },
{ "Scroll Lock Indicator", LOGITECH_G810_ZONE_DIRECT_INDICATORS, 0x04 },
{ "Num Lock Indicator", LOGITECH_G810_ZONE_DIRECT_INDICATORS, 0x05 },
};
/**------------------------------------------------------------------*\
@name Logitech G810
@category Keyboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectLogitechKeyboardG810
@comment
\*-------------------------------------------------------------------*/
RGBController_LogitechG810::RGBController_LogitechG810(LogitechG810Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "Logitech";
type = DEVICE_TYPE_KEYBOARD;
description = "Logitech Keyboard Device";
location = controller->GetLocationString();
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);
mode Static;
Static.name = "Static";
Static.value = LOGITECH_G810_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Static.colors_min = 1;
Static.colors_max = 1;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.colors.resize(1);
modes.push_back(Static);
mode Off;
Off.name = "Off";
Off.value = LOGITECH_G810_MODE_OFF;
Off.flags = 0;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Cycle;
Cycle.name = "Cycle";
Cycle.value = LOGITECH_G810_MODE_CYCLE;
Cycle.flags = MODE_FLAG_HAS_SPEED;
Cycle.color_mode = MODE_COLORS_NONE;
Cycle.speed_min = LOGITECH_G810_SPEED_SLOWEST;
Cycle.speed_max = LOGITECH_G810_SPEED_FASTEST;
Cycle.speed = LOGITECH_G810_SPEED_NORMAL;
modes.push_back(Cycle);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = LOGITECH_G810_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.colors.resize(1);
Breathing.speed_min = LOGITECH_G810_SPEED_SLOWEST;
Breathing.speed_max = LOGITECH_G810_SPEED_FASTEST;
Breathing.speed = LOGITECH_G810_SPEED_NORMAL;
modes.push_back(Breathing);
SetupZones();
}
RGBController_LogitechG810::~RGBController_LogitechG810()
{
Shutdown();
delete controller;
}
void RGBController_LogitechG810::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.Set(7, 23, (unsigned int *)&matrix_map);
}
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].name;
new_led.value = ( led_names[led_idx].zone << 8 ) + led_names[led_idx].idx;
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_LogitechG810::DeviceUpdateLEDs()
{
#define MAX_FRAMES_PER_PACKET 0x0E
unsigned char frame_buf[MAX_FRAMES_PER_PACKET * 4];
unsigned char frame_cnt = 0;
unsigned char prev_zone = 0;
unsigned char zone = 0;
unsigned char idx = 0;
/*---------------------------------------------------------*\
| TODO: Send packets with multiple LED frames |
\*---------------------------------------------------------*/
for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++)
{
zone = ( leds[led_idx].value >> 8 );
idx = ( leds[led_idx].value & 0xFF );
if((zone != prev_zone) && (frame_cnt != 0))
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
frame_cnt = 0;
}
frame_buf[(frame_cnt * 4) + 0] = idx;
frame_buf[(frame_cnt * 4) + 1] = RGBGetRValue(colors[led_idx]);
frame_buf[(frame_cnt * 4) + 2] = RGBGetGValue(colors[led_idx]);
frame_buf[(frame_cnt * 4) + 3] = RGBGetBValue(colors[led_idx]);
frame_cnt++;
prev_zone = zone;
if(frame_cnt == MAX_FRAMES_PER_PACKET)
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
frame_cnt = 0;
}
}
if(frame_cnt != 0)
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
}
controller->Commit();
}
void RGBController_LogitechG810::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_LogitechG810::DeviceUpdateSingleLED(int led)
{
unsigned char frame[4];
unsigned char zone;
unsigned char idx;
zone = ( leds[led].value >> 8 );
idx = ( leds[led].value & 0xFF );
frame[0] = idx;
frame[1] = RGBGetRValue(colors[led]);
frame[2] = RGBGetGValue(colors[led]);
frame[3] = RGBGetBValue(colors[led]);
controller->SetDirect(zone, 1, frame);
controller->Commit();
}
void RGBController_LogitechG810::DeviceUpdateMode()
{
/*---------------------------------------------------------*\
| Direct mode does not send a mode packet |
| Call UpdateLEDs to send direct packet |
\*---------------------------------------------------------*/
if(active_mode == 0xFFFF)
{
UpdateLEDsInternal();
return;
}
unsigned char red = 0;
unsigned char grn = 0;
unsigned char blu = 0;
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
red = RGBGetRValue(modes[active_mode].colors[0]);
grn = RGBGetGValue(modes[active_mode].colors[0]);
blu = RGBGetBValue(modes[active_mode].colors[0]);
}
controller->SetMode(modes[active_mode].value, modes[active_mode].speed, red, grn, blu);
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_LogitechG810.h |
| |
| RGBController for Logitech G810 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 12 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "LogitechG810Controller.h"
class RGBController_LogitechG810 : public RGBController
{
public:
RGBController_LogitechG810(LogitechG810Controller* controller_ptr);
~RGBController_LogitechG810();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
LogitechG810Controller* controller;
};
@@ -1,198 +0,0 @@
/*---------------------------------------------------------*\
| LogitechG910Controller.cpp |
| |
| Driver for Logitech G910 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 11 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "LogitechG910Controller.h"
#include "StringUtils.h"
LogitechG910Controller::LogitechG910Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, char* path, std::string dev_name)
{
dev_pkt_0x11 = dev_handle_0x11;
dev_pkt_0x12 = dev_handle_0x12;
location = path;
name = dev_name;
}
LogitechG910Controller::~LogitechG910Controller()
{
hid_close(dev_pkt_0x11);
hid_close(dev_pkt_0x12);
}
std::string LogitechG910Controller::GetNameString()
{
return(name);
}
std::string LogitechG910Controller::GetLocationString()
{
return("HID: " + location);
}
std::string LogitechG910Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void LogitechG910Controller::Commit()
{
SendCommit();
}
void LogitechG910Controller::SetDirect
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
)
{
SendDirectFrame(zone, frame_count, frame_data);
}
void LogitechG910Controller::SetMode
(
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
SendMode(LOGITECH_G910_ZONE_MODE_KEYBOARD, mode, speed, red, green, blue);
SendMode(LOGITECH_G910_ZONE_MODE_LOGO, mode, speed, red, green, blue);
SendCommit();
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void LogitechG910Controller::SendCommit()
{
unsigned char usb_buf[20];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Commit packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x11;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0F;
usb_buf[0x03] = 0x5F;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x11, usb_buf, 20);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
void LogitechG910Controller::SendDirectFrame
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
)
{
unsigned char usb_buf[64];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Lighting Control packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x12;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0F;
usb_buf[0x03] = 0x3F;
usb_buf[0x05] = zone;
usb_buf[0x07] = frame_count;
/*-----------------------------------------------------*\
| Copy in frame data |
\*-----------------------------------------------------*/
memcpy(&usb_buf[0x08], frame_data, frame_count * 4);
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x12, usb_buf, 64);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
void LogitechG910Controller::SendMode
(
unsigned char zone,
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[20];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Lighting Control packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x11;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x10;
usb_buf[0x03] = 0x3B;
usb_buf[0x04] = zone;
usb_buf[0x05] = mode;
usb_buf[0x06] = red;
usb_buf[0x07] = green;
usb_buf[0x08] = blue;
speed = 100 * speed;
if(mode == LOGITECH_G910_MODE_CYCLE)
{
usb_buf[0x0B] = speed >> 8;
usb_buf[0x0C] = speed & 0xFF;
usb_buf[0x0D] = 0x64;
}
else if(mode == LOGITECH_G910_MODE_BREATHING)
{
usb_buf[0x09] = speed >> 8;
usb_buf[0x0A] = speed & 0xFF;
usb_buf[0x0C] = 0x64;
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x11, usb_buf, 20);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
@@ -1,104 +0,0 @@
/*---------------------------------------------------------*\
| LogitechG910Controller.h |
| |
| Driver for Logitech G910 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 11 Jun 2020 |
| |
| 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"
enum
{
LOGITECH_G910_ZONE_MODE_KEYBOARD = 0x00,
LOGITECH_G910_ZONE_MODE_LOGO = 0x01,
};
enum
{
LOGITECH_G910_ZONE_DIRECT_KEYBOARD = 0x01,
LOGITECH_G910_ZONE_DIRECT_GKEYS = 0x04,
LOGITECH_G910_ZONE_DIRECT_LOGO = 0x10,
LOGITECH_G910_ZONE_DIRECT_INDICATORS = 0x40,
};
enum
{
LOGITECH_G910_MODE_OFF = 0x00,
LOGITECH_G910_MODE_STATIC = 0x01,
LOGITECH_G910_MODE_BREATHING = 0x02,
LOGITECH_G910_MODE_CYCLE = 0x03,
LOGITECH_G910_MODE_WAVE = 0x04,
};
/*---------------------------------------------------------------------------------------------*\
| Speed is 1000 for fast and 20000 for slow. |
| Values are multiplied by 100 later to give lots of GUI steps. |
\*---------------------------------------------------------------------------------------------*/
enum
{
LOGITECH_G910_SPEED_SLOWEST = 0xC8, /* Slowest speed */
LOGITECH_G910_SPEED_NORMAL = 0x32, /* Normal speed */
LOGITECH_G910_SPEED_FASTEST = 0x0A, /* Fastest speed */
};
class LogitechG910Controller
{
public:
LogitechG910Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, char* path, std::string dev_name);
~LogitechG910Controller();
std::string GetLocationString();
std::string GetNameString();
std::string GetSerialString();
void Commit();
void SetDirect
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
);
void SetMode
(
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
private:
hid_device* dev_pkt_0x11;
hid_device* dev_pkt_0x12;
std::string location;
std::string name;
void SendDirectFrame
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
);
void SendMode
(
unsigned char zone,
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SendCommit();
};
@@ -1,381 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_LogitechG910.cpp |
| |
| RGBController for Logitech G910 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 12 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_LogitechG910.h"
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[8][24] =
{ { NA, 111, 112, 113, 114, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA },
{ 115, 37, NA, 54, 55, 56, 57, NA, 58, 59, 60, 61, NA, 62, 63, 64, 65, 66, 67, 68, NA, NA, NA, NA },
{ 106, 49, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, NA, 41, 42, 38, NA, 69, 70, 71, 79, 80, 81, 82 },
{ 107, 39, NA, 16, 22, 4, 17, NA, 19, 24, 20, 8, 14, 15, 43, 44, 45, 72, 73, 74, 91, 92, 93, 83 },
{ 108, 53, NA, 0, 18, 3, 5, NA, 6, 7, 9, 10, 11, 47, 48, 46, 36, NA, NA, NA, 88, 89, 90, NA },
{ 109, 99, 96, 25, 23, 2, 21, NA, 1, NA, 13, 12, 50, 51, 52, 103, NA, NA, 78, NA, 85, 86, 87, 84 },
{ 110, 98, 101, 100, NA, NA, NA, NA, 40, NA, NA, NA, NA, 104, 105, 97, 102, 76, 77, 75, 94, NA, 95, NA },
{ NA, NA, NA, 116, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
117,
};
typedef struct
{
const char * name;
const unsigned char zone;
const unsigned char idx;
} led_type;
static const led_type led_names[] =
{
/* Key Label Zone, Index */
{ KEY_EN_A, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x04 },
{ KEY_EN_B, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x05 },
{ KEY_EN_C, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x06 },
{ KEY_EN_D, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x07 },
{ KEY_EN_E, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x08 },
{ KEY_EN_F, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x09 },
{ KEY_EN_G, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x0A },
{ KEY_EN_H, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x0B },
{ KEY_EN_I, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x0C },
{ KEY_EN_J, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x0D },
{ KEY_EN_K, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x0E },
{ KEY_EN_L, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x0F },
{ KEY_EN_M, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x10 },
{ KEY_EN_N, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x11 },
{ KEY_EN_O, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x12 },
{ KEY_EN_P, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x13 },
{ KEY_EN_Q, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x14 },
{ KEY_EN_R, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x15 },
{ KEY_EN_S, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x16 },
{ KEY_EN_T, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x17 },
{ KEY_EN_U, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x18 },
{ KEY_EN_V, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x19 },
{ KEY_EN_W, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x1A },
{ KEY_EN_X, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x1B },
{ KEY_EN_Y, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x1C },
{ KEY_EN_Z, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x1D },
{ KEY_EN_1, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x1E },
{ KEY_EN_2, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x1F },
{ KEY_EN_3, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x20 },
{ KEY_EN_4, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x21 },
{ KEY_EN_5, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x22 },
{ KEY_EN_6, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x23 },
{ KEY_EN_7, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x24 },
{ KEY_EN_8, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x25 },
{ KEY_EN_9, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x26 },
{ KEY_EN_0, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x27 },
{ KEY_EN_ANSI_ENTER, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x28 },
{ KEY_EN_ESCAPE, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x29 },
{ KEY_EN_BACKSPACE, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x2A },
{ KEY_EN_TAB, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x2B },
{ KEY_EN_SPACE, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x2C },
{ KEY_EN_MINUS, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x2D },
{ KEY_EN_EQUALS, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x2E },
{ KEY_EN_LEFT_BRACKET, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x2F },
{ KEY_EN_RIGHT_BRACKET, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x30 },
{ KEY_EN_ANSI_BACK_SLASH, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x31 },//ANSI only
{ KEY_EN_POUND, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x32 },//ISO only
{ KEY_EN_SEMICOLON, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x33 },
{ KEY_EN_QUOTE, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x34 },
{ KEY_EN_BACK_TICK, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x35 },
{ KEY_EN_COMMA, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x36 },
{ KEY_EN_PERIOD, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x37 },
{ KEY_EN_FORWARD_SLASH, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x38 },
{ KEY_EN_CAPS_LOCK, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x39 },
{ KEY_EN_F1, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x3A },
{ KEY_EN_F2, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x3B },
{ KEY_EN_F3, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x3C },
{ KEY_EN_F4, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x3D },
{ KEY_EN_F5, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x3E },
{ KEY_EN_F6, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x3F },
{ KEY_EN_F7, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x40 },
{ KEY_EN_F8, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x41 },
{ KEY_EN_F9, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x42 },
{ KEY_EN_F10, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x43 },
{ KEY_EN_F11, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x44 },
{ KEY_EN_F12, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x45 },
{ KEY_EN_PRINT_SCREEN, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x46 },
{ KEY_EN_SCROLL_LOCK, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x47 },
{ KEY_EN_PAUSE_BREAK, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x48 },
{ KEY_EN_INSERT, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x49 },
{ KEY_EN_HOME, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x4A },
{ KEY_EN_PAGE_UP, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x4B },
{ KEY_EN_DELETE, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x4C },
{ KEY_EN_END, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x4D },
{ KEY_EN_PAGE_DOWN, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x4E },
{ KEY_EN_RIGHT_ARROW, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x4F },
{ KEY_EN_LEFT_ARROW, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x50 },
{ KEY_EN_DOWN_ARROW, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x51 },
{ KEY_EN_UP_ARROW, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x52 },
{ KEY_EN_NUMPAD_LOCK, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x53 },
{ KEY_EN_NUMPAD_DIVIDE, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x54 },
{ KEY_EN_NUMPAD_TIMES, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x55 },
{ KEY_EN_NUMPAD_MINUS, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x56 },
{ KEY_EN_NUMPAD_PLUS, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x57 },
{ KEY_EN_NUMPAD_ENTER, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x58 },
{ KEY_EN_NUMPAD_1, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x59 },
{ KEY_EN_NUMPAD_2, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x5A },
{ KEY_EN_NUMPAD_3, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x5B },
{ KEY_EN_NUMPAD_4, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x5C },
{ KEY_EN_NUMPAD_5, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x5D },
{ KEY_EN_NUMPAD_6, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x5E },
{ KEY_EN_NUMPAD_7, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x5F },
{ KEY_EN_NUMPAD_8, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x60 },
{ KEY_EN_NUMPAD_9, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x61 },
{ KEY_EN_NUMPAD_0, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x62 },
{ KEY_EN_NUMPAD_PERIOD, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x63 },
{ KEY_EN_ISO_BACK_SLASH, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x64 },//ISO only
{ KEY_EN_MENU, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0x65 },
{ KEY_EN_LEFT_CONTROL, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE0 },
{ KEY_EN_LEFT_SHIFT, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE1 },
{ KEY_EN_LEFT_ALT, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE2 },
{ KEY_EN_LEFT_WINDOWS, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE3 },
{ KEY_EN_RIGHT_CONTROL, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE4 },
{ KEY_EN_RIGHT_SHIFT, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE5 },
{ KEY_EN_RIGHT_ALT, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE6 },
{ KEY_EN_RIGHT_WINDOWS, LOGITECH_G910_ZONE_DIRECT_KEYBOARD, 0xE7 },
{ "Key: G1", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x01 },
{ "Key: G2", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x02 },
{ "Key: G3", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x03 },
{ "Key: G4", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x04 },
{ "Key: G5", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x05 },
{ "Key: G6", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x06 },
{ "Key: G7", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x07 },
{ "Key: G8", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x08 },
{ "Key: G9", LOGITECH_G910_ZONE_DIRECT_GKEYS, 0x09 },
{ "Logo", LOGITECH_G910_ZONE_DIRECT_LOGO, 0x01 },
{ "Nameplate", LOGITECH_G910_ZONE_DIRECT_LOGO, 0x02 },
};
/**------------------------------------------------------------------*\
@name Logitech G910
@category Keyboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectLogitechKeyboardG910
@comment
\*-------------------------------------------------------------------*/
RGBController_LogitechG910::RGBController_LogitechG910(LogitechG910Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "Logitech";
type = DEVICE_TYPE_KEYBOARD;
description = "Logitech Keyboard Device";
location = controller->GetLocationString();
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);
mode Static;
Static.name = "Static";
Static.value = LOGITECH_G910_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Static.colors_min = 1;
Static.colors_max = 1;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.colors.resize(1);
modes.push_back(Static);
mode Off;
Off.name = "Off";
Off.value = LOGITECH_G910_MODE_OFF;
Off.flags = 0;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Cycle;
Cycle.name = "Cycle";
Cycle.value = LOGITECH_G910_MODE_CYCLE;
Cycle.flags = MODE_FLAG_HAS_SPEED;
Cycle.color_mode = MODE_COLORS_NONE;
Cycle.speed_min = LOGITECH_G910_SPEED_SLOWEST;
Cycle.speed_max = LOGITECH_G910_SPEED_FASTEST;
Cycle.speed = LOGITECH_G910_SPEED_NORMAL;
modes.push_back(Cycle);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = LOGITECH_G910_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.colors.resize(1);
Breathing.speed_min = LOGITECH_G910_SPEED_SLOWEST;
Breathing.speed_max = LOGITECH_G910_SPEED_FASTEST;
Breathing.speed = LOGITECH_G910_SPEED_NORMAL;
modes.push_back(Breathing);
SetupZones();
}
RGBController_LogitechG910::~RGBController_LogitechG910()
{
Shutdown();
delete controller;
}
void RGBController_LogitechG910::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.Set(8, 24, (unsigned int *)&matrix_map);
}
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].name;
new_led.value = ( led_names[led_idx].zone << 8 ) + led_names[led_idx].idx;
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_LogitechG910::DeviceUpdateLEDs()
{
#define MAX_FRAMES_PER_PACKET 0x0E
unsigned char frame_buf[MAX_FRAMES_PER_PACKET * 4];
unsigned char frame_cnt = 0;
unsigned char prev_zone = 0;
unsigned char zone = 0;
unsigned char idx = 0;
/*---------------------------------------------------------*\
| TODO: Send packets with multiple LED frames |
\*---------------------------------------------------------*/
for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++)
{
zone = ( leds[led_idx].value >> 8 );
idx = ( leds[led_idx].value & 0xFF );
if((zone != prev_zone) && (frame_cnt != 0))
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
frame_cnt = 0;
}
frame_buf[(frame_cnt * 4) + 0] = idx;
frame_buf[(frame_cnt * 4) + 1] = RGBGetRValue(colors[led_idx]);
frame_buf[(frame_cnt * 4) + 2] = RGBGetGValue(colors[led_idx]);
frame_buf[(frame_cnt * 4) + 3] = RGBGetBValue(colors[led_idx]);
frame_cnt++;
prev_zone = zone;
if(frame_cnt == MAX_FRAMES_PER_PACKET)
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
frame_cnt = 0;
}
}
if(frame_cnt != 0)
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
}
controller->Commit();
}
void RGBController_LogitechG910::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_LogitechG910::DeviceUpdateSingleLED(int led)
{
unsigned char frame[4];
unsigned char zone;
unsigned char idx;
zone = ( leds[led].value >> 8 );
idx = ( leds[led].value & 0xFF );
frame[0] = idx;
frame[1] = RGBGetRValue(colors[led]);
frame[2] = RGBGetGValue(colors[led]);
frame[3] = RGBGetBValue(colors[led]);
controller->SetDirect(zone, 1, frame);
controller->Commit();
}
void RGBController_LogitechG910::DeviceUpdateMode()
{
/*---------------------------------------------------------*\
| Direct mode does not send a mode packet |
| Call UpdateLEDs to send direct packet |
\*---------------------------------------------------------*/
if(active_mode == 0xFFFF)
{
UpdateLEDsInternal();
return;
}
unsigned char red = 0;
unsigned char grn = 0;
unsigned char blu = 0;
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
red = RGBGetRValue(modes[active_mode].colors[0]);
grn = RGBGetGValue(modes[active_mode].colors[0]);
blu = RGBGetBValue(modes[active_mode].colors[0]);
}
controller->SetMode(modes[active_mode].value, modes[active_mode].speed, red, grn, blu);
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_LogitechG910.h |
| |
| RGBController for Logitech G910 Orion Spectrum |
| |
| Adam Honse (CalcProgrammer1) 12 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "LogitechG910Controller.h"
class RGBController_LogitechG910 : public RGBController
{
public:
RGBController_LogitechG910(LogitechG910Controller* controller_ptr);
~RGBController_LogitechG910();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
LogitechG910Controller* controller;
};
@@ -1,192 +0,0 @@
/*---------------------------------------------------------*\
| LogitechGProController.cpp |
| |
| Driver for Logitech G Pro keyboard |
| |
| sanchezzzs 20 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "LogitechGProKeyboardController.h"
#include "StringUtils.h"
LogitechGProKeyboardController::LogitechGProKeyboardController(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name)
{
dev_pkt_0x11 = dev_handle_0x11;
dev_pkt_0x12 = dev_handle_0x12;
name = dev_name;
}
LogitechGProKeyboardController::~LogitechGProKeyboardController()
{
hid_close(dev_pkt_0x11);
hid_close(dev_pkt_0x12);
}
std::string LogitechGProKeyboardController::GetNameString()
{
return(name);
}
std::string LogitechGProKeyboardController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void LogitechGProKeyboardController::Commit()
{
SendCommit();
}
void LogitechGProKeyboardController::SetDirect
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
)
{
SendDirectFrame(zone, frame_count, frame_data);
}
void LogitechGProKeyboardController::SetMode
(
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
SendMode(LOGITECH_GPRO_ZONE_MODE_KEYBOARD, mode, speed, red, green, blue);
SendMode(LOGITECH_GPRO_ZONE_MODE_LOGO, mode, speed, red, green, blue);
SendCommit();
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void LogitechGProKeyboardController::SendCommit()
{
unsigned char usb_buf[20];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Commit packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x11;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0C;
usb_buf[0x03] = 0x5D;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x11, usb_buf, 20);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
void LogitechGProKeyboardController::SendDirectFrame
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
)
{
unsigned char usb_buf[64];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Lighting Control packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x12;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0C;
usb_buf[0x03] = 0x3D;
usb_buf[0x05] = zone;
usb_buf[0x07] = frame_count;
/*-----------------------------------------------------*\
| Copy in frame data |
\*-----------------------------------------------------*/
memcpy(&usb_buf[0x08], frame_data, frame_count * 4);
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x12, usb_buf, 64);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
void LogitechGProKeyboardController::SendMode
(
unsigned char zone,
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[20];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Lighting Control packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x11;
usb_buf[0x01] = 0xFF;
usb_buf[0x02] = 0x0D;
usb_buf[0x03] = 0x3D;
usb_buf[0x04] = zone;
usb_buf[0x05] = mode;
usb_buf[0x06] = red;
usb_buf[0x07] = green;
usb_buf[0x08] = blue;
speed = 100 * speed;
if(mode == LOGITECH_GPRO_MODE_CYCLE)
{
usb_buf[0x0B] = speed >> 8;
usb_buf[0x0C] = speed & 0xFF;
usb_buf[0x0D] = 0x64;
}
else if(mode == LOGITECH_GPRO_MODE_BREATHING)
{
usb_buf[0x09] = speed >> 8;
usb_buf[0x0A] = speed & 0xFF;
usb_buf[0x0C] = 0x64;
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev_pkt_0x11, usb_buf, 20);
hid_read(dev_pkt_0x11, usb_buf, 20);
}
@@ -1,102 +0,0 @@
/*---------------------------------------------------------*\
| LogitechGProController.h |
| |
| Driver for Logitech G Pro keyboard |
| |
| sanchezzzs 20 Oct 2021 |
| |
| 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"
enum
{
LOGITECH_GPRO_ZONE_MODE_KEYBOARD = 0x00,
LOGITECH_GPRO_ZONE_MODE_LOGO = 0x01,
};
enum
{
LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD = 0x01,
LOGITECH_GPRO_ZONE_DIRECT_MEDIA = 0x02,
LOGITECH_GPRO_ZONE_DIRECT_LOGO = 0x10,
LOGITECH_GPRO_ZONE_DIRECT_INDICATORS = 0x40,
};
enum
{
LOGITECH_GPRO_MODE_OFF = 0x00,
LOGITECH_GPRO_MODE_STATIC = 0x01,
LOGITECH_GPRO_MODE_BREATHING = 0x02,
LOGITECH_GPRO_MODE_CYCLE = 0x03,
LOGITECH_GPRO_MODE_WAVE = 0x04,
};
/*---------------------------------------------------------------------------------------------*\
| Speed is 1000 for fast and 20000 for slow. |
| Values are multiplied by 100 later to give lots of GUI steps. |
\*---------------------------------------------------------------------------------------------*/
enum
{
LOGITECH_GPRO_SPEED_SLOWEST = 0xC8, /* Slowest speed */
LOGITECH_GPRO_SPEED_NORMAL = 0x32, /* Normal speed */
LOGITECH_GPRO_SPEED_FASTEST = 0x0A, /* Fastest speed */
};
class LogitechGProKeyboardController
{
public:
LogitechGProKeyboardController(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name);
~LogitechGProKeyboardController();
std::string GetNameString();
std::string GetSerialString();
void Commit();
void SetDirect
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
);
void SetMode
(
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
private:
hid_device* dev_pkt_0x11;
hid_device* dev_pkt_0x12;
std::string name;
void SendDirectFrame
(
unsigned char zone,
unsigned char frame_count,
unsigned char * frame_data
);
void SendMode
(
unsigned char zone,
unsigned char mode,
unsigned short speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SendCommit();
};
@@ -1,356 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_LogitechGPro.cpp |
| |
| RGBController for Logitech G Pro keyboard |
| |
| sanchezzzs 20 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_LogitechGProKeyboard.h"
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[7][19] =
{ { 89, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 93, 92, NA, NA, 91, NA, 90 },
{ 37, NA, 54, 55, 56, 57, NA, 58, 59, 60, 61, NA, 62, 63, 64, 65, 66, 67, 68 },
{ 49, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, NA, 41, 42, 38, NA, 69, 70, 71 },
{ 39, NA, 16, 22, 4, 17, NA, 19, 24, 20, 8, 14, 15, 43, 44, 45, 72, 73, 74 },
{ 53, NA, 0, 18, 3, 5, NA, 6, 7, 9, 10, 11, 47, 48, 46, 36, NA, NA, NA },
{ 82, 79, 25, 23, 2, 21, NA, 1, NA, 13, 12, 50, 51, 52, 86, NA, NA, 78, NA },
{ 81, 84, 83, NA, NA, NA, NA, 40, NA, NA, NA, NA, 87, 88, 80, 85, 76, 77, 75 } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
94,
};
typedef struct
{
const char * name;
const unsigned char zone;
const unsigned char idx;
} led_type;
static const led_type led_names[] =
{
/* Key Label Zone, Index */
{ KEY_EN_A, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x04 },//00
{ KEY_EN_B, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x05 },
{ KEY_EN_C, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x06 },
{ KEY_EN_D, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x07 },
{ KEY_EN_E, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x08 },
{ KEY_EN_F, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x09 },
{ KEY_EN_G, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x0A },
{ KEY_EN_H, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x0B },
{ KEY_EN_I, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x0C },
{ KEY_EN_J, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x0D },
{ KEY_EN_K, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x0E },//10
{ KEY_EN_L, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x0F },
{ KEY_EN_M, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x10 },
{ KEY_EN_N, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x11 },
{ KEY_EN_O, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x12 },
{ KEY_EN_P, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x13 },
{ KEY_EN_Q, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x14 },
{ KEY_EN_R, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x15 },
{ KEY_EN_S, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x16 },
{ KEY_EN_T, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x17 },
{ KEY_EN_U, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x18 },//20
{ KEY_EN_V, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x19 },
{ KEY_EN_W, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x1A },
{ KEY_EN_X, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x1B },
{ KEY_EN_Y, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x1C },
{ KEY_EN_Z, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x1D },
{ KEY_EN_1, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x1E },
{ KEY_EN_2, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x1F },
{ KEY_EN_3, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x20 },
{ KEY_EN_4, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x21 },
{ KEY_EN_5, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x22 },//30
{ KEY_EN_6, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x23 },
{ KEY_EN_7, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x24 },
{ KEY_EN_8, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x25 },
{ KEY_EN_9, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x26 },
{ KEY_EN_0, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x27 },
{ KEY_EN_ANSI_ENTER, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x28 },
{ KEY_EN_ESCAPE, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x29 },
{ KEY_EN_BACKSPACE, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x2A },
{ KEY_EN_TAB, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x2B },
{ KEY_EN_SPACE, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x2C },//40
{ KEY_EN_MINUS, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x2D },
{ KEY_EN_EQUALS, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x2E },
{ KEY_EN_LEFT_BRACKET, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x2F },
{ KEY_EN_RIGHT_BRACKET, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x30 },
{ KEY_EN_ANSI_BACK_SLASH, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x31 },//ANSI only
{ KEY_EN_POUND, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x32 },//ISO only
{ KEY_EN_SEMICOLON, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x33 },
{ KEY_EN_QUOTE, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x34 },
{ KEY_EN_BACK_TICK, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x35 },
{ KEY_EN_COMMA, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x36 },//50
{ KEY_EN_PERIOD, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x37 },
{ KEY_EN_FORWARD_SLASH, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x38 },
{ KEY_EN_CAPS_LOCK, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x39 },
{ KEY_EN_F1, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x3A },
{ KEY_EN_F2, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x3B },
{ KEY_EN_F3, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x3C },
{ KEY_EN_F4, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x3D },
{ KEY_EN_F5, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x3E },
{ KEY_EN_F6, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x3F },
{ KEY_EN_F7, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x40 },//60
{ KEY_EN_F8, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x41 },
{ KEY_EN_F9, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x42 },
{ KEY_EN_F10, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x43 },
{ KEY_EN_F11, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x44 },
{ KEY_EN_F12, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x45 },
{ KEY_EN_PRINT_SCREEN, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x46 },
{ KEY_EN_SCROLL_LOCK, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x47 },
{ KEY_EN_PAUSE_BREAK, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x48 },
{ KEY_EN_INSERT, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x49 },
{ KEY_EN_HOME, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x4A },//70
{ KEY_EN_PAGE_UP, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x4B },
{ KEY_EN_DELETE, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x4C },
{ KEY_EN_END, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x4D },
{ KEY_EN_PAGE_DOWN, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x4E },
{ KEY_EN_RIGHT_ARROW, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x4F },
{ KEY_EN_LEFT_ARROW, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x50 },
{ KEY_EN_DOWN_ARROW, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x51 },
{ KEY_EN_UP_ARROW, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x52 },
{ KEY_EN_ISO_BACK_SLASH, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x64 },//ISO only
{ KEY_EN_MENU, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0x65 },//80
{ KEY_EN_LEFT_CONTROL, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE0 },
{ KEY_EN_LEFT_SHIFT, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE1 },
{ KEY_EN_LEFT_ALT, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE2 },
{ KEY_EN_LEFT_WINDOWS, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE3 },
{ KEY_EN_RIGHT_CONTROL, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE4 },
{ KEY_EN_RIGHT_SHIFT, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE5 },
{ KEY_EN_RIGHT_ALT, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE6 },
{ KEY_EN_RIGHT_FUNCTION, LOGITECH_GPRO_ZONE_DIRECT_KEYBOARD, 0xE7 },
{ "Logo", LOGITECH_GPRO_ZONE_DIRECT_LOGO, 0x01 },
{ "Lighting", LOGITECH_GPRO_ZONE_DIRECT_INDICATORS, 0x01 },//90
{ "Game Mode", LOGITECH_GPRO_ZONE_DIRECT_INDICATORS, 0x02 },
{ "Caps Lock Indicator", LOGITECH_GPRO_ZONE_DIRECT_INDICATORS, 0x03 },
{ "Scroll Lock Indicator", LOGITECH_GPRO_ZONE_DIRECT_INDICATORS, 0x04 },//93
};
/**------------------------------------------------------------------*\
@name Logitech G Pro
@category Keyboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectLogitechKeyboardGPro
@comment
\*-------------------------------------------------------------------*/
RGBController_LogitechGProKeyboard::RGBController_LogitechGProKeyboard(LogitechGProKeyboardController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "Logitech";
type = DEVICE_TYPE_KEYBOARD;
description = "Logitech Keyboard Device";
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);
mode Static;
Static.name = "Static";
Static.value = LOGITECH_GPRO_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Static.colors_min = 1;
Static.colors_max = 1;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.colors.resize(1);
modes.push_back(Static);
mode Off;
Off.name = "Off";
Off.value = LOGITECH_GPRO_MODE_OFF;
Off.flags = 0;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Cycle;
Cycle.name = "Cycle";
Cycle.value = LOGITECH_GPRO_MODE_CYCLE;
Cycle.flags = MODE_FLAG_HAS_SPEED;
Cycle.color_mode = MODE_COLORS_NONE;
Cycle.speed_min = LOGITECH_GPRO_SPEED_SLOWEST;
Cycle.speed_max = LOGITECH_GPRO_SPEED_FASTEST;
Cycle.speed = LOGITECH_GPRO_SPEED_NORMAL;
modes.push_back(Cycle);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = LOGITECH_GPRO_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.colors.resize(1);
Breathing.speed_min = LOGITECH_GPRO_SPEED_SLOWEST;
Breathing.speed_max = LOGITECH_GPRO_SPEED_FASTEST;
Breathing.speed = LOGITECH_GPRO_SPEED_NORMAL;
modes.push_back(Breathing);
SetupZones();
}
RGBController_LogitechGProKeyboard::~RGBController_LogitechGProKeyboard()
{
Shutdown();
delete controller;
}
void RGBController_LogitechGProKeyboard::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.Set(7, 19, (unsigned int *)&matrix_map);
}
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].name;
new_led.value = ( led_names[led_idx].zone << 8 ) + led_names[led_idx].idx;
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_LogitechGProKeyboard::DeviceUpdateLEDs()
{
#define MAX_FRAMES_PER_PACKET 0x0E
unsigned char frame_buf[MAX_FRAMES_PER_PACKET * 4];
unsigned char frame_cnt = 0;
unsigned char prev_zone = 0;
unsigned char zone = 0;
unsigned char idx = 0;
/*---------------------------------------------------------*\
| TODO: Send packets with multiple LED frames |
\*---------------------------------------------------------*/
for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++)
{
zone = ( leds[led_idx].value >> 8 );
idx = ( leds[led_idx].value & 0xFF );
if((zone != prev_zone) && (frame_cnt != 0))
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
frame_cnt = 0;
}
frame_buf[(frame_cnt * 4) + 0] = idx;
frame_buf[(frame_cnt * 4) + 1] = RGBGetRValue(colors[led_idx]);
frame_buf[(frame_cnt * 4) + 2] = RGBGetGValue(colors[led_idx]);
frame_buf[(frame_cnt * 4) + 3] = RGBGetBValue(colors[led_idx]);
frame_cnt++;
prev_zone = zone;
if(frame_cnt == MAX_FRAMES_PER_PACKET)
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
frame_cnt = 0;
}
}
if(frame_cnt != 0)
{
controller->SetDirect(prev_zone, frame_cnt, frame_buf);
}
controller->Commit();
}
void RGBController_LogitechGProKeyboard::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_LogitechGProKeyboard::DeviceUpdateSingleLED(int led)
{
unsigned char frame[4];
unsigned char zone;
unsigned char idx;
zone = ( leds[led].value >> 8 );
idx = ( leds[led].value & 0xFF );
frame[0] = idx;
frame[1] = RGBGetRValue(colors[led]);
frame[2] = RGBGetGValue(colors[led]);
frame[3] = RGBGetBValue(colors[led]);
controller->SetDirect(zone, 1, frame);
controller->Commit();
}
void RGBController_LogitechGProKeyboard::DeviceUpdateMode()
{
/*---------------------------------------------------------*\
| Direct mode does not send a mode packet |
| Call UpdateLEDs to send direct packet |
\*---------------------------------------------------------*/
if(active_mode == 0xFFFF)
{
UpdateLEDsInternal();
return;
}
unsigned char red = 0;
unsigned char grn = 0;
unsigned char blu = 0;
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
red = RGBGetRValue(modes[active_mode].colors[0]);
grn = RGBGetGValue(modes[active_mode].colors[0]);
blu = RGBGetBValue(modes[active_mode].colors[0]);
}
controller->SetMode(modes[active_mode].value, modes[active_mode].speed, red, grn, blu);
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_LogitechGPro.h |
| |
| RGBController for Logitech G Pro keyboard |
| |
| sanchezzzs 20 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "LogitechGProKeyboardController.h"
class RGBController_LogitechGProKeyboard : public RGBController
{
public:
RGBController_LogitechGProKeyboard(LogitechGProKeyboardController* controller_ptr);
~RGBController_LogitechGProKeyboard();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
LogitechGProKeyboardController* controller;
};
@@ -922,23 +922,6 @@ bool LogitechHIDPP20Controller::PrefersShortFrame(size_t len) const
#endif
}
/*---------------------------------------------------------*\
| Outgoing frame as hex, for trace-level wire comparison. |
\*---------------------------------------------------------*/
static std::string hex_frame(const uint8_t* buf, size_t len)
{
std::string out;
char byte[4];
for(size_t i = 0; i < len; i++)
{
snprintf(byte, sizeof(byte), "%02X ", buf[i]);
out += byte;
}
return out;
}
int LogitechHIDPP20Controller::SendStandard
(
uint8_t feat_idx,
@@ -1011,11 +994,6 @@ int LogitechHIDPP20Controller::SendStandard
result = hid_write(dev, buf, msg_len);
}
if(LogManager::get()->GetLogLevel() >= LL_TRACE)
{
LOG_TRACE("%s TX %s(result=%d)", LOG_TAG, hex_frame(buf, msg_len).c_str(), result);
}
/*-----------------------------------------------------*\
| A collection with no short report rejects the 0x10 |
| write (G560, G933). Resend as long and stay long. |
@@ -1043,11 +1021,6 @@ int LogitechHIDPP20Controller::SendStandard
result = hid_write(dev, buf, LOGITECH_LONG_MESSAGE_LEN);
}
if(LogManager::get()->GetLogLevel() >= LL_TRACE)
{
LOG_TRACE("%s TX %s(result=%d)", LOG_TAG, hex_frame(buf, LOGITECH_LONG_MESSAGE_LEN).c_str(), result);
}
if(result >= 0)
{
LOG_DEBUG("%s Short report rejected, using long frames", LOG_TAG);
@@ -1199,9 +1172,6 @@ int LogitechHIDPP20Controller::ReadStandardDirect
{
if(response.device_index != device_index)
{
LOG_TRACE("%s ReadStandardDirect: dropping frame for index 0x%02X (ours 0x%02X)",
LOG_TAG, response.device_index, device_index);
if(++drained > HIDPP20_READ_DRAIN_BUDGET)
{
LOG_DEBUG("%s ReadStandardDirect: drain budget (%d) exceeded",
@@ -4829,18 +4799,9 @@ int LogitechHIDPP20Controller::ProcessOnePerKeyResponse(int timeout_ms, uint8_t
{
/*-------------------------------------------------*\
| Echo format unknown for this function, count |
| it toward the group, and log the payload so a |
| real run teaches us what the firmware echoes. |
| it toward the group. |
\*-------------------------------------------------*/
frame_unmatched_acks[resp_func & 0xF0]++;
char hex[16 * 3 + 1];
for(int b = 0; b < 16; b++)
{
snprintf(&hex[b * 3], 4, "%02X ", resp_data[b]);
}
LOG_TRACE("%s per-key ACK echo unmatched func=0x%02X data=[%s]",
LOG_TAG, resp_func, hex);
}
return 1;
@@ -4902,11 +4863,6 @@ void LogitechHIDPP20Controller::SubmitPerKeyFrame(const std::vector<RGBColor>& f
{
std::lock_guard<std::mutex> lock(pending_frame_mutex);
if(pending_frame_valid)
{
pending_frames_skipped++;
}
pending_frame = frame;
pending_frame_valid = true;
}
@@ -4919,7 +4875,6 @@ void LogitechHIDPP20Controller::SenderThreadFunc()
while(sender_running.load())
{
std::vector<RGBColor> frame;
uint32_t skipped = 0;
{
std::unique_lock<std::mutex> lock(pending_frame_mutex);
@@ -4934,15 +4889,8 @@ void LogitechHIDPP20Controller::SenderThreadFunc()
return;
}
frame = std::move(pending_frame);
pending_frame_valid = false;
skipped = pending_frames_skipped;
pending_frames_skipped = 0;
}
if(skipped > 0)
{
LOG_TRACE("%s sender skipped %u stale frame(s)", LOG_TAG, skipped);
frame = std::move(pending_frame);
pending_frame_valid = false;
}
/*-------------------------------------------------*\
@@ -5437,6 +5385,7 @@ PerKeyFrameResult LogitechHIDPP20Controller::PerKeyFrameEnd()
if(lost > 0)
{
perkey_clean_frames = 0;
perkey_acks_lost += lost;
if(perkey_window > HIDPP20_PERKEY_WINDOW_MIN)
{
@@ -5446,9 +5395,6 @@ PerKeyFrameResult LogitechHIDPP20Controller::PerKeyFrameEnd()
{
perkey_window = HIDPP20_PERKEY_WINDOW_MIN;
}
LOG_DEBUG("%s %zu write ACK(s) lost, write window now %zu",
LOG_TAG, lost, perkey_window);
}
}
else if(perkey_window < HIDPP20_PERKEY_WINDOW_MAX &&
@@ -5472,34 +5418,55 @@ PerKeyFrameResult LogitechHIDPP20Controller::PerKeyFrameEnd()
DrainStaleResponses();
}
/*-----------------------------------------------------*\
| Link quality. A lost ACK or an unfinished frame is |
| the link's normal backpressure and the next frame |
| resends what did not land, so single frames are not |
| logged. Counts are summarized once per interval, |
| and only when something was lost. |
\*-----------------------------------------------------*/
if(!result.attempted_zones.empty())
{
std::chrono::steady_clock::time_point frame_done = std::chrono::steady_clock::now();
perkey_frames_seen++;
int send_ms = (int)std::chrono::duration_cast<std::chrono::milliseconds>(
send_done - frame_first_write).count();
int ack_ms = (int)std::chrono::duration_cast<std::chrono::milliseconds>(
acks_done - send_done).count();
int fe_ms = (int)std::chrono::duration_cast<std::chrono::milliseconds>(
frame_done - acks_done).count();
if(complete)
if(frame_aborted)
{
LOG_TRACE("%s frame committed: %zu zones, %zu packets (%zu echo-matched) "
"send=%dms ack=%dms fe=%dms pred=%ums busy=%d win=%zu",
LOG_TAG, result.attempted_zones.size(), frame_packets.size(),
frame_exact_acks, send_ms, ack_ms, fe_ms, predicted_ms, busy_polls,
perkey_window);
perkey_frames_aborted++;
}
else
else if(!complete)
{
LOG_DEBUG("%s frame %s: %zu/%zu zones acked (%zu packets, %zu echo-matched), "
"frame_end=%d, send=%dms ack=%dms fe=%dms pred=%ums busy=%d win=%zu",
LOG_TAG, frame_aborted ? "aborted" : "partial",
result.acked_zones.size(), result.attempted_zones.size(),
frame_packets.size(), frame_exact_acks,
(int)result.frame_end_acked, send_ms, ack_ms, fe_ms, predicted_ms,
busy_polls, perkey_window);
perkey_frames_partial++;
}
if(!result.frame_end_acked)
{
perkey_frames_no_end++;
}
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
if(perkey_summary_time == std::chrono::steady_clock::time_point())
{
perkey_summary_time = now;
}
else if(now - perkey_summary_time >= std::chrono::seconds(HIDPP20_PERKEY_SUMMARY_S))
{
if(perkey_frames_partial > 0 || perkey_frames_aborted > 0 ||
perkey_frames_no_end > 0 || perkey_acks_lost > 0)
{
LOG_DEBUG("%s per-key link, last %ds: %zu frames, %zu partial, %zu aborted, "
"%zu without FrameEnd ack, %zu ACKs lost, window %zu",
LOG_TAG, HIDPP20_PERKEY_SUMMARY_S, perkey_frames_seen,
perkey_frames_partial, perkey_frames_aborted,
perkey_frames_no_end, perkey_acks_lost, perkey_window);
}
perkey_frames_seen = 0;
perkey_frames_partial = 0;
perkey_frames_aborted = 0;
perkey_frames_no_end = 0;
perkey_acks_lost = 0;
perkey_summary_time = now;
}
}
@@ -5855,15 +5822,6 @@ void LogitechHIDPP20Controller::SetZoneEffect
\*-----------------------------------------------------*/
data[12] = persist ? 0x01 : 0x00;
LOG_DEBUG("%s SetEffect cluster=%u idx=%u id=0x%04X "
"data=[%02X %02X %02X %02X %02X %02X %02X %02X "
"%02X %02X %02X %02X %02X %02X %02X %02X]",
LOG_TAG, cluster_idx, effect_idx, effect_id,
data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11],
data[12], data[13], data[14], data[15]);
blankFAPmessage response;
SendAckedIntoFAP(caps.idx_rgb_effects, caps.fn_set_effect,
data, 16, response);
@@ -5951,9 +5909,6 @@ void LogitechHIDPP20Controller::SetHeadsetRGBHostmodeColors
uint8_t frame_end[4] = { 0x01, 0x00, 0x00, 0x00 };
SendAckedIntoFAP(caps.idx_headset_rgb_hostmode, FN_0620_FRAME_END,
frame_end, sizeof(frame_end), response);
LOG_TRACE("%s 0x0620 wrote %zu zone(s) in %zu color group(s), FrameEnd[0x01]",
LOG_TAG, zones.size(), groups.size());
}
/*---------------------------------------------------------*\
@@ -7604,7 +7559,8 @@ void LogitechHIDPP20Controller::ReadActiveProfileSector()
}
constexpr uint16_t SECTOR_SIZE = 0x63; // 99 bytes
constexpr uint16_t PAGE_SIZE = 16;
constexpr uint16_t SIZE_OF_PAGE = 16;
/*-----------------------------------------------------*\
| Step 1: load the sector into the device's read buffer |
@@ -7630,7 +7586,7 @@ void LogitechHIDPP20Controller::ReadActiveProfileSector()
\*-----------------------------------------------------*/
uint8_t sector_buf[SECTOR_SIZE] = {};
for(uint16_t offset = 0; offset < SECTOR_SIZE; offset += PAGE_SIZE)
for(uint16_t offset = 0; offset < SECTOR_SIZE; offset += SIZE_OF_PAGE)
{
uint8_t read_req[3] = {
(uint8_t)((offset >> 8) & 0xFF),
@@ -7650,9 +7606,9 @@ void LogitechHIDPP20Controller::ReadActiveProfileSector()
return;
}
size_t copy_len = (offset + PAGE_SIZE > SECTOR_SIZE)
size_t copy_len = (offset + SIZE_OF_PAGE > SECTOR_SIZE)
? (size_t)(SECTOR_SIZE - offset)
: PAGE_SIZE;
: SIZE_OF_PAGE;
memcpy(sector_buf + offset, page_resp, copy_len);
}
@@ -7662,11 +7618,11 @@ void LogitechHIDPP20Controller::ReadActiveProfileSector()
LOG_DEBUG("%s ProfileSector partition=NVS sector=1 size=%u bytes:",
LOG_TAG, (unsigned)SECTOR_SIZE);
for(uint16_t row = 0; row < SECTOR_SIZE; row += PAGE_SIZE)
for(uint16_t row = 0; row < SECTOR_SIZE; row += SIZE_OF_PAGE)
{
size_t row_len = (row + PAGE_SIZE > SECTOR_SIZE)
size_t row_len = (row + SIZE_OF_PAGE > SECTOR_SIZE)
? (size_t)(SECTOR_SIZE - row)
: PAGE_SIZE;
: SIZE_OF_PAGE;
char hex[64] = {};
char* p = hex;
@@ -510,6 +510,7 @@ static constexpr size_t HIDPP20_PERKEY_WINDOW_MAX = 8;
static constexpr size_t HIDPP20_PERKEY_WINDOW_MIN = 2;
static constexpr uint16_t HIDPP20_PERKEY_ACK_WAIT_MS = 60;
static constexpr uint16_t HIDPP20_PERKEY_ACK_TAIL_MS = 25;
static constexpr int HIDPP20_PERKEY_SUMMARY_S = 60;
static constexpr uint8_t HIDPP20_PERKEY_WINDOW_GROW_AFTER = 16;
/*---------------------------------------------------------*\
@@ -1243,6 +1244,17 @@ private:
size_t perkey_window = HIDPP20_PERKEY_WINDOW_MAX;
uint8_t perkey_clean_frames = 0;
/*-----------------------------------------------------*\
| Link quality counters, logged as one summary at most |
| once per HIDPP20_PERKEY_SUMMARY_S. |
\*-----------------------------------------------------*/
size_t perkey_frames_seen = 0;
size_t perkey_frames_partial = 0;
size_t perkey_frames_aborted = 0;
size_t perkey_frames_no_end = 0;
size_t perkey_acks_lost = 0;
std::chrono::steady_clock::time_point perkey_summary_time;
void ResetPerKeyFrameState();
/*-----------------------------------------------------*\
@@ -1293,7 +1305,6 @@ private:
std::condition_variable pending_frame_cv;
std::vector<RGBColor> pending_frame;
bool pending_frame_valid = false;
uint32_t pending_frames_skipped = 0;
/*-----------------------------------------------------*\
| Callbacks |
@@ -329,6 +329,10 @@ static const std::map<uint16_t, std::string> hidpp20_extras_names =
{ 182, "G3" },
{ 183, "G4" },
{ 184, "G5" },
{ 185, "G6" },
{ 186, "G7" },
{ 187, "G8" },
{ 188, "G9" },
{ 210, "Logo" },
};
@@ -423,9 +427,39 @@ static const keyboard_led proxrapid_top_strip[] =
{ 0, 0, 13, 153, "Media Mute", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above F12 */
};
/*---------------------------------------------------------*\
| G915 X Wired top strip and G-key column: INSERT_ROW adds |
| row 0 above the F-row, the rest INSERT_SHIFT_RIGHT into |
| it. G1-G5 insert at column 0 of the main rows; the unused |
| key at the F-row's column 0 shifts that row right so it |
| stays aligned with them. Zone ids hardware-probed on this |
| board. Game Mode (above F5) is a non-RGB toggle, so none |
| is listed. |
\*---------------------------------------------------------*/
static const keyboard_led g915x_strip_and_gkeys[] =
{
{ 0, 0, 0, 210, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW },
{ 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* shift the F-row */
{ 0, 2, 0, 180, "G1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT },
{ 0, 3, 0, 181, "G2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT },
{ 0, 4, 0, 182, "G3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT },
{ 0, 5, 0, 183, "G4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT },
{ 0, 6, 0, 184, "G5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT },
{ 0, 0, 3, 185, "G6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above F1 */
{ 0, 0, 4, 186, "G7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above F2 */
{ 0, 0, 5, 187, "G8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above F3 */
{ 0, 0, 6, 188, "G9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above F4 */
{ 0, 0, 8, 153, "Brightness", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above F6 */
{ 0, 0, 18, 158, "Media Previous", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above Num Lock */
{ 0, 0, 19, 155, "Media Play/Pause", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above Numpad / */
{ 0, 0, 20, 157, "Media Next", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above Numpad * */
{ 0, 0, 21, 156, "Media Mute", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* above Numpad - */
};
static const KbLayoutEdit known_kb_layout_edits[] =
{
{ 0xC35B, proxrapid_top_strip, 5 }, /* PRO X RAPID */
{ 0xC35B, proxrapid_top_strip, 5 }, /* PRO X RAPID */
{ 0xC359, g915x_strip_and_gkeys, 16 }, /* G915 X Wired */
};
static key_set FindKbLayoutEdit(uint16_t pid_wired, uint16_t pid_wireless)
@@ -804,9 +838,10 @@ static const keyboard_led g512_top_strip[] =
| legacy map: the media cluster above the numpad (on/off |
| backlight, not RGB; the firmware still advertises media |
| keyType 0x02, see the C32B quirk) and the four small |
| mode keys left of G6, which nothing has identified yet. |
| If firmware enumerates any of these they surface in |
| Extras (suppression is off for this board). |
| mode keys left of G6. Painting the advertised extras |
| controls nothing (hardware-observed), so unclaimed ids |
| are suppressed as phantoms; the plugin's Show Unmapped |
| override surfaces them for auditing. |
\*---------------------------------------------------------*/
static const keyboard_led g910_side_strip[] =
{
@@ -831,15 +866,15 @@ static const keyboard_led g910_side_strip[] =
\*---------------------------------------------------------*/
static const Kb8080Strip known_kb_8080_strips[] =
{
{ 0xC331, true, g810_top_strip, 11, false }, /* G810 */
{ 0xC337, true, g810_top_strip, 11, false }, /* G810 */
{ 0xC333, true, g810_top_strip, 11, false }, /* G610 */
{ 0xC338, true, g810_top_strip, 11, false }, /* G610 */
{ 0xC331, true, g810_top_strip, 11, true }, /* G810 */
{ 0xC337, true, g810_top_strip, 11, true }, /* G810 */
{ 0xC333, true, g810_top_strip, 11, true }, /* G610 */
{ 0xC338, true, g810_top_strip, 11, true }, /* G610 */
{ 0xC342, true, g512_top_strip, 2, true }, /* G512 */
{ 0xC33C, true, g512_top_strip, 2, true }, /* G512 RGB */
{ 0xC32B, true, g910_side_strip, 11, false }, /* G910 Orion Spark */
{ 0xC335, true, g910_side_strip, 11, false }, /* G910 */
{ 0xC339, false, gpro_top_strip, 5, false }, /* G Pro */
{ 0xC32B, true, g910_side_strip, 11, true }, /* G910 Orion Spark */
{ 0xC335, true, g910_side_strip, 11, true }, /* G910 */
{ 0xC339, false, gpro_top_strip, 5, true }, /* G Pro */
};
static const Kb8080Strip* FindKb8080Strip(uint16_t pid_wired, uint16_t pid_wireless)
@@ -855,9 +890,10 @@ static const Kb8080Strip* FindKb8080Strip(uint16_t pid_wired, uint16_t pid_wirel
return(nullptr);
}
RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Controller* controller_ptr)
RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Controller* controller_ptr, std::function<void ()> callback)
{
controller = controller_ptr;
shutdown_callback = callback;
const HIDPP20DeviceCapabilities& caps = controller->GetCapabilities();
@@ -988,6 +1024,27 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
{
const HIDPP20ZoneCluster& cluster = caps.zone_clusters[0];
/*-------------------------------------------------*\
| Per-LED effect colors: multi-cluster devices |
| whose only paint path is zone effects, one color |
| per cluster. Per-key devices take a single mode |
| color: the UI repaints per-key on any per-LED |
| mode set, which overwrites the zone effect. |
\*-------------------------------------------------*/
const bool per_led_colors = (caps.zone_clusters.size() > 1)
&& !caps.has_perkey
&& !PerKey8080Capable();
/*-------------------------------------------------*\
| 0x8070 keyboard firmware ignores the Cycle, Wave |
| and Breathing intensity byte (G810/G910 |
| hardware); the same slots drive brightness on |
| the mice. No slider for a dead control; the wire |
| still sends 100 in that slot. |
\*-------------------------------------------------*/
const bool effect_brightness = !(caps.rgb_feature_page == HIDPP20_FEAT_COLOR_LED_EFFECTS
&& caps.device_type == LOGITECH_DEVICE_TYPE_KEYBOARD);
for(size_t i = 0; i < cluster.effects.size(); i++)
{
const HIDPP20Effect& fx = cluster.effects[i];
@@ -1000,16 +1057,7 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
Static.name = "Static";
Static.value = fx.index;
/*-------------------------------------*\
| Multi-cluster devices (mice with |
| logo/scroll/DPI) get per-LED colors |
| so each zone can be painted |
| independently in Static. Single- |
| cluster devices (keyboards, single- |
| zone mice) keep the single-color |
| MODE_COLORS_MODE_SPECIFIC UX. |
\*-------------------------------------*/
if(caps.zone_clusters.size() > 1)
if(per_led_colors)
{
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Static.color_mode = MODE_COLORS_PER_LED;
@@ -1031,8 +1079,11 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
mode Cycle;
Cycle.name = "Spectrum Cycle";
Cycle.value = fx.index;
Cycle.flags = MODE_FLAG_HAS_SPEED
| MODE_FLAG_HAS_BRIGHTNESS;
Cycle.flags = MODE_FLAG_HAS_SPEED;
if(effect_brightness)
{
Cycle.flags |= MODE_FLAG_HAS_BRIGHTNESS;
}
Cycle.speed_min = HIDPP20_SPEED_SLIDER_MIN;
Cycle.speed_max = HIDPP20_SPEED_SLIDER_MAX;
Cycle.speed = 80; /* ~4.9s, lively medium */
@@ -1056,11 +1107,7 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
Breathing.brightness_max = 100;
Breathing.brightness = 100;
/*-------------------------------------*\
| See Static above, multi- |
| cluster gets per-LED colors. |
\*-------------------------------------*/
if(caps.zone_clusters.size() > 1)
if(per_led_colors)
{
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR
| MODE_FLAG_HAS_SPEED
@@ -1077,6 +1124,12 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.colors.resize(1);
}
if(!effect_brightness)
{
Breathing.flags &= ~MODE_FLAG_HAS_BRIGHTNESS;
}
modes.push_back(Breathing);
break;
}
@@ -1096,7 +1149,7 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
Visualizer.speed_max = HIDPP20_SPEED_SLIDER_MAX;
Visualizer.speed = 80; /* ~4.9s, near the 5s firmware default */
if(caps.zone_clusters.size() > 1)
if(per_led_colors)
{
Visualizer.flags = MODE_FLAG_HAS_PER_LED_COLOR
| MODE_FLAG_HAS_SPEED;
@@ -1120,8 +1173,11 @@ RGBController_LogitechHIDPP20::RGBController_LogitechHIDPP20(LogitechHIDPP20Cont
mode Wave;
Wave.name = "Color Wave";
Wave.value = fx.index;
Wave.flags = MODE_FLAG_HAS_SPEED
| MODE_FLAG_HAS_BRIGHTNESS;
Wave.flags = MODE_FLAG_HAS_SPEED;
if(effect_brightness)
{
Wave.flags |= MODE_FLAG_HAS_BRIGHTNESS;
}
Wave.speed_min = HIDPP20_SPEED_SLIDER_MIN;
Wave.speed_max = HIDPP20_SPEED_SLIDER_MAX;
Wave.speed = 80; /* ~4.9s, lively medium */
@@ -1346,6 +1402,11 @@ RGBController_LogitechHIDPP20::~RGBController_LogitechHIDPP20()
{
controller->StopPowerManager();
if(shutdown_callback)
{
shutdown_callback();
}
Shutdown();
delete controller;
@@ -15,7 +15,7 @@
class RGBController_LogitechHIDPP20 : public RGBController
{
public:
RGBController_LogitechHIDPP20(LogitechHIDPP20Controller* controller_ptr);
RGBController_LogitechHIDPP20(LogitechHIDPP20Controller* controller_ptr, std::function<void()> shutdown_callback);
~RGBController_LogitechHIDPP20();
void SetupZones();
@@ -116,4 +116,6 @@ private:
| Parallel to led_to_zone_id; 0x8080 path only. |
\*-----------------------------------------------------*/
std::vector<std::pair<uint16_t, uint8_t>> led_to_keytype_keyid_8080;
std::function<void()> shutdown_callback;
};
@@ -38,17 +38,24 @@ MSIMotherboard112Controller::MSIMotherboard112Controller(hid_device* handle, con
location = path;
name = dev_name;
if(dev)
{
ReadFwVersion();
ReadSettings();
}
/*-----------------------------------------------------*\
| Perform initial reads - get the controller's firmware |
| version and then read the controller's active |
| configuration data |
\*-----------------------------------------------------*/
ReadFwVersion();
ReadSettings();
/*-----------------------------------------------------*\
| Initialize save flag |
| The last byte of the packet is the save flag. This |
| byte is stored as a zero in the data flash, but is |
| set to 1 at the protocol level to tell the firmware |
| to save the active configuration to flash. |
| Also set onboard zone to act as sync master for all |
| of the onboard LEDs. |
\*-----------------------------------------------------*/
data.save_data = 0;
data.on_board_led.colorFlags = 0x81; // force MS bit of color flags to 1 to have expected zone control
data.save_data = 0;
data.on_board_led.colorFlags = MSI_COLOR_FLAG_USE_CUSTOM_COLOR | MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
/*-----------------------------------------------------*\
| Initialize zone based per LED data |
@@ -56,25 +63,25 @@ MSIMotherboard112Controller::MSIMotherboard112Controller(hid_device* handle, con
numof_onboard_leds = 7;
supported_zones = &zones_set;
zone_based_per_led_data.j_rgb_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rgb_1.colorFlags = BITSET(zone_based_per_led_data.j_rgb_1.colorFlags, true, 7u);
zone_based_per_led_data.j_rainbow_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rainbow_1.colorFlags = BITSET(zone_based_per_led_data.j_rainbow_1.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led.colorFlags = BITSET(zone_based_per_led_data.on_board_led.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_1.colorFlags = BITSET(zone_based_per_led_data.on_board_led_1.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_2.colorFlags = BITSET(zone_based_per_led_data.on_board_led_2.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_3.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_3.colorFlags = BITSET(zone_based_per_led_data.on_board_led_3.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_4.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_4.colorFlags = BITSET(zone_based_per_led_data.on_board_led_4.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_5.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_5.colorFlags = BITSET(zone_based_per_led_data.on_board_led_5.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_6.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2 << 2;
zone_based_per_led_data.on_board_led_6.colorFlags = BITSET(zone_based_per_led_data.on_board_led_6.colorFlags, true, 7u);
zone_based_per_led_data.save_data = 0;
zone_based_per_led_data.j_rgb_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_rgb_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.j_rainbow_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_rainbow_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_2.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_3.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_3.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_4.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_4.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_5.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_5.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_6.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_6.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.save_data = 0;
direct_mode = false;
}
@@ -93,29 +100,38 @@ void MSIMotherboard112Controller::SetMode
bool rainbow_color
)
{
/*-----------------------------------------------------*\
| Get the zone data pointer within the configuration |
| data buffer |
\*-----------------------------------------------------*/
ZoneData* zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
if (zone <= MSI_ZONE_ON_BOARD_LED_0)
if(zone <= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
zone_data->padding = 0x00;
if(mode > MSI_MODE_DOUBLE_FLASHING)
{
zone_data->speedAndBrightnessFlags |= SYNC_SETTING_JRGB;
zone_data->colorFlags |= SYNC_SETTING_ONBOARD;
zone_data->speedAndBrightnessFlags |= MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
zone_data->colorFlags |= MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
}
else
{
zone_data->speedAndBrightnessFlags &= ~SYNC_SETTING_JRGB;
zone_data->colorFlags &= ~SYNC_SETTING_ONBOARD;
zone_data->speedAndBrightnessFlags &= ~MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
zone_data->colorFlags &= ~MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
}
}
@@ -126,8 +142,10 @@ void MSIMotherboard112Controller::SetMode
if(zone_data != nullptr)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
zone_data->padding = 0x00;
}
}
@@ -201,14 +219,21 @@ void MSIMotherboard112Controller::SetZoneColor
unsigned char blu2
)
{
/*-----------------------------------------------------*\
| Get the zone data pointer within the configuration |
| data buffer |
\*-----------------------------------------------------*/
ZoneData* zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
if (zone <= MSI_ZONE_ON_BOARD_LED_0)
if(zone <= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data->color.R = red1;
zone_data->color.G = grn1;
@@ -410,10 +435,10 @@ void MSIMotherboard112Controller::GetMode
/*-----------------------------------------------------*\
| Update pointers with data |
\*-----------------------------------------------------*/
mode = (MSI_MODE)zone_data->effect;
speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F);
rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false;
mode = (MSI_MODE) zone_data->effect;
speed = (MSI_SPEED) ((zone_data->speedAndBrightnessFlags >> MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK);
rainbow_color = ((zone_data->colorFlags & MSI_COLOR_FLAG_USE_CUSTOM_COLOR) == 0 ? false : true);
color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B);
}
@@ -85,24 +85,32 @@ MSIMotherboard162Controller::MSIMotherboard162Controller(hid_device* handle, con
location = path;
name = dev_name;
if(dev)
{
ReadFwVersion();
ReadSettings();
}
/*-----------------------------------------------------*\
| Initialize save flag |
| Perform initial reads - get the controller's firmware |
| version and then read the controller's active |
| configuration data |
\*-----------------------------------------------------*/
data.save_data = 0;
data.on_board_led.colorFlags = 0x81; // force MS bit of color flags to 1 to have expectd zone control
ReadFwVersion();
ReadSettings();
/*-----------------------------------------------------*\
| Initialize zone based per LED data |
| The last byte of the packet is the save flag. This |
| byte is stored as a zero in the data flash, but is |
| set to 1 at the protocol level to tell the firmware |
| to save the active configuration to flash. |
| Also set onboard zone to act as sync master for all |
| of the onboard LEDs. |
\*-----------------------------------------------------*/
data.save_data = 0;
data.on_board_led.colorFlags = MSI_COLOR_FLAG_USE_CUSTOM_COLOR | MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
/*-----------------------------------------------------*\
| Search for the board configuration matching this |
| board. |
\*-----------------------------------------------------*/
const mystic_light_162_config* board_config = nullptr;
for(std::size_t i = 0; i < NUMOF_CONFIGS; ++i)
for(std::size_t i = 0; i < NUMOF_CONFIGS; i++)
{
if (board_configs[i].pid == pid)
{
@@ -111,6 +119,10 @@ MSIMotherboard162Controller::MSIMotherboard162Controller(hid_device* handle, con
}
}
/*-----------------------------------------------------*\
| Fill in the number of each zone type based on the |
| board configuration |
\*-----------------------------------------------------*/
if(board_config != nullptr)
{
numof_onboard_leds = board_config->numof_onboard_leds;
@@ -137,29 +149,38 @@ void MSIMotherboard162Controller::SetMode
bool rainbow_color
)
{
/*-----------------------------------------------------*\
| Get the zone data pointer within the configuration |
| data buffer |
\*-----------------------------------------------------*/
ZoneData* zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
if (zone <= MSI_ZONE_ON_BOARD_LED_0)
if(zone <= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
zone_data->padding = 0x00;
if(mode > MSI_MODE_DOUBLE_FLASHING)
{
zone_data->speedAndBrightnessFlags |= SYNC_SETTING_JRGB;
zone_data->colorFlags |= SYNC_SETTING_ONBOARD;
zone_data->speedAndBrightnessFlags |= MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
zone_data->colorFlags |= MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
}
else
{
zone_data->speedAndBrightnessFlags &= ~SYNC_SETTING_JRGB;
zone_data->colorFlags &= ~SYNC_SETTING_ONBOARD;
zone_data->speedAndBrightnessFlags &= ~MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
zone_data->colorFlags &= ~MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
}
}
@@ -170,8 +191,10 @@ void MSIMotherboard162Controller::SetMode
if(zone_data != nullptr)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
zone_data->padding = 0x00;
}
}
@@ -238,14 +261,21 @@ void MSIMotherboard162Controller::SetZoneColor
unsigned char blu2
)
{
/*-----------------------------------------------------*\
| Get the zone data pointer within the configuration |
| data buffer |
\*-----------------------------------------------------*/
ZoneData* zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
if (zone <= MSI_ZONE_ON_BOARD_LED_0)
if(zone <= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data->color.R = red1;
zone_data->color.G = grn1;
@@ -431,10 +461,10 @@ void MSIMotherboard162Controller::GetMode
/*-----------------------------------------------------*\
| Update pointers with data |
\*-----------------------------------------------------*/
mode = (MSI_MODE)zone_data->effect;
speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F);
rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false;
mode = (MSI_MODE) zone_data->effect;
speed = (MSI_SPEED) ((zone_data->speedAndBrightnessFlags >> MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK);
rainbow_color = ((zone_data->colorFlags & MSI_COLOR_FLAG_USE_CUSTOM_COLOR) == 0 ? false : true);
color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B);
}
@@ -33,18 +33,19 @@ using namespace std::chrono_literals;
#define JCORSAIR_MAX_LED_COUNT 240
#define MSI_DIRECT_MODE 0x25
#define PER_LED_BASIC_SYNC_MODE (0x80 | SYNC_SETTING_ONBOARD | SYNC_SETTING_JPIPE1 | SYNC_SETTING_JPIPE2)
#define PER_LED_FULL_SYNC_MODE (PER_LED_BASIC_SYNC_MODE | SYNC_SETTING_JRAINBOW1 | SYNC_SETTING_JRAINBOW2 | SYNC_SETTING_JCORSAIR)
#define PER_LED_BASIC_SYNC_MODE (MSI_COLOR_FLAG_USE_CUSTOM_COLOR | MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD | MSI_COLOR_FLAG_SYNC_SETTING_JPIPE1 | MSI_COLOR_FLAG_SYNC_SETTING_JPIPE2)
#define PER_LED_FULL_SYNC_MODE (PER_LED_BASIC_SYNC_MODE | MSI_COLOR_FLAG_SYNC_SETTING_JRAINBOW1 | MSI_COLOR_FLAG_SYNC_SETTING_JRAINBOW2 | MSI_COLOR_FLAG_SYNC_SETTING_JCORSAIR)
struct mystic_light_185_config
{
unsigned short pid; // PID of the board
int numof_onboard_leds; // number of onboard leds
int numof_pipe1_leds; // number of pipe 1 leds (used in per LED mode only)
int numof_pipe2_leds; // number of pipe 2 leds (used in per LED mode only)
int numof_JRGBs; // number of supported JRGB headers (used in per LED mode only)
const std::vector<MSI_ZONE>* supported_zones; // pointer to vector of supported zones
MSIMotherboard185Controller::DIRECT_MODE per_led_mode; // type of direct mode support
unsigned short pid; // PID of the board
int numof_onboard_leds; // number of onboard leds
int numof_pipe1_leds; // number of pipe 1 leds (used in per LED mode only)
int numof_pipe2_leds; // number of pipe 2 leds (used in per LED mode only)
int numof_JRGBs; // number of supported JRGB headers (used in per LED mode only)
const std::vector<MSI_ZONE>* supported_zones; // pointer to vector of supported zones
MSIMotherboard185Controller::DIRECT_MODE per_led_mode; // type of direct mode support
unsigned char minimum_firmware_version; // minimum required firmware version for this config (0 = all versions acceptable)
};
const std::vector<MSI_ZONE> all_zones =
@@ -257,104 +258,103 @@ const std::vector<MSI_ZONE> zones_set21 =
static const mystic_light_185_config board_configs[] =
{
{ 0x7B93, 6, 1, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // MPG X570 GAMING PRO CARBON WIFI
{ 0x7C34, 0, 1, 1, 1, &zones_set8, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // MEG X570 GODLIKE
{ 0x7C35, 0, 1, 0, 1, &zones_set9, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // MEG X570 ACE
{ 0x7C36, 6, 1, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // PRESTIGE X570 CREATION
{ 0x7C37, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // MPG X570 GAMING PLUS
{ 0x7C56, 6, 0, 0, 1, &zones_set2, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B550 GAMING PLUS
{ 0x7C59, 0, 8, 0, 1, &zones_set9, MSIMotherboard185Controller::DIRECT_MODE_DISABLED }, // CREATOR TRX40
{ 0x7C60, 6, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // TRX40-A PRO
{ 0x7C67, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B365M MORTAR
{ 0x7C71, 6, 6, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z490 ACE
{ 0x7C73, 6, 4, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z490 GAMING CARBON WIFI
{ 0x7C75, 6, 0, 0, 1, &zones_set2, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z490 GAMING PLUS
{ 0x7C76, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_DISABLED }, // MPG Z490M GAMING EDGE
{ 0x7C77, 0, 0, 0, 0, &zones_set14, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z490I UNIFY
{ 0x7C79, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z490 GAMING EDGE WIFI
{ 0x7C80, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG Z490 TOMAHAWK
{ 0x7C02, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B450 TOMAHAWK MAX
{ 0x7C81, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B460 TOMAHAWK
{ 0x7C82, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B460M MORTAR WIFI
{ 0x7C83, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_DISABLED }, // B460M PRO-VDH WIFI
{ 0x7C84, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // MAG X570 TOMAHAWK WIFI
{ 0x7C86, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_DISABLED }, // MPG B460I GAMING EDGE
{ 0x7C87, 6, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // B450M BAZOOKA MAX WIFI
{ 0x7C90, 6, 4, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B550 GAMING CARBON WIFI
{ 0x7C91, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B550 TOMAHAWK
{ 0x7C92, 6, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B550I GAMING EDGE WIFI
{ 0x7C94, 6, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B550M MORTAR
{ 0x7C95, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // B550M PRO-VDH WIFI
{ 0x7C98, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // Z490 PLUS
{ 0x7D03, 0, 15, 18, 1, &zones_set8, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z590 GODLIKE
{ 0x7D06, 4, 4, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z590 GAMING FORCE
{ 0x7D07, 4, 5, 0, 2, &zones_set7, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z590 GAMING EDGE WIFI
{ 0x7D08, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG Z590 TOMAHAWK
{ 0x7D09, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // Z590-A PRO WIFI
{ 0x7D13, 6, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG B550 UNIFY
{ 0x7D14, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // A520M PRO
{ 0x7D15, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B560 TOMAHAWK WIFI
{ 0x7D17, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B560M MORTAR
{ 0x7D18, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B560M PRO-VDH
{ 0x7D19, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B560I GAMIING EDGE WIFI
{ 0x7D20, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B560M PRO
{ 0x7D25, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO Z690-A WIFI DDR4
{ 0x7D27, 6, 0, 0, 2, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z690 ACE
{ 0x7D28, 6, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z690 UNIFY-X
{ 0x7D29, 6, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z690I UNIFY
{ 0x7D30, 6, 6, 0, 2, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z690 CARBON WIFI
{ 0x7D31, 4, 8, 0, 2, &zones_set12, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG EDGE WIFI DDR4
{ 0x7D32, 1, 0, 0, 1, &zones_set10, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG Z690 TOMAHAWK WIFI DDR4
{ 0x7D33, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-VC WIFI
{ 0x7D36, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO Z690-P DDR4
{ 0x7D37, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B760M-VC WIFI (MS-7D37) - fans on JRAINBOW2
{ 0x7D38, 0, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z590 UNIFY-X
{ 0x7D40, 0, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B760i EDGE WIFI DDR4
{ 0x7D41, 6, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B660M TOMAHAWK WIFI DDR4
{ 0x7D42, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B660 MORTAR WIFI DDR4
{ 0x7D43, 0, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B660M-A WIFI DDR4
{ 0x7D46, 0, 1, 1, 0, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO H610M-G DDR4
{ 0x7D50, 6, 12, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG X570S ACE MAX
{ 0x7D51, 6, 0, 0, 2, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG X570S UNIFY-X MAX
{ 0x7D52, 6, 14, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG X570S CARBON EK X
{ 0x7D53, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG X570S EDGE MAX WIFI
{ 0x7D54, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG X570S TOMAHAWK MAX WIFI
{ 0x7D59, 0, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B660-A DDR4
{ 0x7D67, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO X670-P WIFI
{ 0x7D69, 9, 2, 4, 1, &zones_set15, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG X670E ACE
{ 0x7D70, 0, 6, 0, 1, &zones_set9, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG X670E Carbon WIFI
{ 0x7D73, 1, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B650I EDGE WIFI
{ 0x7D74, 0, 6, 0, 1, &zones_set18, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B650 CARBON WIFI
{ 0x7D75, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B650 TOMAHAWK WIFI
{ 0x7D76, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B650M MORTAR WIFI
{ 0x7D77, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-A WIFI
{ 0x7D78, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B650-P WIFI
{ 0x7D86, 0, 18, 4, 1, &zones_set16, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MEG Z790 ACE
{ 0x7D88, 0, 0, 0, 1, &zones_set20, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z790-S WIFI
{ 0x7D89, 0, 6, 0, 1, &zones_set18, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z790 CARBON WIFI
{ 0x7D90, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // B760M BOMBER DDR4
{ 0x7D91, 1, 0, 0, 1, &zones_set10, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG Z790 TOMAHAWK WIFI
{ 0x7D93, 6, 0, 0, 1, &zones_set2, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // Z790 GAMING PRO WIFI
{ 0x7D96, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B760 TOMAHAWK WIFI DDR5
{ 0x7D97, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B660 MORTAR MAX WIFI DDR4
{ 0x7D98, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B760-P WIFI DDR4
{ 0x7D99, 6, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B760M-A WIFI DDR4
{ 0x7E01, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG B760M MORTAR MAX
{ 0x7E03, 6, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG Z790I EDGE WIFI
{ 0x7E06, 0, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-P WIFI DDR4
{ 0x7E07, 0, 0, 0, 2, &zones_set10, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-A WIFI DDR4
{ 0x7E09, 0, 0, 0, 0, &zones_set19, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // B650M PROJECT ZERO
{ 0x7E10, 0, 6, 0, 2, &zones_set17, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MPG B650 EDGE WIFI
{ 0x7E12, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG X670E TOMAHAWK WIFI
{ 0x0076, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // MAG X670E TOMAHAWK WIFI (Common PID)
{ 0x7E16, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // X670E GAMING PLUS WIFI
{ 0x7E24, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // B650M GAMING PLUS WIFI
{ 0x7E26, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // B650 GAMING PLUS WIFI
{ 0x7E27, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-P
{ 0x7E28, 6, 0, 0, 2, &zones_set21, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO A620M-B (MS-7E28)
{ 0x7B93, 6, 1, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // MPG X570 GAMING PRO CARBON WIFI
{ 0x7C34, 0, 1, 1, 1, &zones_set8, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // MEG X570 GODLIKE
{ 0x7C35, 0, 1, 0, 1, &zones_set9, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // MEG X570 ACE
{ 0x7C36, 6, 1, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // PRESTIGE X570 CREATION
{ 0x7C37, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // MPG X570 GAMING PLUS
{ 0x7C56, 6, 0, 0, 1, &zones_set2, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 6 }, // MPG B550 GAMING PLUS
{ 0x7C59, 0, 8, 0, 1, &zones_set9, MSIMotherboard185Controller::DIRECT_MODE_DISABLED, 0 }, // CREATOR TRX40
{ 0x7C60, 6, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // TRX40-A PRO
{ 0x7C67, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B365M MORTAR
{ 0x7C71, 6, 6, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z490 ACE
{ 0x7C73, 6, 4, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z490 GAMING CARBON WIFI
{ 0x7C75, 6, 0, 0, 1, &zones_set2, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z490 GAMING PLUS
{ 0x7C76, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_DISABLED, 0 }, // MPG Z490M GAMING EDGE
{ 0x7C77, 0, 0, 0, 0, &zones_set14, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z490I UNIFY
{ 0x7C79, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z490 GAMING EDGE WIFI
{ 0x7C80, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG Z490 TOMAHAWK
{ 0x7C02, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B450 TOMAHAWK MAX
{ 0x7C81, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B460 TOMAHAWK
{ 0x7C82, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B460M MORTAR WIFI
{ 0x7C83, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_DISABLED, 0 }, // B460M PRO-VDH WIFI
{ 0x7C84, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // MAG X570 TOMAHAWK WIFI
{ 0x7C86, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_DISABLED, 0 }, // MPG B460I GAMING EDGE
{ 0x7C87, 6, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // B450M BAZOOKA MAX WIFI
{ 0x7C90, 6, 4, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B550 GAMING CARBON WIFI
{ 0x7C91, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B550 TOMAHAWK
{ 0x7C92, 6, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B550I GAMING EDGE WIFI
{ 0x7C94, 6, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B550M MORTAR
{ 0x7C95, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // B550M PRO-VDH WIFI
{ 0x7C98, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // Z490 PLUS
{ 0x7D03, 0, 15, 18, 1, &zones_set8, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z590 GODLIKE
{ 0x7D06, 4, 4, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z590 GAMING FORCE
{ 0x7D07, 4, 5, 0, 2, &zones_set7, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z590 GAMING EDGE WIFI
{ 0x7D08, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG Z590 TOMAHAWK
{ 0x7D09, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // Z590-A PRO WIFI
{ 0x7D13, 6, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG B550 UNIFY
{ 0x7D14, 6, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // A520M PRO
{ 0x7D15, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B560 TOMAHAWK WIFI
{ 0x7D17, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B560M MORTAR
{ 0x7D18, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B560M PRO-VDH
{ 0x7D19, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B560I GAMIING EDGE WIFI
{ 0x7D20, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B560M PRO
{ 0x7D25, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO Z690-A WIFI DDR4
{ 0x7D27, 6, 0, 0, 2, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z690 ACE
{ 0x7D28, 6, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z690 UNIFY-X
{ 0x7D29, 6, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z690I UNIFY
{ 0x7D30, 6, 6, 0, 2, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z690 CARBON WIFI
{ 0x7D31, 4, 8, 0, 2, &zones_set12, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG EDGE WIFI DDR4
{ 0x7D32, 1, 0, 0, 1, &zones_set10, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG Z690 TOMAHAWK WIFI DDR4
{ 0x7D33, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO Z790-VC WIFI
{ 0x7D36, 6, 0, 0, 2, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO Z690-P DDR4
{ 0x7D37, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B760M-VC WIFI (MS-7D37) - fans on JRAINBOW2
{ 0x7D38, 0, 0, 0, 1, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z590 UNIFY-X
{ 0x7D40, 0, 0, 0, 1, &zones_set5, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B760i EDGE WIFI DDR4
{ 0x7D41, 6, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B660M TOMAHAWK WIFI DDR4
{ 0x7D42, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B660 MORTAR WIFI DDR4
{ 0x7D43, 0, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B660M-A WIFI DDR4
{ 0x7D46, 0, 1, 1, 0, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO H610M-G DDR4
{ 0x7D50, 6, 12, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG X570S ACE MAX
{ 0x7D51, 6, 0, 0, 2, &zones_set1, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG X570S UNIFY-X MAX
{ 0x7D52, 6, 14, 0, 1, &zones_set3, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG X570S CARBON EK X
{ 0x7D53, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG X570S EDGE MAX WIFI
{ 0x7D54, 6, 0, 0, 2, &zones_set0, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG X570S TOMAHAWK MAX WIFI
{ 0x7D59, 0, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B660-A DDR4
{ 0x7D67, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO X670-P WIFI
{ 0x7D69, 9, 2, 4, 1, &zones_set15, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG X670E ACE
{ 0x7D70, 0, 6, 0, 1, &zones_set9, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG X670E Carbon WIFI
{ 0x7D73, 1, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B650I EDGE WIFI
{ 0x7D74, 0, 6, 0, 1, &zones_set18, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B650 CARBON WIFI
{ 0x7D75, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B650 TOMAHAWK WIFI
{ 0x7D76, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B650M MORTAR WIFI
{ 0x7D77, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B650M-A WIFI
{ 0x7D78, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B650-P WIFI
{ 0x7D86, 0, 18, 4, 1, &zones_set16, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MEG Z790 ACE
{ 0x7D88, 0, 0, 0, 1, &zones_set20, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z790-S WIFI
{ 0x7D89, 0, 6, 0, 1, &zones_set18, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z790 CARBON WIFI
{ 0x7D90, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // B760M BOMBER DDR4
{ 0x7D91, 1, 0, 0, 1, &zones_set10, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG Z790 TOMAHAWK WIFI
{ 0x7D93, 6, 0, 0, 1, &zones_set2, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // Z790 GAMING PRO WIFI
{ 0x7D96, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B760 TOMAHAWK WIFI DDR5
{ 0x7D97, 6, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B660 MORTAR MAX WIFI DDR4
{ 0x7D98, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B760-P WIFI DDR4
{ 0x7D99, 6, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B760M-A WIFI DDR4
{ 0x7E01, 0, 0, 0, 1, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG B760M MORTAR MAX
{ 0x7E03, 6, 0, 0, 0, &zones_set6, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG Z790I EDGE WIFI
{ 0x7E06, 0, 0, 0, 2, &zones_set11, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO Z790-P WIFI DDR4
{ 0x7E07, 0, 0, 0, 2, &zones_set10, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO Z790-A WIFI DDR4
{ 0x7E09, 0, 0, 0, 0, &zones_set19, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // B650M PROJECT ZERO
{ 0x7E10, 0, 6, 0, 2, &zones_set17, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MPG B650 EDGE WIFI
{ 0x7E12, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG X670E TOMAHAWK WIFI
{ 0x0076, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // MAG X670E TOMAHAWK WIFI (Common PID)
{ 0x7E16, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // X670E GAMING PLUS WIFI
{ 0x7E24, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // B650M GAMING PLUS WIFI
{ 0x7E26, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // B650 GAMING PLUS WIFI
{ 0x7E27, 0, 0, 0, 2, &zones_set13, MSIMotherboard185Controller::DIRECT_MODE_PER_LED, 0 }, // PRO B650M-P
{ 0x7E28, 6, 0, 0, 2, &zones_set21, MSIMotherboard185Controller::DIRECT_MODE_ZONE_BASED, 0 }, // MSI PRO A620M-B (MS-7E28)
};
FeaturePacket_185 enable_per_led_msg;
Color* per_led_onboard_leds;
@@ -367,22 +367,29 @@ Color* per_led_jcorsair_sync;
MSIMotherboard185Controller::MSIMotherboard185Controller(hid_device* handle, const char* path, unsigned short pid, std::string dev_name)
{
dev = handle;
location = path;
name = dev_name;
dev = handle;
location = path;
name = dev_name;
version_invalid = false;
if(dev)
{
ReadFwVersion();
ReadSettings();
}
/*-----------------------------------------------------*\
| Read the controller's firmware version |
\*-----------------------------------------------------*/
ReadFwVersion();
/*-----------------------------------------------------*\
| Common PID boards embed their virtual PID in the |
| serial number, extract it |
\*-----------------------------------------------------*/
if(pid == MSI_USB_PID_COMMON)
{
std::string pidStr(GetSerial().substr(0, 4));
pid = std::stoi(pidStr, nullptr, 16);
}
/*-----------------------------------------------------*\
| Determine if this board has mixed-mode support |
\*-----------------------------------------------------*/
mixed_mode_support = false;
if(pid >= 0x7D03)
@@ -391,14 +398,23 @@ MSIMotherboard185Controller::MSIMotherboard185Controller(hid_device* handle, con
}
/*-----------------------------------------------------*\
| Initialize save flag and some static settings |
| The last byte of the packet is the save flag. This |
| byte is stored as a zero in the data flash, but is |
| set to 1 at the protocol level to tell the firmware |
| to save the active configuration to flash. |
| Also set onboard zone to act as sync master for all |
| of the onboard LEDs. |
\*-----------------------------------------------------*/
data.save_data = 0;
data.on_board_led.colorFlags = 0x80 | SYNC_SETTING_ONBOARD; // always enable onboard sync flag to have expected zone control
data.save_data = 0;
data.on_board_led.colorFlags = MSI_COLOR_FLAG_USE_CUSTOM_COLOR | MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
/*-----------------------------------------------------*\
| Search for the board configuration matching this |
| board. |
\*-----------------------------------------------------*/
const mystic_light_185_config* board_config = nullptr;
for(std::size_t i = 0; i < NUMOF_CONFIGS; ++i)
for(std::size_t i = 0; i < NUMOF_CONFIGS; i++)
{
if(board_configs[i].pid == pid)
{
@@ -407,25 +423,44 @@ MSIMotherboard185Controller::MSIMotherboard185Controller(hid_device* handle, con
}
}
/*-----------------------------------------------------*\
| Fill in the number of each zone type based on the |
| board configuration |
\*-----------------------------------------------------*/
if(board_config != nullptr)
{
numof_onboard_leds = board_config->numof_onboard_leds;
numof_pipe1_leds = board_config->numof_pipe1_leds;
numof_pipe2_leds = board_config->numof_pipe2_leds;
numof_JRGBs = board_config->numof_JRGBs;
supported_zones = board_config->supported_zones;
per_led_mode = board_config->per_led_mode;
/*-------------------------------------------------*\
| If the firmware version is below the minimum, set |
| invalid version flag and return |
\*-------------------------------------------------*/
if(version_APROM_val < board_config->minimum_firmware_version)
{
version_invalid = true;
return;
}
numof_onboard_leds = board_config->numof_onboard_leds;
numof_pipe1_leds = board_config->numof_pipe1_leds;
numof_pipe2_leds = board_config->numof_pipe2_leds;
numof_JRGBs = board_config->numof_JRGBs;
supported_zones = board_config->supported_zones;
per_led_mode = board_config->per_led_mode;
}
else
{
numof_onboard_leds = 6;
numof_pipe1_leds = 1;
numof_pipe2_leds = 1;
numof_JRGBs = 2;
supported_zones = &all_zones;
per_led_mode = DIRECT_MODE_DISABLED;
numof_onboard_leds = 6;
numof_pipe1_leds = 1;
numof_pipe2_leds = 1;
numof_JRGBs = 2;
supported_zones = &all_zones;
per_led_mode = DIRECT_MODE_DISABLED;
}
/*-----------------------------------------------------*\
| Read the controller's active configuration data |
\*-----------------------------------------------------*/
ReadSettings();
/*-----------------------------------------------------*\
| Initialize per-LED data |
\*-----------------------------------------------------*/
@@ -500,7 +535,7 @@ MSIMotherboard185Controller::MSIMotherboard185Controller(hid_device* handle, con
enable_per_led_msg.j_corsair_outerll120.speedAndBrightnessFlags = 0x28;
enable_per_led_msg.j_corsair_outerll120.colorFlags = 0x80;
enable_per_led_msg.on_board_led.effect = MSI_DIRECT_MODE;
enable_per_led_msg.on_board_led.speedAndBrightnessFlags = 0x29 | SYNC_SETTING_JRGB;
enable_per_led_msg.on_board_led.speedAndBrightnessFlags = 0x29 | MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
enable_per_led_msg.on_board_led.colorFlags = PER_LED_FULL_SYNC_MODE;
enable_per_led_msg.on_board_led_1.speedAndBrightnessFlags = 0x28;
enable_per_led_msg.on_board_led_1.colorFlags = 0x80;
@@ -526,42 +561,43 @@ MSIMotherboard185Controller::MSIMotherboard185Controller(hid_device* handle, con
/*-----------------------------------------------------*\
| Initialize zone based per LED data |
\*-----------------------------------------------------*/
zone_based_per_led_data.j_rgb_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rgb_1.colorFlags = BITSET(zone_based_per_led_data.j_rgb_1.colorFlags, true, 7u);
zone_based_per_led_data.j_pipe_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_pipe_1.colorFlags = BITSET(zone_based_per_led_data.j_pipe_1.colorFlags, true, 7u);
zone_based_per_led_data.j_pipe_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_pipe_2.colorFlags = BITSET(zone_based_per_led_data.j_pipe_2.colorFlags, true, 7u);
zone_based_per_led_data.j_rainbow_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rainbow_1.colorFlags = BITSET(zone_based_per_led_data.j_rainbow_1.colorFlags, true, 7u);
zone_based_per_led_data.j_rainbow_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rainbow_2.colorFlags = BITSET(zone_based_per_led_data.j_rainbow_2.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led.colorFlags = BITSET(zone_based_per_led_data.on_board_led.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_1.colorFlags = BITSET(zone_based_per_led_data.on_board_led_1.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_2.colorFlags = BITSET(zone_based_per_led_data.on_board_led_2.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_3.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_3.colorFlags = BITSET(zone_based_per_led_data.on_board_led_3.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_4.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_4.colorFlags = BITSET(zone_based_per_led_data.on_board_led_4.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_5.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_5.colorFlags = BITSET(zone_based_per_led_data.on_board_led_5.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_6.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2 << 2;
zone_based_per_led_data.on_board_led_6.colorFlags = BITSET(zone_based_per_led_data.on_board_led_6.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_7.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100;
zone_based_per_led_data.on_board_led_7.colorFlags = BITSET(zone_based_per_led_data.on_board_led_7.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_8.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_8.colorFlags = BITSET(zone_based_per_led_data.on_board_led_8.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_9.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_9.colorFlags = BITSET(zone_based_per_led_data.on_board_led_9.colorFlags, true, 7u);
zone_based_per_led_data.j_rgb_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rgb_2.colorFlags = BITSET(zone_based_per_led_data.j_rgb_2.colorFlags, true, 7u);
zone_based_per_led_data.j_rgb_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_rgb_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.j_pipe_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_pipe_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.j_pipe_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_pipe_2.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.j_rainbow_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_rainbow_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.j_rainbow_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_rainbow_2.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_1.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_2.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_3.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_3.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_4.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_4.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_5.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_5.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_6.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_6.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_7.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_7.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_8.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_8.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.on_board_led_9.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.on_board_led_9.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.j_rgb_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT;
zone_based_per_led_data.j_rgb_2.colorFlags |= MSI_COLOR_FLAG_USE_CUSTOM_COLOR;
zone_based_per_led_data.save_data = 0;
direct_mode = false;
sync_direct_mode = true;
direct_mode = false;
direct_mode_configured = false;
sync_direct_mode = true;
}
MSIMotherboard185Controller::~MSIMotherboard185Controller()
@@ -569,6 +605,11 @@ MSIMotherboard185Controller::~MSIMotherboard185Controller()
hid_close(dev);
}
bool MSIMotherboard185Controller::GetFirmwareVersionInvalid()
{
return(version_invalid);
}
void MSIMotherboard185Controller::SetMode
(
MSI_ZONE zone,
@@ -583,40 +624,74 @@ void MSIMotherboard185Controller::SetMode
return;
}
/*-----------------------------------------------------*\
| Get the zone data pointer within the configuration |
| data buffer |
\*-----------------------------------------------------*/
ZoneData* zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
/*-----------------------------------------------------*\
| Update the zone's mode and mode parameters |
\*-----------------------------------------------------*/
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
/*-----------------------------------------------------*\
| J_RAINBOW_3 zone needs padding of 4 |
\*-----------------------------------------------------*/
zone == MSI_ZONE_J_RAINBOW_3 ? zone_data->padding = 4 : zone_data->padding = 0;
/*-----------------------------------------------------*\
| Get the zone data pointer to the on-board LED 0 zone |
\*-----------------------------------------------------*/
ZoneData* on_board_zone = GetZoneData(data, MSI_ZONE_ON_BOARD_LED_0);
/*-----------------------------------------------------*\
| If the zone is JRGB or JPIPE and the board has no |
| onboard LEDs, set the onboard zone to this zone's |
| settings |
\*-----------------------------------------------------*/
if(no_onboards && ((zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_RGB_2) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2)))
{
on_board_zone->effect = zone_data->effect;
on_board_zone->speedAndBrightnessFlags = zone_data->speedAndBrightnessFlags;
on_board_zone->colorFlags = zone_data->colorFlags;
on_board_zone->colorFlags |= SYNC_SETTING_ONBOARD;
on_board_zone->padding = 0x00;
on_board_zone->effect = zone_data->effect;
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
on_board_zone->colorFlags |= MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD;
on_board_zone->padding = 0x00;
}
/*-----------------------------------------------------*\
| For modes above MSI_MODE_LIGHTNING, set the onboard |
| zone to sync with JRGB, JPIPE1, and JPIPE2 |
\*-----------------------------------------------------*/
if(mode > MSI_MODE_LIGHTNING)
{
on_board_zone->speedAndBrightnessFlags |= SYNC_SETTING_JRGB;
on_board_zone->colorFlags |= (SYNC_SETTING_JPIPE1 | SYNC_SETTING_JPIPE2);
on_board_zone->speedAndBrightnessFlags |= MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
on_board_zone->colorFlags |= (MSI_COLOR_FLAG_SYNC_SETTING_JPIPE1 | MSI_COLOR_FLAG_SYNC_SETTING_JPIPE2);
}
else
{
on_board_zone->speedAndBrightnessFlags &= ~SYNC_SETTING_JRGB;
on_board_zone->colorFlags &= ~(SYNC_SETTING_JPIPE1 | SYNC_SETTING_JPIPE2);
on_board_zone->speedAndBrightnessFlags &= ~MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB;
on_board_zone->colorFlags &= ~(MSI_COLOR_FLAG_SYNC_SETTING_JPIPE1 | MSI_COLOR_FLAG_SYNC_SETTING_JPIPE2);
}
/*-----------------------------------------------------*\
| For modes at or below MSI_MODE_LIGHTNING, set all |
| onboard LED zones to match onboard LED zone 0 |
\*-----------------------------------------------------*/
if((zone == MSI_ZONE_ON_BOARD_LED_0) && (mode <= MSI_MODE_LIGHTNING))
{
for(int i = 0; i < numof_onboard_leds; ++i)
@@ -626,8 +701,10 @@ void MSIMotherboard185Controller::SetMode
if(zone_data != nullptr)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->speedAndBrightnessFlags = ((brightness << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK)
| ((speed << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
zone_data->colorFlags = (rainbow_color ? (zone_data->colorFlags & ~MSI_COLOR_FLAG_USE_CUSTOM_COLOR)
: (zone_data->colorFlags | MSI_COLOR_FLAG_USE_CUSTOM_COLOR));
zone_data->padding = 0x00;
}
}
@@ -667,7 +744,7 @@ bool MSIMotherboard185Controller::ReadSettings()
/*-----------------------------------------------------*\
| Read packet from hardware, return true if successful |
\*-----------------------------------------------------*/
return (hid_get_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof data);
return(hid_get_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof data);
}
bool MSIMotherboard185Controller::Update
@@ -682,33 +759,73 @@ bool MSIMotherboard185Controller::Update
{
if(per_led_mode == DIRECT_MODE_PER_LED)
{
/*---------------------------------------------*\
| Skip sending update if there are no LEDs |
| configured |
\*---------------------------------------------*/
bool has_active_per_led_data = false;
if(!no_onboards)
{
has_active_per_led_data = true;
}
if(!no_jrainbow1)
{
has_active_per_led_data = true;
}
if(!no_jrainbow2)
{
has_active_per_led_data = true;
}
if(!no_jcorsair)
{
has_active_per_led_data = true;
}
if(!has_active_per_led_data)
{
return false;
}
/*---------------------------------------------*\
| Ensure the enable per-LED mode message has |
| been sent before sending the per-LED data |
\*---------------------------------------------*/
if(!direct_mode_configured)
{
if(!SelectPerLedProtocol())
{
return false;
}
}
if(sync_direct_mode)
{
return (hid_send_feature_report(dev, (unsigned char*)&per_led_data_onboard_and_sync, sizeof(per_led_data_onboard_and_sync)) == sizeof(per_led_data_onboard_and_sync));
return(hid_send_feature_report(dev, (unsigned char*)&per_led_data_onboard_and_sync, sizeof(per_led_data_onboard_and_sync)) == sizeof(per_led_data_onboard_and_sync));
}
else
{
if(!no_jrainbow1)
{
(void)hid_send_feature_report(dev, (unsigned char*)&per_led_data_jrainbow1, sizeof(per_led_data_jrainbow1));
hid_send_feature_report(dev, (unsigned char*)&per_led_data_jrainbow1, sizeof(per_led_data_jrainbow1));
std::this_thread::sleep_for(13ms);
}
if(!no_jrainbow2)
{
(void)hid_send_feature_report(dev, (unsigned char*)&per_led_data_jrainbow2, sizeof(per_led_data_jrainbow2));
hid_send_feature_report(dev, (unsigned char*)&per_led_data_jrainbow2, sizeof(per_led_data_jrainbow2));
std::this_thread::sleep_for(13ms);
}
if(!no_jcorsair)
{
(void)hid_send_feature_report(dev, (unsigned char*)&per_led_data_jcorsair, sizeof(per_led_data_jcorsair));
hid_send_feature_report(dev, (unsigned char*)&per_led_data_jcorsair, sizeof(per_led_data_jcorsair));
std::this_thread::sleep_for(13ms);
}
return (hid_send_feature_report(dev, (unsigned char*)&per_led_data_onboard_and_sync, sizeof(per_led_data_onboard_and_sync)) == sizeof(per_led_data_onboard_and_sync));
return(hid_send_feature_report(dev, (unsigned char*)&per_led_data_onboard_and_sync, sizeof(per_led_data_onboard_and_sync)) == sizeof(per_led_data_onboard_and_sync));
}
}
else
{
return (hid_send_feature_report(dev, (unsigned char*)&zone_based_per_led_data, sizeof(zone_based_per_led_data)) == sizeof(zone_based_per_led_data));
return(hid_send_feature_report(dev, (unsigned char*)&zone_based_per_led_data, sizeof(zone_based_per_led_data)) == sizeof(zone_based_per_led_data));
}
}
else
@@ -728,7 +845,7 @@ bool MSIMotherboard185Controller::Update
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));
return(hid_send_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof(data));
}
}
@@ -748,13 +865,23 @@ void MSIMotherboard185Controller::SetZoneColor
return;
}
/*-----------------------------------------------------*\
| Get the zone data pointer within the configuration |
| data buffer |
\*-----------------------------------------------------*/
ZoneData* zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
/*-----------------------------------------------------*\
| Set the colors in the zone data |
\*-----------------------------------------------------*/
zone_data->color.R = red1;
zone_data->color.G = grn1;
zone_data->color.B = blu1;
@@ -762,6 +889,11 @@ void MSIMotherboard185Controller::SetZoneColor
zone_data->color2.G = grn2;
zone_data->color2.B = blu2;
/*-----------------------------------------------------*\
| If the zone is JRGB or JPIPE and the board has no |
| onboard LEDs, set the onboard zone's colors to this |
| zone's colors |
\*-----------------------------------------------------*/
if(no_onboards && ((zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_RGB_2) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2)))
{
ZoneData* on_board_zone = GetZoneData(data, MSI_ZONE_ON_BOARD_LED_0);
@@ -774,6 +906,10 @@ void MSIMotherboard185Controller::SetZoneColor
on_board_zone->color2.B = blu2;
}
/*-----------------------------------------------------*\
| Set all onboard LED zones' colors to match onboard |
| LED 0 |
\*-----------------------------------------------------*/
if(zone == MSI_ZONE_ON_BOARD_LED_0)
{
for(int i = 0; i < numof_onboard_leds; ++i)
@@ -802,6 +938,10 @@ void MSIMotherboard185Controller::SetLedColor
unsigned char blu
)
{
/*-----------------------------------------------------*\
| If this board supports Per-LED direct mode, update |
| the per-LED packet buffers |
\*-----------------------------------------------------*/
if(per_led_mode == DIRECT_MODE_PER_LED)
{
Color* zone_data = GetPerLedZoneData(zone);
@@ -837,6 +977,9 @@ void MSIMotherboard185Controller::SetLedColor
}
}
}
/*-----------------------------------------------------*\
| Otherwise, colors are set per zone. |
\*-----------------------------------------------------*/
else
{
if(((zone == MSI_ZONE_J_RAINBOW_1) || (zone == MSI_ZONE_J_RAINBOW_2) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2)) && (index != 0))
@@ -1038,6 +1181,8 @@ bool MSIMotherboard185Controller::ReadFwVersion()
ret_val &= hid_write(dev, request, 64);
ret_val &= hid_read(dev, response, 64);
version_APROM_val = response[2];
/*-----------------------------------------------------*\
| Extract high and low values from response |
\*-----------------------------------------------------*/
@@ -1124,17 +1269,17 @@ void MSIMotherboard185Controller::GetMode
/*-----------------------------------------------------*\
| Update pointers with data |
\*-----------------------------------------------------*/
mode = (MSI_MODE)zone_data->effect;
speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F);
rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false;
mode = (MSI_MODE) zone_data->effect;
speed = (MSI_SPEED) ((zone_data->speedAndBrightnessFlags >> MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT) & MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK);
rainbow_color = ((zone_data->colorFlags & MSI_COLOR_FLAG_USE_CUSTOM_COLOR) == 0 ? false : true);
color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B);
}
void MSIMotherboard185Controller::SetCycleCount
void MSIMotherboard185Controller::SetZoneLEDCount
(
MSI_ZONE zone,
unsigned char cycle_num
unsigned char led_num
)
{
RainbowZoneData *requested_zone = GetRainbowZoneData(zone);
@@ -1144,7 +1289,7 @@ void MSIMotherboard185Controller::SetCycleCount
return;
}
requested_zone->cycle_or_led_num = cycle_num;
requested_zone->cycle_or_led_num = led_num;
SelectPerLedProtocol();
}
@@ -1153,7 +1298,8 @@ void MSIMotherboard185Controller::SetDirectMode
bool mode
)
{
direct_mode = mode;
direct_mode = mode;
direct_mode_configured = false;
SelectPerLedProtocol();
}
@@ -1212,9 +1358,8 @@ size_t MSIMotherboard185Controller::GetMaxDirectLeds
}
}
void MSIMotherboard185Controller::SelectPerLedProtocol()
bool MSIMotherboard185Controller::SelectPerLedProtocol()
{
unsigned char jrainbow1_size = 0;
unsigned char jrainbow2_size = 0;
unsigned char jrainbow3_size = 0;
@@ -1283,7 +1428,17 @@ void MSIMotherboard185Controller::SelectPerLedProtocol()
{
if(per_led_mode == DIRECT_MODE_PER_LED)
{
hid_send_feature_report(dev, (unsigned char*)&enable_per_led_msg, sizeof(enable_per_led_msg));
if(hid_send_feature_report(dev, (unsigned char*)&enable_per_led_msg, sizeof(enable_per_led_msg)) != sizeof(enable_per_led_msg))
{
return false;
}
direct_mode_configured = true;
}
return true;
}
else
{
return false;
}
}
@@ -46,6 +46,7 @@ public:
);
MSI_MODE GetMode();
bool GetFirmwareVersionInvalid();
void GetMode
(
@@ -77,10 +78,10 @@ public:
unsigned char blu
);
void SetCycleCount
void SetZoneLEDCount
(
MSI_ZONE zone,
unsigned char cycle_num
unsigned char led_num
);
bool Update
@@ -119,6 +120,8 @@ private:
std::string name;
std::string location;
std::string version_APROM;
unsigned char version_APROM_val;
bool version_invalid;
std::string version_LDROM;
FeaturePacket_185 data;
@@ -128,6 +131,7 @@ private:
FeaturePacket_PerLED_185 per_led_data_jcorsair;
FeaturePacket_185 zone_based_per_led_data;
bool direct_mode;
bool direct_mode_configured;
bool sync_direct_mode;
bool no_onboards;
bool no_jrainbow1;
@@ -153,5 +157,5 @@ private:
(
MSI_ZONE zone
);
void SelectPerLedProtocol();
bool SelectPerLedProtocol();
};
@@ -227,7 +227,7 @@ void RGBController_MSIMotherboard185::SetupZones()
last_resizable_zone = zd->zone_type;
}
controller->SetCycleCount(zone_description[zone_idx]->zone_type, zones[zone_idx].leds_count);
controller->SetZoneLEDCount(zone_description[zone_idx]->zone_type, zones[zone_idx].leds_count);
if((zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURABLE_SIZE_EFFECTS_ONLY) == 0)
{
@@ -267,6 +267,11 @@ void RGBController_MSIMotherboard185::DeviceConfigureZone(int zone_idx)
void RGBController_MSIMotherboard185::DeviceUpdateLEDs()
{
if((modes[active_mode].value == MSI_MODE_DIRECT_DUMMY) && !controller->IsDirectModeActive())
{
controller->SetDirectMode(true);
}
for(std::size_t zone_idx = 0; zone_idx < zones.size(); ++zone_idx)
{
for(int led_idx = zones[zone_idx].leds_count - 1; led_idx >= 0; led_idx--)
@@ -279,6 +284,11 @@ void RGBController_MSIMotherboard185::DeviceUpdateLEDs()
void RGBController_MSIMotherboard185::DeviceUpdateZoneLEDs(int zone)
{
if((modes[active_mode].value == MSI_MODE_DIRECT_DUMMY) && !controller->IsDirectModeActive())
{
controller->SetDirectMode(true);
}
for(int led_idx = zones[zone].leds_count - 1; led_idx >= 0; led_idx--)
{
UpdateLed(zone, led_idx);
@@ -291,6 +301,11 @@ void RGBController_MSIMotherboard185::DeviceUpdateSingleLED
int led
)
{
if((modes[active_mode].value == MSI_MODE_DIRECT_DUMMY) && !controller->IsDirectModeActive())
{
controller->SetDirectMode(true);
}
int zone_index = IndexOfZoneForType((MSI_ZONE)leds[led].value);
if(zone_index == -1)
@@ -319,7 +334,7 @@ void RGBController_MSIMotherboard185::DeviceUpdateMode()
void RGBController_MSIMotherboard185::DeviceSaveMode()
{
controller->Update(true);
controller->Update(true);
}
void RGBController_MSIMotherboard185::SetupModes()
@@ -72,9 +72,15 @@ static const std::string board_names[] =
"MSI MAG B850 TOMAHAWK WIFI (MS-7E53)",
"MSI MEG Z890 UNIFY-X (MS-7E20)",
"MSI PRO X870E-S EVO WIFI (MS-7E86)",
"MSI MAG X870E GAMING MAX WIFI (MS-7E86)",
"MSI PRO Z890-P WIFI (MS-7E34)",
"MSI B850 GAMING PLUS WIFI PZ (MS-7E75)",
"MSI MAG X870E TOMAHAWK MAX WIFI PZ (MS-7E84)",
"MSI PRO B850M-A WIFI PZ (MS-7E78)",
"MSI B850MPOWER (MS-7E83)",
"MSI B840M GAMING WIFI6E (MS-7E76)",
"MSI PRO B850M-A WIFI (MS-7E66)",
"MSI PRO B850-S WIFI6E (MS-7E80)"
};
static const mystic_light_761_config board_configs[] =
@@ -104,9 +110,15 @@ static const mystic_light_761_config board_configs[] =
{ &(board_names[22]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG B850 TOMAHAWK WIFI (MS-7E53)
{ &(board_names[23]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MEG Z890 UNIFY-X (MS-7E20)
{ &(board_names[24]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO X870E-S EVO WIFI (MS-7E86)
{ &(board_names[25]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO Z890-P WIFI (MS-7E34)
{ &(board_names[26]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI B850 GAMING PLUS WIFI PZ (MS-7E75)
{ &(board_names[27]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG X870E TOMAHAWK MAX WIFI PZ (MS-7E84)
{ &(board_names[25]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG X870E GAMING MAX WIFI (MS-7E86)
{ &(board_names[26]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO Z890-P WIFI (MS-7E34)
{ &(board_names[27]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI B850 GAMING PLUS WIFI PZ (MS-7E75)
{ &(board_names[28]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI MAG X870E TOMAHAWK MAX WIFI PZ (MS-7E84)
{ &(board_names[29]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO B850M-A WIFI PZ (MS-7E78)
{ &(board_names[30]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI B850MPOWER (MS-7E83)
{ &(board_names[31]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI B840M GAMING WIFI6E (MS-7E76)
{ &(board_names[32]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO B850M-A WIFI (MS-7E66)
{ &(board_names[33]), 0, 0, 0, 1, &zone_set1, MSIMotherboard761Controller::DIRECT_MODE_ZONE_BASED }, // MSI PRO B850-S WIFI6E (MS-7E80)
};
enum MSI_ZONE setup_map [] =
@@ -591,10 +603,10 @@ void MSIMotherboard761Controller::GetMode
color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B);
}
void MSIMotherboard761Controller::SetCycleCount
void MSIMotherboard761Controller::SetZoneLEDCount
(
MSI_ZONE /*zone*/,
unsigned char /*cycle_num*/
unsigned char /*led_num*/
)
{
return;
@@ -75,10 +75,10 @@ public:
unsigned char blu
);
void SetCycleCount
void SetZoneLEDCount
(
MSI_ZONE zone,
unsigned char cycle_num
unsigned char led_num
);
bool Update
@@ -210,7 +210,7 @@ void RGBController_MSIMotherboard761::SetupZones()
last_resizable_zone = zd->zone_type;
}
controller->SetCycleCount(zone_description[zone_idx]->zone_type, zones[zone_idx].leds_count);
controller->SetZoneLEDCount(zone_description[zone_idx]->zone_type, zones[zone_idx].leds_count);
if((zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURABLE_SIZE_EFFECTS_ONLY) == 0)
{
@@ -122,13 +122,22 @@ enum MSI_BRIGHTNESS
#define NUMOF_PER_LED_MODE_LEDS 240
#define NUM_LEDS_761 720
#define SYNC_SETTING_ONBOARD 0x01
#define SYNC_SETTING_JRAINBOW1 0x02
#define SYNC_SETTING_JRAINBOW2 0x04
#define SYNC_SETTING_JCORSAIR 0x08
#define SYNC_SETTING_JPIPE1 0x10
#define SYNC_SETTING_JPIPE2 0x20
#define SYNC_SETTING_JRGB 0x80
/*---------------------------------------------------------*\
| Flag bitfield bit definitions |
| Note that the sync flags split across the two fields |
\*---------------------------------------------------------*/
#define MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT 0
#define MSI_SPEED_BRIGHTNESS_FLAG_SPEED_MASK (0x03 << MSI_SPEED_BRIGHTNESS_FLAG_SPEED_SHIFT)
#define MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT 2
#define MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_MASK (0x1F << MSI_SPEED_BRIGHTNESS_FLAG_BRIGHTNESS_SHIFT)
#define MSI_SPEED_BRIGHTNESS_FLAG_SYNC_SETTING_JRGB (1 << 7)
#define MSI_COLOR_FLAG_SYNC_SETTING_ONBOARD (1 << 0)
#define MSI_COLOR_FLAG_SYNC_SETTING_JRAINBOW1 (1 << 1)
#define MSI_COLOR_FLAG_SYNC_SETTING_JRAINBOW2 (1 << 2)
#define MSI_COLOR_FLAG_SYNC_SETTING_JCORSAIR (1 << 3)
#define MSI_COLOR_FLAG_SYNC_SETTING_JPIPE1 (1 << 4)
#define MSI_COLOR_FLAG_SYNC_SETTING_JPIPE2 (1 << 5)
#define MSI_COLOR_FLAG_USE_CUSTOM_COLOR (1 << 7)
struct Color
{
@@ -54,9 +54,17 @@ DetectedControllers DetectMSIMotherboardControllers(hid_device_info* info, const
if((packet_length >= sizeof(FeaturePacket_185)) && (packet_length <= (sizeof(FeaturePacket_185) + 1))) //WHY r we doing this ? why not ==
{
MSIMotherboard185Controller* controller = new MSIMotherboard185Controller(dev, info->path, info->product_id, dmi_name);
RGBController_MSIMotherboard185* rgb_controller = new RGBController_MSIMotherboard185(controller);
detected_controllers.push_back(rgb_controller);
if(controller->GetFirmwareVersionInvalid())
{
LOG_WARNING("[MSIMotherboard185] Controller firmware below minimum supported version, skipping");
}
else
{
RGBController_MSIMotherboard185* rgb_controller = new RGBController_MSIMotherboard185(controller);
detected_controllers.push_back(rgb_controller);
}
}
else if((packet_length >= sizeof(FeaturePacket_162)) && (packet_length <= (sizeof(FeaturePacket_162) + 1)))
{
@@ -223,9 +231,12 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E70", DetectMSIMotherboardCont
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E59", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E59, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E80", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E80, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E81", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E81, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E86", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E86, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E34", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E34, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E32", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E32, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E20", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E20, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E76", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E76, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E66", DetectMSIMotherboardControllers, MSI_USB_VID, 0x7E66, 0x0001, 0x00);
// Detector for the set of common boards
REGISTER_HID_DETECTOR_PU("MSI Mystic Light Common", DetectMSIMotherboardControllers, MSI_USB_VID_COMMON, MSI_USB_PID_COMMON, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light X870", DetectMSIMotherboardControllers, MSI_USB_VID_COMMON, MSI_USB_PID_COMMON, 0xFF00, 0x01);
@@ -236,6 +247,7 @@ REGISTER_CUSTOM_UDEV_RULE(msi_7e24, "MSI Mystic Light MS_7E24", "SUBSYSTEMS==\"u
REGISTER_CUSTOM_UDEV_RULE(msi_7e26, "MSI Mystic Light MS_7E26", "SUBSYSTEMS==\"usb|hidraw\", ATTRS{idVendor}==\"1462\", ATTRS{idProduct}==\"7e26\", TAG+=\"uaccess\", TAG+=\"MSI_Mystic_Light_MS_7E26\"");
REGISTER_CUSTOM_UDEV_RULE(msi_7e27, "MSI Mystic Light MS_7E27", "SUBSYSTEMS==\"usb|hidraw\", ATTRS{idVendor}==\"1462\", ATTRS{idProduct}==\"7e27\", TAG+=\"uaccess\", TAG+=\"MSI_Mystic_Light_MS_7E27\"");
REGISTER_CUSTOM_UDEV_RULE(msi_7e49, "MSI Mystic Light MS_7E49", "SUBSYSTEMS==\"usb|hidraw\", ATTRS{idVendor}==\"1462\", ATTRS{idProduct}==\"7e49\", TAG+=\"uaccess\", TAG+=\"MSI_Mystic_Light_MS_7E49\"");
REGISTER_CUSTOM_UDEV_RULE(msi_7e76, "MSI Mystic Light MS_7E76", "SUBSYSTEMS==\"usb|hidraw\", ATTRS{idVendor}==\"1462\", ATTRS{idProduct}==\"7e76\", TAG+=\"uaccess\", TAG+=\"MSI_Mystic_Light_MS_7E76\"");
#ifdef ENABLE_UNTESTED_MYSTIC_LIGHT
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_3EA4", DetectMSIMotherboardControllers, MSI_USB_VID, 0x3EA4, 0x0001, 0x00);
@@ -56,6 +56,7 @@ static const nv_gpu_pci_device device_list[] =
{NVIDIA_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3060 Pegasus" },
{NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 3060 LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X" },
{NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_LHR_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X" },
{NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_GA104_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 3060 LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 Ti XLR8 REVEL EPIC-X" },
@@ -68,8 +68,6 @@ RGBController_NVIDIAIlluminationV1::RGBController_NVIDIAIlluminationV1(NVIDIAIll
Static.value = NVIDIA_ILLUMINATION_DIRECT;
Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR;
Static.color_mode = MODE_COLORS_PER_LED;
Static.colors_min = 1;
Static.colors_max = 1;
Static.brightness_min = 0;
Static.brightness = 100;
Static.brightness_max = 100;
@@ -55,15 +55,12 @@ enum
/*---------------------------------------------------------*\
| Bounds for the device-list read-until-response loop. |
| Neither value comes from a measurement against real |
| hardware - it's a reasonable default at the same scale |
| hid_read_timeout() is used elsewhere in this codebase |
| (10-100ms per read). 1s total worst-case is enough to |
| absorb a slow reply without hanging forever if the |
| device never answers correctly at all. |
| Tested against Smart Device V2, required between 100-200 |
| ms to detect attached devices, so 1000ms was chosen to |
| provide an ample buffer on top of that. |
\*---------------------------------------------------------*/
#define NZXT_HUE_2_DEVICE_LIST_READ_TIMEOUT_MS 50
#define NZXT_HUE_2_DEVICE_LIST_MAX_RETRIES 20
#define NZXT_HUE_2_DEVICE_LIST_READ_TIMEOUT_MS 1000
#define NZXT_HUE_2_DEVICE_LIST_MAX_RETRIES 10
enum
{
@@ -47,9 +47,10 @@ DetectedControllers DetectPNYARGBEpicXGPULargeControllers(i2c_smbus_interface* b
return(detected_controllers);
}
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", DetectPNYARGBEpicXGPUSmallControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PNY_SUB_VEN, PNY_RTX_5070TI_ARGB_EPIC_X_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);
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", DetectPNYARGBEpicXGPUSmallControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PNY_SUB_VEN, PNY_RTX_5070TI_ARGB_EPIC_X_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 5070Ti ARGB Epic-X OC", DetectPNYARGBEpicXGPUSmallControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PNY_SUB_VEN, PNY_RTX_5070TI_ARGB_EPIC_X_OC_SUB_DEV2, 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);
@@ -1,112 +0,0 @@
/*---------------------------------------------------------*\
| PNYGPUController.cpp |
| |
| Driver for PNY Turing GPU |
| |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "PNYGPUController.h"
PNYGPUController::PNYGPUController(i2c_smbus_interface* bus, pny_dev_id dev, std::string name)
{
this->bus = bus;
this->dev = dev;
this->name = name;
}
PNYGPUController::~PNYGPUController()
{
}
std::string PNYGPUController::GetDeviceName()
{
return(name);
}
std::string PNYGPUController::GetDeviceLocation()
{
std::string return_string(bus->info.device_name);
char addr[5];
snprintf(addr, 5, "0x%02X", dev);
return_string.append(", address ");
return_string.append(addr);
return("I2C: " + return_string);
}
void PNYGPUController::WriteI2CData(u8 command, u8 length, u8* data)
{
//Simulating i2c_smbus_write_i2c_block_data(command, length, data);
for (u8 i = 0; i < length; i++)
{
bus->i2c_smbus_write_byte_data(dev, command+i, data[i]);
}
}
unsigned char PNYGPUController::GetMode()
{
return(bus->i2c_smbus_read_byte_data(dev, PNY_GPU_MODE_OFF));
}
unsigned char PNYGPUController::GetRed()
{
return(bus->i2c_smbus_read_byte_data(dev, PNY_GPU_REG_COLOR_RED));
}
unsigned char PNYGPUController::GetGreen()
{
return(bus->i2c_smbus_read_byte_data(dev, PNY_GPU_REG_COLOR_GREEN));
}
unsigned char PNYGPUController::GetBlue()
{
return(bus->i2c_smbus_read_byte_data(dev, PNY_GPU_REG_COLOR_BLUE));
}
void PNYGPUController::SetOff()
{
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_CONTROL, 0);
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_MODE, 0x00);
}
void PNYGPUController::SetCycle(unsigned char speed)
{
u8 loop[] = {
0x01, // Direction
0x00, // ??
speed, // Speed
0x1F // Somehow related to speed
};
loop[2] = speed;
WriteI2CData(PNY_GPU_REG_CONTROL, sizeof(loop), loop);
}
void PNYGPUController::SetStrobe(unsigned char r, unsigned char g, unsigned char b, unsigned char speed, unsigned char brightness)
{
u8 strobe[] = {
0x02, // Strobe
0x00, // Rise speed
speed, // Cycle length/2
0x00, // Off delay
r, // R
g, // G
b, // B
brightness, // Peak brightness
0x05 // Fade speed
};
WriteI2CData(PNY_GPU_REG_CONTROL, sizeof(strobe), strobe);
}
void PNYGPUController::SetDirect(unsigned char red, unsigned char green, unsigned char blue, unsigned char brightness)
{
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_CONTROL, 0);
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_MODE, 0x01);
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_COLOR_RED, red);
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_COLOR_BLUE, blue);
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_COLOR_GREEN, green);
bus->i2c_smbus_write_byte_data(dev, PNY_GPU_REG_COLOR_BRIGHTNESS, brightness);
}
@@ -1,62 +0,0 @@
/*---------------------------------------------------------*\
| PNYGPUController.h |
| |
| Driver for PNY Turing GPU |
| |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
typedef unsigned char pny_dev_id;
enum
{
PNY_GPU_REG_CONTROL = 0xE0,
PNY_GPU_REG_MODE = 0x60,
PNY_GPU_REG_COLOR_RED = 0x6C,
PNY_GPU_REG_COLOR_GREEN = 0x6D,
PNY_GPU_REG_COLOR_BLUE = 0x6E,
PNY_GPU_REG_COLOR_BRIGHTNESS = 0x6F,
};
enum
{
PNY_GPU_MODE_OFF = 0x00,
PNY_GPU_MODE_DIRECT = 0x01,
PNY_GPU_MODE_CYCLE = 0x02,
PNY_GPU_MODE_STROBE = 0x03,
};
class PNYGPUController
{
public:
PNYGPUController(i2c_smbus_interface* bus, pny_dev_id dev, std::string name);
~PNYGPUController();
std::string GetDeviceName();
std::string GetDeviceLocation();
void SetOff();
void SetCycle(unsigned char speed);
void SetStrobe(unsigned char r, unsigned char g, unsigned char b, unsigned char speed, unsigned char brightness);
void SetDirect(unsigned char red, unsigned char green, unsigned char blue, unsigned char brightness);
private:
i2c_smbus_interface* bus;
pny_dev_id dev;
std::string name;
void WriteI2CData(u8 command, u8 length, u8* data);
unsigned char GetMode();
unsigned char GetRed();
unsigned char GetGreen();
unsigned char GetBlue();
};
@@ -1,76 +0,0 @@
/*---------------------------------------------------------*\
| PNYGPUControllerDetect.cpp |
| |
| Detector for PNY Turing GPU |
| |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DetectionManager.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
#include "PNYGPUController.h"
#include "RGBController_PNYGPU.h"
DetectedControllers DetectPNYGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
DetectedControllers detected_controllers;
if(bus->info.port_id == 1)
{
PNYGPUController* controller = new PNYGPUController(bus, i2c_addr, name);
RGBController_PNYGPU* rgb_controller = new RGBController_PNYGPU(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 2060 XLR8 OC EDITION", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, PNY_SUB_VEN, PNY_RTX_2060_XLR8_OC_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3060 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3070 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3070 XLR8 Revel EPIC-X LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3080 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PNY_SUB_VEN, PNY_RTX_3080_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3080 Ti XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PNY_SUB_VEN, PNY_RTX_3080TI_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3090 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PNY_SUB_VEN, PNY_RTX_3090_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 2070 SUPER Jetstream", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PALIT_SUB_VEN, PALIT_RTX3060_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3060_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, PALIT_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PALIT_SUB_VEN, NVIDIA_RTX3060TI_LHR_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti Dual", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, NVIDIA_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PALIT_SUB_VEN, PALIT_RTX3070_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3070_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Gamerock LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3070_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Ti GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_GAMING_PRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Gamerock LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 12GB GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMINGPRO_12G_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090 Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, PALIT_SUB_VEN, PALIT_RTX3090TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti SUPER GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4080 GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4080 SUPER GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PALIT_SUB_VEN, PALIT_RTX4090_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5060 Ti White OC 16GB", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, PALIT_SUB_VEN, PALIT_RTX5060TI_WHITE_OC_16G_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, PALIT_SUB_VEN, PALIT_RTX5070_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 Ti GameRock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PALIT_SUB_VEN, PALIT_RTX5070TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 Ti GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PALIT_SUB_VEN, PALIT_RTX5070TI_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 Ti GamingPro-S", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PALIT_SUB_VEN, PALIT_RTX5070TI_GAMINGPRO_S_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5080 GameRock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PALIT_SUB_VEN, PALIT_RTX5080_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5080 GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PALIT_SUB_VEN, PALIT_RTX5080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, PALIT_SUB_VEN, PALIT_RTX5090_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("NVIDIA GeForce RTX 2060 SUPER", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_TU106_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("NVIDIA GeForce RTX 2080 SUPER", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_DEV, 0x49);
@@ -1,161 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_PNYGPU.cpp |
| |
| RGBController for PNY Turing GPU |
| |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_PNYGPU.h"
/**------------------------------------------------------------------*\
@name PNY GPU
@category GPU
@type I2C
@save :x:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectPNYGPUControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_PNYGPU::RGBController_PNYGPU(PNYGPUController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = name.substr(0, name.find(' '));
description = "PNY/Palit RGB GPU Device";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
mode Off;
Off.name = "Off";
Off.value = PNY_GPU_MODE_OFF;
Off.flags = 0;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Direct;
Direct.name = "Direct";
Direct.value = PNY_GPU_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR| MODE_FLAG_HAS_BRIGHTNESS;
Direct.brightness = 255;
Direct.brightness_min = 0;
Direct.brightness_max = 100;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Cycle;
Cycle.name = "Cycle";
Cycle.value = PNY_GPU_MODE_CYCLE;
Cycle.flags = MODE_FLAG_HAS_SPEED;
Cycle.speed = 3;
Cycle.speed_max = 0;
Cycle.speed_max = 100;
Cycle.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Cycle);
mode Strobe;
Strobe.name = "Strobe";
Strobe.value = PNY_GPU_MODE_STROBE;
Strobe.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Strobe.speed = 2;
Strobe.speed_max = 0;
Strobe.speed_max = 255;
Strobe.brightness = 255;
Strobe.brightness_min = 0;
Strobe.brightness_max = 100;
Strobe.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Strobe);
SetupZones();
// Initialize active mode
active_mode = 0;
}
RGBController_PNYGPU::~RGBController_PNYGPU()
{
Shutdown();
delete controller;
}
void RGBController_PNYGPU::SetupZones()
{
/*---------------------------------------------------------*\
| This device only has one LED, so create a single zone and |
| LED for it |
\*---------------------------------------------------------*/
zone* new_zone = new zone();
led* new_led = new led();
new_zone->name = "GPU Zone";
new_zone->type = ZONE_TYPE_SINGLE;
new_zone->leds_min = 1;
new_zone->leds_max = 1;
new_zone->leds_count = 1;
new_led->name = "GPU LED";
/*---------------------------------------------------------*\
| Push the zone and LED on to device vectors |
\*---------------------------------------------------------*/
leds.push_back(*new_led);
zones.push_back(*new_zone);
SetupColors();
}
void RGBController_PNYGPU::DeviceUpdateLEDs()
{
DeviceUpdateMode();
}
void RGBController_PNYGPU::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_PNYGPU::DeviceUpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_PNYGPU::DeviceUpdateMode()
{
RGBColor color = colors[0];
unsigned char r = RGBGetRValue(color);
unsigned char g = RGBGetGValue(color);
unsigned char b = RGBGetBValue(color);
unsigned char speed, brightness;
switch(modes[active_mode].value)
{
case PNY_GPU_MODE_OFF:
controller->SetOff();
break;
case PNY_GPU_MODE_DIRECT:
brightness = modes[active_mode].brightness;
controller->SetDirect(r, g, b, brightness);
break;
case PNY_GPU_MODE_CYCLE:
speed = modes[active_mode].speed;
controller->SetCycle(speed);
break;
case PNY_GPU_MODE_STROBE:
speed = modes[active_mode].speed;
brightness = modes[active_mode].brightness;
controller->SetStrobe(r, g, b, speed, brightness);
break;
default:
break;
}
}
@@ -1,46 +0,0 @@
/*---------------------------------------------------------*\
| PalitGPUController.cpp |
| |
| Driver for Palit GPU |
| |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "PalitGPUController.h"
PalitGPUController::PalitGPUController(i2c_smbus_interface* bus, palit_dev_id dev, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
}
PalitGPUController::~PalitGPUController()
{
}
std::string PalitGPUController::GetDeviceLocation()
{
std::string return_string(bus->info.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 PalitGPUController::GetName()
{
return(name);
}
void PalitGPUController::SetDirect(unsigned char red, unsigned char green, unsigned char blue)
{
// NvAPI_I2CWriteEx: Dev: 0x08 RegSize: 0x01 Reg: 0x03 Size: 0x04 Data: 0xFF 0x00 0x00 0xFF
uint8_t values[] = {red, green, blue, 0xFF};
bus->i2c_smbus_write_i2c_block_data(dev, PALIT_GPU_REG_LED, sizeof(values), values);
}
@@ -1,44 +0,0 @@
/*---------------------------------------------------------*\
| PalitGPUController.h |
| |
| Driver for Palit GPU |
| |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
typedef unsigned char palit_dev_id;
enum
{
PALIT_GPU_MODE_DIRECT = 0x00,
};
enum
{
PALIT_GPU_REG_LED = 0x03,
};
class PalitGPUController
{
public:
PalitGPUController(i2c_smbus_interface* bus, palit_dev_id dev, std::string dev_name);
~PalitGPUController();
std::string GetDeviceLocation();
std::string GetName();
void SetDirect(unsigned char red, unsigned char green, unsigned char blue);
private:
i2c_smbus_interface* bus;
palit_dev_id dev;
std::string name;
};
@@ -4,6 +4,9 @@
| Detector for Palit GPU |
| |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| TheRogueZeta 05 Nov 2020 |
| KundaPanda 04 Jan 2021 |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -13,21 +16,24 @@
#include <stdlib.h>
#include "DetectionManager.h"
#include "i2c_smbus.h"
#include "PalitGPUController.h"
#include "PalitGPUv1Controller.h"
#include "PalitGPUv2Controller.h"
#include "pci_ids.h"
#include "RGBController_PalitGPU.h"
#include "RGBController_PalitGPUv1.h"
#include "RGBController_PalitGPUv2.h"
DetectedControllers DetectPalitGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
bool TestForPalitGPUv1Controller(i2c_smbus_interface* bus, uint8_t i2c_addr)
{
DetectedControllers detected_controllers;
bool pass = false;
if(bus->info.port_id == 1)
{
/*-----------------------------------------------------*\
| Check for PALIT string |
\*-----------------------------------------------------*/
/*-------------------------------------------------*\
| Check for PALIT string, which is known to work |
| for Palit variants |
\*-------------------------------------------------*/
const uint8_t palit[] = {'P', 'A', 'L', 'I', 'T'};
bool match = true;
bool match = true;
for(size_t i = 0; i < sizeof(palit); i++)
{
@@ -39,20 +45,151 @@ DetectedControllers DetectPalitGPUControllers(i2c_smbus_interface* bus, uint8_t
}
}
/*-------------------------------------------------*\
| If PALIT string fails, try a quick write to the |
| target address, which is known to work for |
| Gainward variants |
\*-------------------------------------------------*/
if(match)
{
PalitGPUController* controller = new PalitGPUController(bus, i2c_addr, name);
RGBController_PalitGPU* rgb_controller = new RGBController_PalitGPU(controller);
DetectionManager::get()->RegisterRGBController(rgb_controller);
pass = true;
}
else
{
switch(i2c_addr)
{
case 0x08:
pass = bus->i2c_smbus_write_quick(i2c_addr, I2C_SMBUS_WRITE);
break;
}
}
}
return(pass);
}
bool TestForPalitGPUv2Controller(i2c_smbus_interface* bus, uint8_t i2c_addr)
{
bool pass = false;
if(bus->info.port_id == 1)
{
switch(i2c_addr)
{
case 0x49:
s32 data = bus->i2c_smbus_read_byte_data(i2c_addr, 0x0);
s32 mode_data = bus->i2c_smbus_read_byte_data(i2c_addr, 0xe0);
pass = (data == 0x0) && (mode_data < 0x5);
break;
}
}
return(pass);
}
DetectedControllers DetectPalitGPUv1Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
DetectedControllers detected_controllers;
if(TestForPalitGPUv1Controller(bus, i2c_addr))
{
PalitGPUv1Controller* controller = new PalitGPUv1Controller(bus, i2c_addr, name);
RGBController_PalitGPUv1* rgb_controller = new RGBController_PalitGPUv1(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1060", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1060_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1070", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1070_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1070 Ti", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1070TI_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1080", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1080 Ti", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080TI_DEV, 0x08);
DetectedControllers DetectPalitGPUv2Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
DetectedControllers detected_controllers;
if(TestForPalitGPUv2Controller(bus, i2c_addr))
{
PalitGPUv2Controller* controller = new PalitGPUv2Controller(bus, i2c_addr, name);
RGBController_PalitGPUv2* rgb_controller = new RGBController_PalitGPUv2(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
/*---------------------------------------------------------*\
| Register detectors for Palit GPU controllers |
| Uses the unified PalitGPUv1Controllers for all V1 protocol|
| devices ( Gainward and Palit branded) |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1060", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1060_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1070", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1070_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1070 Ti", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1070TI_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1080", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1080 Ti", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080TI_DEV, 0x08);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1080 Phoenix", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080_PHOENIX, 0x08);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1080 Ti Phoenix", DetectPalitGPUv1Controllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080TI_PHOENIX, 0x08);
/*---------------------------------------------------------*\
| Register detectors for Palit V2 GPU controllers |
| (Gainward and PNY branded cards) |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1660 SUPER Ghost", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1660S_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 2070 SUPER Phantom", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 2080 Phoenix GS", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2080_A_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3060 Pegasus 12G", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Phantom", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3070_PHANTOM, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Phoenix", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Ti Phoenix", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070TI_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Phoenix", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Ti Phoenix", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080TI_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Phoenix", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3090_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Ti Phantom", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3090TI_PHANTOM, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 4080 Phantom GS", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4080_PHANTOM_GS_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 4090 Phantom", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4090_PHANTOM_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 5080 Phoenix", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_5080_PHOENIX_SUB_DEV, 0x49);
/*---------------------------------------------------------*\
| PNY GPU controllers (also Palit-manufactured) |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 2060 XLR8 OC EDITION", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, PNY_SUB_VEN, PNY_RTX_2060_XLR8_OC_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3060 XLR8 Revel EPIC-X", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3070 XLR8 Revel EPIC-X", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3070 XLR8 Revel EPIC-X LHR", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3080 XLR8 Revel EPIC-X", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PNY_SUB_VEN, PNY_RTX_3080_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3080 Ti XLR8 Revel EPIC-X", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PNY_SUB_VEN, PNY_RTX_3080TI_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3090 XLR8 Revel EPIC-X", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PNY_SUB_VEN, PNY_RTX_3090_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49);
/*---------------------------------------------------------*\
| Palit GPU controllers detected via PNY detector |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 2070 SUPER Jetstream", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PALIT_SUB_VEN, PALIT_RTX3060_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 LHR", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3060_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, PALIT_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti LHR", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PALIT_SUB_VEN, NVIDIA_RTX3060TI_LHR_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PALIT_SUB_VEN, PALIT_RTX3070_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 LHR", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3070_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Ti", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 LHR", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_LHR_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Ti", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090 Gamerock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090 Ti Gamerock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, PALIT_SUB_VEN, PALIT_RTX3090TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti Gamerock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti SUPER GamingPro", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4080 GamingPro", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4080 SUPER GamingPro", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4090 Gamerock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PALIT_SUB_VEN, PALIT_RTX4090_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5060 Ti White OC 16GB", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, PALIT_SUB_VEN, PALIT_RTX5060TI_WHITE_OC_16G_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 GamingPro", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, PALIT_SUB_VEN, PALIT_RTX5070_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 Ti GameRock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PALIT_SUB_VEN, PALIT_RTX5070TI_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 Ti GamingPro", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PALIT_SUB_VEN, PALIT_RTX5070TI_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 Ti GamingPro-S", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PALIT_SUB_VEN, PALIT_RTX5070TI_GAMINGPRO_S_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5080 GameRock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PALIT_SUB_VEN, PALIT_RTX5080_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5080 GamingPro", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PALIT_SUB_VEN, PALIT_RTX5080_GAMINGPRO_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5090 Gamerock", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, PALIT_SUB_VEN, PALIT_RTX5090_GAMEROCK_SUB_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("NVIDIA GeForce RTX 2060 SUPER", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_TU106_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("NVIDIA GeForce RTX 2080 SUPER", DetectPalitGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_DEV, 0x49);
@@ -0,0 +1,77 @@
/*---------------------------------------------------------*\
| PalitGPUv1Controller.cpp |
| |
| Driver for Palit v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "PalitGPUv1Controller.h"
PalitGPUv1Controller::PalitGPUv1Controller(i2c_smbus_interface* bus, palit_gpu_dev_id dev, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
}
PalitGPUv1Controller::~PalitGPUv1Controller()
{
}
std::string PalitGPUv1Controller::GetDeviceLocation()
{
std::string return_string(bus->info.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 PalitGPUv1Controller::GetDeviceName()
{
return(name);
}
unsigned char PalitGPUv1Controller::GetLEDRed()
{
/*-----------------------------------------------------*\
| Read red color from register 0x03 |
\*-----------------------------------------------------*/
return(bus->i2c_smbus_read_byte_data(dev, PALIT_V1_RED_REGISTER));
}
unsigned char PalitGPUv1Controller::GetLEDGreen()
{
/*-----------------------------------------------------*\
| Read green color from register 0x04 |
\*-----------------------------------------------------*/
return(bus->i2c_smbus_read_byte_data(dev, PALIT_V1_RED_REGISTER + 1));
}
unsigned char PalitGPUv1Controller::GetLEDBlue()
{
/*-----------------------------------------------------*\
| Read blue color from register 0x05 |
\*-----------------------------------------------------*/
return(bus->i2c_smbus_read_byte_data(dev, PALIT_V1_RED_REGISTER + 2));
}
void PalitGPUv1Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue)
{
/*-----------------------------------------------------*\
| Write RGB colors and control byte using individual |
| writes to registers 0x03, 0x04, 0x05, 0x06 |
\*-----------------------------------------------------*/
bus->i2c_smbus_write_byte_data(dev, PALIT_V1_RED_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, PALIT_V1_RED_REGISTER + 1, green);
bus->i2c_smbus_write_byte_data(dev, PALIT_V1_RED_REGISTER + 2, blue);
bus->i2c_smbus_write_byte_data(dev, PALIT_V1_RED_REGISTER + 3, 0xFF);
}
@@ -1,9 +1,10 @@
/*---------------------------------------------------------*\
| GainwardGPUv1Controller.h |
| PalitGPUv1Controller.h |
| |
| Driver for Gainward v1 GPU |
| Driver for Palit v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -14,22 +15,19 @@
#include <string>
#include "i2c_smbus.h"
typedef unsigned char gainward_gpu_dev_id;
typedef unsigned char palit_gpu_dev_id;
enum
{
/* RGB Registers */
GAINWARD_RED_REGISTER = 0x03, /* Red Register */
GAINWARD_GREEN_REGISTER = 0x04, /* Green Register */
GAINWARD_BLUE_REGISTER = 0x05, /* Blue Register */
GAINWARD_06_REGISTER = 0x06, /* Unknown (Brightness/Mode?) Register */
PALIT_V1_RED_REGISTER = 0x03, /* Red Register */
};
class GainwardGPUv1Controller
class PalitGPUv1Controller
{
public:
GainwardGPUv1Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id, std::string dev_name);
~GainwardGPUv1Controller();
PalitGPUv1Controller(i2c_smbus_interface* bus, palit_gpu_dev_id, std::string dev_name);
~PalitGPUv1Controller();
std::string GetDeviceLocation();
std::string GetDeviceName();
@@ -38,13 +36,9 @@ public:
unsigned char GetLEDGreen();
unsigned char GetLEDBlue();
void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue);
void SetMode();
unsigned char GainwardGPURegisterRead(unsigned char reg);
void GainwardGPURegisterWrite(unsigned char reg, unsigned char val);
private:
i2c_smbus_interface * bus;
gainward_gpu_dev_id dev;
palit_gpu_dev_id dev;
std::string name;
};
@@ -0,0 +1,154 @@
/*---------------------------------------------------------*\
| PalitGPUv2Controller.cpp |
| |
| Driver for Palit v2 GPU (merged from Gainward v2 and |
| PNY controllers) |
| |
| KundaPanda 04 Jan 2021 |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "PalitGPUv2Controller.h"
PalitGPUv2Controller::PalitGPUv2Controller(i2c_smbus_interface* bus, palit_gpu_dev_id dev, std::string dev_name)
{
this->bus = bus;
this->dev = dev;
this->name = dev_name;
}
PalitGPUv2Controller::~PalitGPUv2Controller()
{
}
std::string PalitGPUv2Controller::GetDeviceLocation()
{
std::string return_string(bus->info.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 PalitGPUv2Controller::GetDeviceName()
{
return(name);
}
unsigned char PalitGPUv2Controller::GetLEDRed()
{
return(bus->i2c_smbus_read_byte_data(dev, PALIT_V2_RED_REGISTER));
}
unsigned char PalitGPUv2Controller::GetLEDGreen()
{
return(bus->i2c_smbus_read_byte_data(dev, PALIT_V2_GREEN_REGISTER));
}
unsigned char PalitGPUv2Controller::GetLEDBlue()
{
return(bus->i2c_smbus_read_byte_data(dev, PALIT_V2_BLUE_REGISTER));
}
void PalitGPUv2Controller::WriteI2CData(u8 command, u8 length, u8* data)
{
for (u8 i = 0; i < length; i++)
{
bus->i2c_smbus_write_byte_data(dev, command + i, data[i]);
}
}
void PalitGPUv2Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue, unsigned char color_register)
{
switch (color_register)
{
default:
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_RED_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_GREEN_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BLUE_REGISTER, blue);
break;
case PALIT_V2_COLOR_REGISTER_SECONDARY:
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_RED_SECONDARY_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_GREEN_SECONDARY_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BLUE_SECONDARY_REGISTER, blue);
break;
case PALIT_V2_COLOR_REGISTER_TERTIARY:
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_RED_TERTIARY_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_GREEN_TERTIARY_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BLUE_TERTIARY_REGISTER, blue);
break;
}
}
void PalitGPUv2Controller::SetMode(unsigned char mode, unsigned char speed, unsigned char control_mode)
{
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_MODE_REGISTER, mode);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_CONTROL_REGISTER, control_mode);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_SPEED_REGISTER, speed);
}
void PalitGPUv2Controller::SetDirection(unsigned char direction)
{
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_MODE_DIRECTION_REGISTER, direction);
}
void PalitGPUv2Controller::SetBreathingSpeed(unsigned int speed)
{
unsigned char lower = speed & 0xFF;
unsigned char upper = (speed >> 2 * 4) & 0xFF;
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BREATHE_SPEED_REGISTER_A, lower);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BREATHE_SPEED_SECONDARY_REGISTER_A, lower);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BREATHE_SPEED_REGISTER_B, upper);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BREATHE_SPEED_SECONDARY_REGISTER_B, upper);
}
void PalitGPUv2Controller::SetOff()
{
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_MODE_REGISTER, 0);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_CONTROL_REGISTER, 0x00);
}
void PalitGPUv2Controller::SetCycle(unsigned char speed)
{
u8 loop[] = {
0x01, // Direction
0x00, // ??
speed, // Speed
0x1F // Somehow related to speed
};
loop[2] = speed;
WriteI2CData(PALIT_V2_MODE_REGISTER, sizeof(loop), loop);
}
void PalitGPUv2Controller::SetStrobe(unsigned char r, unsigned char g, unsigned char b, unsigned char speed, unsigned char brightness)
{
u8 strobe[] = {
0x02, // Strobe
0x00, // Rise speed
speed, // Cycle length/2
0x00, // Off delay
r, // R
g, // G
b, // B
brightness, // Peak brightness
0x05 // Fade speed
};
WriteI2CData(PALIT_V2_MODE_REGISTER, sizeof(strobe), strobe);
}
void PalitGPUv2Controller::SetDirect(unsigned char red, unsigned char green, unsigned char blue, unsigned char brightness)
{
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_MODE_REGISTER, 0);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_CONTROL_REGISTER, 0x01);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_RED_REGISTER, red);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BLUE_REGISTER, blue);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_GREEN_REGISTER, green);
bus->i2c_smbus_write_byte_data(dev, PALIT_V2_BRIGHTNESS_REGISTER, brightness);
}
@@ -0,0 +1,115 @@
/*---------------------------------------------------------*\
| PalitGPUv2Controller.h |
| |
| Driver for Palit v2 GPU (merged from Gainward v2 and |
| PNY controllers) |
| |
| KundaPanda 04 Jan 2021 |
| KendallMorgan 17 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "i2c_smbus.h"
typedef unsigned char palit_gpu_dev_id;
enum
{
/* Control Registers */
PALIT_V2_CONTROL_REGISTER = 0x60, /* Control Register (direct mode / software control) */
/* Breathing speed registers */
PALIT_V2_BREATHE_SPEED_REGISTER_A = 0x62, /* Lower part of speed control for breathe effect */
PALIT_V2_BREATHE_SPEED_REGISTER_B = 0x63, /* Upper part of speed control for breathe effect */
PALIT_V2_BREATHE_SPEED_SECONDARY_REGISTER_A = 0x64, /* Lower part of speed control for breathe effect - prob. secondary color */
PALIT_V2_BREATHE_SPEED_SECONDARY_REGISTER_B = 0x65, /* Upper part of speed control for breathe effect - prob. secondary color */
/* RGB Registers - Primary color */
PALIT_V2_RED_REGISTER = 0x6C, /* Red Register */
PALIT_V2_GREEN_REGISTER = 0x6D, /* Green Register */
PALIT_V2_BLUE_REGISTER = 0x6E, /* Blue Register */
PALIT_V2_BRIGHTNESS_REGISTER = 0x6F, /* Brightness Register */
/* RGB Registers - Secondary color */
PALIT_V2_RED_SECONDARY_REGISTER = 0x70, /* Red Register 2 */
PALIT_V2_GREEN_SECONDARY_REGISTER = 0x71, /* Green Register 2 */
PALIT_V2_BLUE_SECONDARY_REGISTER = 0x72, /* Blue Register 2 */
/* Mode Registers */
PALIT_V2_MODE_REGISTER = 0xE0, /* Mode Register */
PALIT_V2_MODE_DIRECTION_REGISTER = 0xE1, /* Mode direction Register */
PALIT_V2_SPEED_REGISTER = 0xE2, /* Mode speed Register */
/* RGB Registers - Tertiary color */
PALIT_V2_RED_TERTIARY_REGISTER = 0xE4, /* Red Register 3 */
PALIT_V2_GREEN_TERTIARY_REGISTER = 0xE5, /* Green Register 3 */
PALIT_V2_BLUE_TERTIARY_REGISTER = 0xE6, /* Blue Register 3 */
};
/* Mode values for the hardware mode register */
enum
{
PALIT_V2_MODE_OFF = 0x00,
PALIT_V2_MODE_STATIC = 0x00,
PALIT_V2_MODE_CYCLE = 0x01,
PALIT_V2_MODE_STROBE = 0x02,
};
/* Mode identifiers for RGBController (unique values for switch statements) */
enum
{
PALIT_V2_MODE_ID_OFF = 0,
PALIT_V2_MODE_ID_DIRECT = 1,
PALIT_V2_MODE_ID_BREATHING = 2,
PALIT_V2_MODE_ID_CYCLE = 3,
PALIT_V2_MODE_ID_STROBE = 4,
};
enum
{
PALIT_V2_COLOR_REGISTER_PRIMARY,
PALIT_V2_COLOR_REGISTER_SECONDARY,
PALIT_V2_COLOR_REGISTER_TERTIARY,
};
enum
{
/* Software controlled direct mode */
PALIT_V2_STATIC_SOFTWARE = 0x01,
/* GPU controlled direct mode with breathing effect */
PALIT_V2_STATIC_BREATHING = 0x22,
};
class PalitGPUv2Controller
{
public:
PalitGPUv2Controller(i2c_smbus_interface* bus, palit_gpu_dev_id, std::string dev_name);
~PalitGPUv2Controller();
std::string GetDeviceLocation();
std::string GetDeviceName();
unsigned char GetLEDRed();
unsigned char GetLEDGreen();
unsigned char GetLEDBlue();
void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue, unsigned char color_register = PALIT_V2_COLOR_REGISTER_PRIMARY);
void SetMode(unsigned char mode, unsigned char speed, unsigned char direct_mode = PALIT_V2_STATIC_SOFTWARE);
void SetBreathingSpeed(unsigned int speed);
void SetDirection(unsigned char direction);
void SetOff();
void SetCycle(unsigned char speed);
void SetStrobe(unsigned char r, unsigned char g, unsigned char b, unsigned char speed, unsigned char brightness);
void SetDirect(unsigned char red, unsigned char green, unsigned char blue, unsigned char brightness);
private:
i2c_smbus_interface * bus;
palit_gpu_dev_id dev;
std::string name;
void WriteI2CData(u8 command, u8 length, u8* data);
};
@@ -1,112 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_PalitGPU.cpp |
| |
| RGBController for Palit GPU |
| |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_PalitGPU.h"
/**------------------------------------------------------------------*\
@name Palit GPU
@category GPU
@type I2C
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectPalitGPUControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_PalitGPU::RGBController_PalitGPU(PalitGPUController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetName();
vendor = "Palit";
description = "Legacy Palit RGB GPU Device";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
mode Direct;
Direct.name = "Direct";
Direct.value = PALIT_GPU_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
// Initialize active mode
active_mode = 0;
}
RGBController_PalitGPU::~RGBController_PalitGPU()
{
Shutdown();
delete controller;
}
void RGBController_PalitGPU::SetupZones()
{
/*---------------------------------------------------------*\
| This device only has one LED, so create a single zone and |
| LED for it |
\*---------------------------------------------------------*/
zone* new_zone = new zone();
led* new_led = new led();
new_zone->name = "GPU Zone";
new_zone->type = ZONE_TYPE_SINGLE;
new_zone->leds_min = 1;
new_zone->leds_max = 1;
new_zone->leds_count = 1;
new_led->name = "GPU LED";
/*---------------------------------------------------------*\
| Push the zone and LED on to device vectors |
\*---------------------------------------------------------*/
leds.push_back(*new_led);
zones.push_back(*new_zone);
SetupColors();
}
void RGBController_PalitGPU::DeviceUpdateLEDs()
{
DeviceUpdateMode();
}
void RGBController_PalitGPU::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_PalitGPU::DeviceUpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_PalitGPU::DeviceUpdateMode()
{
RGBColor color = colors[0];
unsigned char r = RGBGetRValue(color);
unsigned char g = RGBGetGValue(color);
unsigned char b = RGBGetBValue(color);
switch(modes[active_mode].value)
{
case PALIT_GPU_MODE_DIRECT:
controller->SetDirect(r, g, b);
break;
default:
break;
}
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_PalitGPU.h |
| |
| RGBController for Palit GPU |
| |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "PalitGPUController.h"
class RGBController_PalitGPU : public RGBController
{
public:
RGBController_PalitGPU(PalitGPUController* controller_ptr);
~RGBController_PalitGPU();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
PalitGPUController* controller;
};
@@ -0,0 +1,110 @@
/*---------------------------------------------------------*\
| RGBController_PalitGPUv1.cpp |
| |
| RGBController for Palit v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_PalitGPUv1.h"
/**------------------------------------------------------------------*\
@name Palit GPU v1
@category GPU
@type I2C
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectPalitGPUControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_PalitGPUv1::RGBController_PalitGPUv1(PalitGPUv1Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "Palit";
type = DEVICE_TYPE_GPU;
description = "Palit GPU V1 Device";
location = controller->GetDeviceLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = 1;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_PalitGPUv1::~RGBController_PalitGPUv1()
{
Shutdown();
delete controller;
}
void RGBController_PalitGPUv1::SetupZones()
{
/*-----------------------------------------------------*\
| Set up zone |
\*-----------------------------------------------------*/
zone palit_gpu_zone;
palit_gpu_zone.name = "GPU";
palit_gpu_zone.type = ZONE_TYPE_SINGLE;
palit_gpu_zone.leds_min = 1;
palit_gpu_zone.leds_max = 1;
palit_gpu_zone.leds_count = 1;
zones.push_back(palit_gpu_zone);
/*-----------------------------------------------------*\
| Set up LED |
\*-----------------------------------------------------*/
led palit_gpu_led;
palit_gpu_led.name = "GPU";
leds.push_back(palit_gpu_led);
SetupColors();
/*-----------------------------------------------------*\
| Initialize color |
\*-----------------------------------------------------*/
unsigned char red = controller->GetLEDRed();
unsigned char grn = controller->GetLEDGreen();
unsigned char blu = controller->GetLEDBlue();
colors[0] = ToRGBColor(red, grn, blu);
}
void RGBController_PalitGPUv1::DeviceUpdateLEDs()
{
for(std::size_t led = 0; led < colors.size(); led++)
{
unsigned char red = RGBGetRValue(colors[led]);
unsigned char grn = RGBGetGValue(colors[led]);
unsigned char blu = RGBGetBValue(colors[led]);
controller->SetLEDColors(red, grn, blu);
}
}
void RGBController_PalitGPUv1::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_PalitGPUv1::DeviceUpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_PalitGPUv1::DeviceUpdateMode()
{
}
@@ -1,35 +1,36 @@
/*---------------------------------------------------------*\
| RGBController_GainwardGPUv1.h |
| |
| RGBController for Gainward v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "GainwardGPUv1Controller.h"
class RGBController_GainwardGPUv1 : public RGBController
{
public:
RGBController_GainwardGPUv1(GainwardGPUv1Controller* controller_ptr);
~RGBController_GainwardGPUv1();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
GainwardGPUv1Controller* controller;
int GetDeviceMode();
};
/*---------------------------------------------------------*\
| RGBController_PalitGPUv1.h |
| |
| RGBController for Palit v1 GPU |
| |
| TheRogueZeta 05 Nov 2020 |
| Manatsawin Hanmongkolchai 11 Apr 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "PalitGPUv1Controller.h"
class RGBController_PalitGPUv1 : public RGBController
{
public:
RGBController_PalitGPUv1(PalitGPUv1Controller* controller_ptr);
~RGBController_PalitGPUv1();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
PalitGPUv1Controller* controller;
int GetDeviceMode();
};

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