Compare commits

..
Author SHA1 Message Date
Adam Honse a4de85363a Add ConfigureDevice and the ability to configure device name 2026-05-31 22:55:08 -05:00
Adam Honse 5fc61d9e88 Add SetHidden SDK packet 2026-05-27 13:41:20 -05:00
Adam Honse 7ce0b51116 Use RGBControllerInterface for plugin API 2026-05-27 13:41:20 -05:00
Adam Honse 71386d9e5f Add another thread in NetworkClient for handling ProfileManager requests outside of the main listener thread, to avoid deadlocking the waiting receivers 2026-05-27 13:41:20 -05:00
Adam Honse a52766df76 Update translation files and fix some translation related issues 2026-05-27 13:41:20 -05:00
Adam Honse 3ae14c9d70 NetworkClient cleanup and internal API standardization 2026-05-27 13:41:20 -05:00
Adam Honse 41994f4291 NetworkServer cleanup and internal API standardization 2026-05-27 13:41:20 -05:00
Adam Honse 1ca10a5622 Add indication of standalone or local client mode to about page 2026-05-27 13:41:20 -05:00
Adam Honse 12a61009a7 Implement network request to get list of I2C buses so that the Get Hardware IDs dialog works in local client mode 2026-05-27 13:41:19 -05:00
Adam Honse d4effd7c13 Add option to force compact tabs and option to move tabs from left to top 2026-05-27 13:41:19 -05:00
Adam Honse bf6795a282 More LogManager cleanup, default to a log file count of 10, fix bug in log rotation 2026-05-27 13:41:19 -05:00
Adam Honse b65c1b376b Log manager SDK protocol 2026-05-27 13:41:19 -05:00
Adam Honse aadc90cace Log Console Updates 2026-05-27 13:41:19 -05:00
Adam Honse ea4029caad LogManager cleanup 2026-05-27 13:41:19 -05:00
Adam Honse c61a0d9c5a Settings Rework
* Add JSON string configuration field to RGBController to store device-specific configurations
    * This JSON string holds both configuration and schema
    * Add settings schema tracking to SettingsManager
    * Implement dynamic settings widget that generates a settings UI based on a JSON schema
    * Implement SettingsManager callback for notifying of settings changes and settings schema updates
    * Always enable Entire Device zone option and use it to enable Edit Device
    * Rename SaveSizes to SaveConfiguration in ProfileManager and Sizes.json to Configuration.json
    * Add zone flag for indicating that a zone's geometry may change, informing profile manager to ignore this check
    * Remove Theme setting and Theme Manager, as this didn't work on most setups anyways and Qt6 has proper Windows dark theming
2026-05-27 13:41:19 -05:00
Dmitry Kychanov a32a766fbb Fix losing software info upon changing language [next] 2026-05-27 13:41:19 -05:00
Dmitry Kychanov 4b359766eb Fix device tabs not applying compact mode when hotplugging 2026-05-27 13:41:19 -05:00
Adam Honse 833778f2a3 Close SDK connection if magic value is not correctly received 2026-05-27 13:41:19 -05:00
Adam Honse 4fe6e45b9f Implement size verification on RGBController set description functions 2026-05-27 13:41:19 -05:00
Adam Honse c0d64bc790 Clean up zone initialization dialog 2026-05-27 13:41:19 -05:00
Adam Honse 9924e573f1 Require local client permission for DeleteProfile, SaveProfile, UploadProfile, SetSettings, and SaveSettings operations, some general cleanup 2026-05-27 13:41:19 -05:00
Adam Honse ca23ae4452 Sanitize profile filenames 2026-05-27 13:41:19 -05:00
Adam Honse fb16226bc0 Add RescanDevices to plugin API 2026-05-27 13:41:19 -05:00
Adam Honse 763eb3e87c Implement segment groups in zone editor 2026-05-27 13:40:38 -05:00
Adam Honse 9d35d28a6a Rework server initialization
* Only create server instance if server is actually needed
    * Pass initial server host and port through ResourceManager
    * Allow setting default server host and port in Server settings
2026-05-07 17:24:46 -05:00
stephen iacovelli b4b4f3b891 Sort profiles list alphabetically 2026-05-07 17:24:46 -05:00
Adam Honse e1086712ad Organize OpenRGBSettingsPage with Group Boxes 2026-05-07 17:24:46 -05:00
Kasslim fd7ccad1e6 Correct spelling Busses -> Buses
Commits merged by Adam Honse <[email protected]>
2026-05-07 17:24:46 -05:00
诺诺 8bc1a0cb8f Add Nollie controller OS2.1 2026-05-07 17:24:46 -05:00
Adam Honse 5112224240 Initial implementation of OpenRGB SDK protocol Wireshark dissector 2026-05-07 17:24:46 -05:00
Adam Honse 5e2cc42290 Add ACK to network packets processed by NetworkServer 2026-05-07 17:24:46 -05:00
Adam Honse b1436a8435 Only update device view when RGBController::UpdateLEDs signal is sent to OpenRGBDevicePage, fix device view not refreshing if multiple LEDs are selected 2026-05-07 17:24:46 -05:00
Adam Honse a8d4e25642 Don't emit selection update on mouse click event to avoid sending unnecessary events, also only send one type of event per mouse release event. Fix LED box not being updated 2026-05-07 17:24:46 -05:00
Adam Honse 2b3638ba57 Have dummy controller shut down its background thread immediately during constructor to save resources 2026-05-07 17:24:46 -05:00
Adam Honse 78369c2a92 DeviceView code cleanup, formatting, commenting 2026-05-07 17:24:46 -05:00
Adam Honse 03ce513254 Fix selecting LEDs in device view 2026-05-07 17:24:46 -05:00
Adam Honse 18503cccc6 TabLabel sets its own tooltip so all tabs have a tooltip rather than just devices 2026-05-07 17:24:46 -05:00
Adam Honse e1d46d3bb3 Resize tabs when width is small 2026-05-07 17:24:46 -05:00
Adam Honse 0466996970 Rework adding segments with ConfigureZone 2026-05-07 17:24:46 -05:00
Adam Honse 56bd7580ba Zone and Segment type updates
* Add zone flags to indicate if fields are manually configurable and if they have been manually configured
  * Add flags field to segment type
  * Add segment flags for group start and group member
  * Add color mode support flags to zone (RGB, RBG, GRB, GBR, BRG, BGR)
  * Add color mode enum to zone
  * Update zone and segment description functions to support new fields
  * Rename the effects-only configurable size flag
  * Remove zone type and matrix map configuration from E1.31 manual configuration, use zone editor instead
  * Rework DeviceResizeZone to DeviceConfigureZone
  * Rework most ARGB controllers to allow zone customizations
  * Rework DRGBController to define devices in DRGBDevices list (similar to RazerDevices)
  * Rework NollieController to define devices in NollieDevices list (similar to RazerDevices)
2026-05-07 17:24:46 -05:00
Adam Honse ca47047bf8 Add matrix map automatic generation to matrix map editor 2026-05-07 17:24:46 -05:00
Adam Honse cc00690dd4 RGBController API changes and segment configuration updates
* Make the Get/Set RGBControler descriptor functions static
  * Add functions for getting the matrix_map_type for zone and segment matrix maps
  * Rename zone resize dialog to zone editor dialog
  * Add additional segment types
  * Add option to import segments configuration from JSON file in zone editor dialog
  * Update device view to be able to display matrix segment types
  * Add matrix map editor dialog for creating/editing segment matrix maps
  * Add option to export segments configuration to JSON file in zone editor dialog
2026-05-07 17:24:46 -05:00
Adam Honse 973311aa48 When updating existing profile without profile editor dialog, keep saved states for unavailable controllers, base color, and only update plugins already part of the existing profile 2026-05-07 17:24:46 -05:00
Adam Honse 747afdf553 When saving sizes/manual configuration, keep any existing controllers that are not currently available 2026-05-07 17:24:46 -05:00
Adam Honse 8f11f8fd97 Rework how manual configuration (previously sizes) are loaded to newly detected controllers, load active profile to newly detected controllers 2026-05-07 17:24:45 -05:00
Adam Honse 2b11f6fe07 Profile editor dialog 2026-05-07 17:24:45 -05:00
Adam Honse 94981f107b Rework API interface passed into plugins from ResourceManagerInterface to OpenRGBPluginAPIInterface 2026-05-07 17:24:45 -05:00
Adam Honse 0144a6a150 [next] Active profile tracking 2026-05-07 17:24:45 -05:00
Adam Honse 6ec8b80e65 Apply profiles server-side rather than client-side, signal active profile update, forward loaded profile to local client for plugins 2026-05-07 17:24:45 -05:00
Adam Honse ddae1ed20a Split HID and wrapped HID detector lists into specific detectors (with exact VID/PID matching) and generic detectors (with only IPU matching) and prioritize specific detectors when detecting HID devices 2026-05-07 17:24:45 -05:00
Adam Honse 70f79e97b4 Move RGBController base destructor functionality into RGBController::Shutdown() so that update thread can be stopped before deleting the controller. Shutdown() must be called in every RGBController implementation before deleting the controller. Also some fixes to the NetworkServer to avoid deadlocking and disconnect issues 2026-05-07 17:24:45 -05:00
Adam Honse d05fe1bdf1 Add detectors for filtering on IPU only (no VID/PID) 2026-05-07 17:24:45 -05:00
Adam Honse e9e99a029d Drop support for old hidapi versions that don't support usage information 2026-05-07 17:24:45 -05:00
Adam Honse 98dd494f75 Add some validity checks to mode setters and getters in RGBController 2026-05-07 17:24:45 -05:00
Adam Honse 7b7f0aa0fe [next] SDK v6: Implement client and server flags to indicate capabilities and... 2026-05-07 17:24:45 -05:00
Adam Honse 70876193cf SDK documentation updates 2026-05-07 17:24:45 -05:00
Adam Honse f47a22fb2f Expose LogManager in ResourceManager so that plugins can use it 2026-05-07 17:24:45 -05:00
Adam Honse f24b56b64f Update NetworkClient to use log manager and use common name constant in server logs 2026-05-07 17:24:45 -05:00
Adam Honse 4e70949aec Use std::string.assign when setting strings in the SDK protocol and description handlers so that string size limit is enforced, then strip out null terminators 2026-05-07 17:24:45 -05:00
Adam Honse 5133887632 Add optional HID device hotplug support (requires https://gitlab.com/OpenRGBDevelopers/hidapi-hotplug) 2026-05-07 17:24:45 -05:00
Adam Honse 45950047cb SDK v6: Use unique IDs for identifying RGBControllers in SDK protocol 2026-05-07 17:24:45 -05:00
Adam Honse a56a08411f Rework list handling in ResourceManager by having NetworkClient own its own list rather than sharing ResourceManager's list 2026-05-07 17:24:45 -05:00
Adam Honse 52f0049025 Move HID detector calls to RunHIDDetector/RunHIDWrappedDetector functions and return controller list from detector functions 2026-05-07 17:24:45 -05:00
Adam Honse f6f317d487 Detection progress SDK integration, NetworkClient callback rework 2026-05-07 17:24:45 -05:00
Adam Honse ad364871c6 Split out detection system from ResourceManager into DetectionManager
* Split detection system out into its own class, DetectionManager
    * Clean up ResourceManger's many callbacks into just two, one for detection and one general purpose
2026-05-07 17:24:45 -05:00
Adam Honse 58582202cf SDK Version 6 Updates
* SDK Protocol
    * Server sends its name to client
    * ProfileManager
      * Rename existing profile commands
      * Add Upload Profile, Download Profile, and Get Active Profile commands
    * SettingsManager
      * Add Get, Set, and Save Settings commands
    * Add zone::active_mode, zone::mode fields for zone-specific modes
    * Add NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE packet for updating zone modes
    * Add segment::matrix_map to segment packet
    * Add NET_PACKET_ID_RGBCONTROLLER_SIGNALUPDATE packet for passing SignalUpdate signal from server to clients
  * NetworkServer
    * Formatting cleanup
    * Use per-controller threads for handling NetworkServer controller-specific packets to avoid delays from controller mutexes
  * NetworkClient
    * Formatting cleanup
  * RGBController
    * Clean up and modularize descriptor functions
2026-05-07 17:24:44 -05:00
Adam Honse 57cde755c1 Rework Profiles to use JSON format
* Update OpenRGB Plugin Interface to include functions for loading/saving profile JSON data into OpenRGB profiles
    * Update ProfileManager to handle auto-load profiles (Exit, Open, Resume, Suspend) and move their settings to ProfileManager section
    * Update ProfileManager to store profiles in "profiles" folder in .json format
    * Update ProfileManager to store size profile in sizes.json
    * Update ProfileManager to perform device UpdateMode/UpdateColors when loading profile
    * Code cleanup of ProfileManager and profile-related code
2026-05-07 17:24:44 -05:00
Adam Honse b0c7dba441 RGBController API Overhaul
* Reorganize and clean up RGBController API functions
    * Add functions to get protected RGBController member values
    * Make NetworkClient, ProfileManager, and ResourceManager friend classes so they can access protected members
    * Protected previously-public RGBController members
        * Information strings (name, vendor, description, version, serial location)
        * Device type
        * Active mode
        * Flags
        * LEDs vector
        * LED alternate names vector
        * Modes vector
        * Colors vector
        * Zones vector
    * Add CONTROLLER_FLAG_HIDDEN to allow plugins to hide controllers from control GUI
    * Add update reason codes to RGBController update callback and signal updates on more RGBController events
    * Add loop zone types and segmented zone type
    * Add matrix map field to segments
    * Rework matrix_map_type from using pointers to vector to prevent memory leaks
    * Rework KeyboardLayoutManager to return new matrix_map_type
    * Add access mutex to RGBController API
    * Add per-zone modes ot RGBController API
    * Add JSON description functions to RGBController API
2026-05-07 17:24:44 -05:00
Adam Honse d763f7ecc7 Move plugin SDK integration from callback into plugin API and PluginManager 2026-05-07 17:24:44 -05:00
Adam Honse 4ec4df8741 Update Plugin API to 5 and SDK Protocol to 6 2026-05-07 17:24:44 -05:00
Adam Honse 5d055d30a3 Update default builds to Qt6
* Update Debian packages to use Qt6
  * Update Fedora packages to use Qt6
  * Update default AppImage builds to use Qt6
  * Update default Windows builds to use Qt6
  * Update default MacOS builds to use Qt6
2026-05-07 17:24:44 -05:00
Adam Honse fc73fe0b4c Revert "Nollie 2.1 firmware for Master"
This reverts commit 07e7feca56.
2026-05-07 17:24:44 -05:00
405 changed files with 10489 additions and 48043 deletions
-15
View File
@@ -119,21 +119,6 @@ bool AutoStart::IsAutoStartEnabled()
std::string AutoStart::GetExePath()
{
/*-----------------------------------------------------*\
| When running from an AppImage, the AppImage runtime |
| sets the APPIMAGE environment variable to the path of |
| the AppImage file itself. /proc/self/exe would |
| instead point at the extracted binary inside the |
| temporary squashfs mount, which disappears once the |
| AppImage is closed, so prefer APPIMAGE when it is set |
\*-----------------------------------------------------*/
const char* appimage_path = getenv("APPIMAGE");
if(appimage_path != NULL)
{
return(std::string(appimage_path));
}
/*-----------------------------------------------------*\
| Create the OpenRGB executable path |
\*-----------------------------------------------------*/
@@ -0,0 +1,66 @@
/*---------------------------------------------------------*\
| A4TechDetector.cpp |
| |
| Detector for A4Tech Devices |
| |
| Chris M (Dr_No) 30 Jun 2022 |
| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "BloodyB820RController.h"
#include "BloodyMouseController.h"
#include "DetectionManager.h"
#include "RGBController_BloodyB820R.h"
#include "RGBController_BloodyMouse.h"
/*---------------------------------------------------------*\
| A4 Tech USB vendor ID |
\*---------------------------------------------------------*/
#define A4_TECH_VID 0x09DA
DetectedControllers DetectA4TechMouseControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
BloodyMouseController* controller = new BloodyMouseController(dev, info->path, info->product_id, name);
RGBController_BloodyMouse* rgb_controller = new RGBController_BloodyMouse(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
DetectedControllers DetectBloodyB820R(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
BloodyB820RController* controller = new BloodyB820RController(dev, info->path, name);
RGBController_BloodyB820R* rgb_controller = new RGBController_BloodyB820R(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529);
REGISTER_HID_DETECTOR_IPU("Bloody W70 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W70_MAX_PID, 2, 0xFF33, 0x0518);
REGISTER_HID_DETECTOR_IPU("Bloody W90 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_MAX_PID, 2, 0xFF33, 0x053D);
REGISTER_HID_DETECTOR_IPU("Bloody W90 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_PRO_PID, 2, 0xFF33, 0x054D);
REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009);
REGISTER_HID_DETECTOR_IPU("Bloody B820R", DetectBloodyB820R, A4_TECH_VID, BLOODY_B820R_PID, 2, 0xFF52, 0x0210);
@@ -1,40 +0,0 @@
/*---------------------------------------------------------*\
| BloodyB820RControllerDetect.cpp |
| |
| Detector for Bloody B820R Devices |
| |
| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "BloodyB820RController.h"
#include "DetectionManager.h"
#include "RGBController_BloodyB820R.h"
/*---------------------------------------------------------*\
| A4 Tech USB vendor ID |
\*---------------------------------------------------------*/
#define A4_TECH_VID 0x09DA
DetectedControllers DetectBloodyB820R(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
BloodyB820RController* controller = new BloodyB820RController(dev, info->path, name);
RGBController_BloodyB820R* rgb_controller = new RGBController_BloodyB820R(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Bloody B820R", DetectBloodyB820R, A4_TECH_VID, BLOODY_B820R_PID, 2, 0xFF52, 0x0210);
@@ -1,44 +0,0 @@
/*---------------------------------------------------------*\
| BloodyMouseControllerDetect.cpp |
| |
| Detector for Bloody Mouse Devices |
| |
| Chris M (Dr_No) 30 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "BloodyMouseController.h"
#include "DetectionManager.h"
#include "RGBController_BloodyMouse.h"
/*---------------------------------------------------------*\
| A4 Tech USB vendor ID |
\*---------------------------------------------------------*/
#define A4_TECH_VID 0x09DA
DetectedControllers DetectBloodyMouseControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
BloodyMouseController* controller = new BloodyMouseController(dev, info->path, info->product_id, name);
RGBController_BloodyMouse* rgb_controller = new RGBController_BloodyMouse(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529);
REGISTER_HID_DETECTOR_IPU("Bloody W70 Max", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W70_MAX_PID, 2, 0xFF33, 0x0518);
REGISTER_HID_DETECTOR_IPU("Bloody W90 Max", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W90_MAX_PID, 2, 0xFF33, 0x053D);
REGISTER_HID_DETECTOR_IPU("Bloody W90 Pro", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_W90_PRO_PID, 2, 0xFF33, 0x054D);
REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectBloodyMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009);
@@ -269,7 +269,7 @@ void RGBController_PolychromeUSB::SetupZones()
new_led.name = zones[channel_idx].name;
new_led.name.append(", LED ");
new_led.name.append(std::to_string(led_ch_idx + 1));
new_led.value = (unsigned int)channel_idx;
new_led.value = channel_idx;
leds.push_back(new_led);
}
@@ -334,14 +334,9 @@ void RGBController_PolychromeUSB::DeviceUpdateLEDs()
}
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
if(zones[zone_idx].leds_count == 0)
{
continue;
}
unsigned char set_mode = zones_info[zone_idx].mode;
if(set_mode>modes.size())
if (set_mode>modes.size())
{
set_mode = active_mode;
}
@@ -352,11 +347,6 @@ void RGBController_PolychromeUSB::DeviceUpdateLEDs()
void RGBController_PolychromeUSB::DeviceUpdateZoneLEDs(int zone)
{
if(zones[zone].leds_count == 0)
{
return;
}
unsigned char set_mode=zones_info[zone].mode;
if(set_mode > modes.size())
@@ -364,7 +354,7 @@ void RGBController_PolychromeUSB::DeviceUpdateZoneLEDs(int zone)
set_mode = active_mode;
}
controller->WriteZone((unsigned char)zone, set_mode, zones_info[zone].speed, zones[zone].colors[0], false);
controller->WriteZone(zone, set_mode, zones_info[zone].speed, zones[zone].colors[0], false);
}
void RGBController_PolychromeUSB::DeviceUpdateSingleLED(int led)
@@ -372,17 +362,12 @@ void RGBController_PolychromeUSB::DeviceUpdateSingleLED(int led)
unsigned int channel = leds[led].value;
unsigned char set_mode = zones_info[channel].mode;
if(zones[channel].leds_count == 0)
{
return;
}
if(set_mode > modes.size())
{
set_mode = active_mode;
}
controller->WriteZone((unsigned char)channel, set_mode, zones_info[channel].speed, zones[channel].colors[0], false);
controller->WriteZone(channel, set_mode, zones_info[channel].speed, zones[channel].colors[0], false);
}
unsigned char RGBController_PolychromeUSB::GetDeviceMode(unsigned char zone)
@@ -1,199 +0,0 @@
/*---------------------------------------------------------*\
| ASRockGPUSMBusController.cpp |
| |
| Driver for ASRock GPU RGB controllers |
| |
| Based on SignalRGB ASRock GPU.js plugin |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "ASRockGPUSMBusController.h"
#include "LogManager.h"
#include <chrono>
#include <cstdio>
#include <cstring>
#include <thread>
using namespace std::chrono_literals;
ASRockGPUSMBusController::ASRockGPUSMBusController(i2c_smbus_interface* bus, asrock_gpu_dev_id dev, std::string name)
{
this->bus = bus;
this->dev = dev;
this->device_name = name;
this->num_channels = 0;
memset(enabled_channels, 0, sizeof(enabled_channels));
memset(led_counts, 0, sizeof(led_counts));
}
ASRockGPUSMBusController::~ASRockGPUSMBusController()
{
}
std::string ASRockGPUSMBusController::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 ASRockGPUSMBusController::GetDeviceName()
{
return(device_name);
}
bool ASRockGPUSMBusController::WriteBlock(uint8_t command, uint8_t subcommand, const uint8_t* data, uint8_t len)
{
/*-----------------------------------------------------*\
| SignalRGB packet format |
| [command, 0, subcommand, data...] |
| Uses pure I2C rather than SMBus |
\*-----------------------------------------------------*/
uint8_t packet[12];
memset(packet, 0, sizeof(packet));
packet[0] = command;
packet[1] = 0x00;
packet[2] = subcommand;
if(data != nullptr && len > 0)
{
uint8_t copy_len = (len > 9) ? 9 : len;
memcpy(&packet[3], data, copy_len);
}
int size = 12;
int result = bus->i2c_write_block(dev, size, packet);
if(result < 0)
{
LOG_DEBUG("[ASRock GPU] Write block failed: %d", result);
return(false);
}
return(true);
}
bool ASRockGPUSMBusController::ReadBlock(uint8_t* response, uint8_t len)
{
memset(response, 0, len);
int size = len;
int result = bus->i2c_read_block(dev, &size, response);
if(result < 0)
{
LOG_DEBUG("[ASRock GPU] Read block failed: %d", result);
return(false);
}
return(true);
}
bool ASRockGPUSMBusController::DetectChannels()
{
/*-----------------------------------------------------*\
| Get enabled channels |
| Command 0x14, subcommand 0x01 |
\*-----------------------------------------------------*/
if(!WriteBlock(0x14, 0x01, nullptr, 0))
{
LOG_WARNING("[ASRock GPU] Failed to request enabled channels");
return(false);
}
std::this_thread::sleep_for(20ms);
uint8_t response[I2C_SMBUS_BLOCK_MAX];
if(!ReadBlock(response, sizeof(response)))
{
LOG_WARNING("[ASRock GPU] Failed to read enabled channels");
return(false);
}
LOG_TRACE("[ASRock GPU] Enabled channels response: %02X %02X %02X %02X %02X %02X", response[0], response[1], response[2], response[3], response[4], response[5]);
/*-----------------------------------------------------*\
| Response format |
| Bytes 4-5 contain the channel bitmap |
\*-----------------------------------------------------*/
uint16_t channel_bits = response[4] | (response[5] << 8);
LOG_TRACE("[ASRock GPU] Channel bits: 0x%04X", channel_bits);
/*-----------------------------------------------------*\
| Get LED counts |
| Command 0x14, subcommand 0x02 |
\*-----------------------------------------------------*/
if(!WriteBlock(0x14, 0x02, nullptr, 0))
{
LOG_WARNING("[ASRock GPU] Failed to request LED counts");
return(false);
}
std::this_thread::sleep_for(20ms);
if(!ReadBlock(response, sizeof(response)))
{
LOG_WARNING("[ASRock GPU] Failed to read LED counts");
return(false);
}
num_channels = 0;
for(int i = 0; i < 16; i++)
{
if(channel_bits & (1 << i))
{
enabled_channels[num_channels] = i;
led_counts[num_channels] = response[4 + i];
const char* name = "Unknown";
if(i == ASROCK_GPU_CHANNEL_ARGB_HEADER)
{
name = "ARGB Header";
}
else if(i == ASROCK_GPU_CHANNEL_TOP_SIDE)
{
name = "Top Side";
}
else if(i == ASROCK_GPU_CHANNEL_FAN)
{
name = "Fan";
}
LOG_DEBUG("[ASRock GPU] Channel %d (%s) active with %d LEDs", i, name, response[4 + i]);
num_channels++;
}
}
LOG_DEBUG("[ASRock GPU] Found %d active channels", num_channels);
return(num_channels > 0);
}
void ASRockGPUSMBusController::SetChannelColor(uint8_t channel_idx, uint8_t red, uint8_t green, uint8_t blue)
{
/*-----------------------------------------------------*\
| SignalRGB color packet |
| Command 0x10, subcommand is the channel index |
\*-----------------------------------------------------*/
uint8_t data[8] =
{
0x01, // Mode: direct/static
red,
green,
blue,
0x80, // Brightness
0xFF, // Effect speed
0x00, // Effect direction
0x1A // Unknown constant
};
if(!WriteBlock(0x10, channel_idx, data, sizeof(data)))
{
LOG_WARNING("[ASRock GPU] Failed to set color for channel %d", channel_idx);
}
}
@@ -1,55 +0,0 @@
/*---------------------------------------------------------*\
| ASRockGPUSMBusController.h |
| |
| Driver for ASRock GPU RGB controllers |
| |
| Based on SignalRGB ASRock GPU.js plugin |
| |
| 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 uint8_t asrock_gpu_dev_id;
#define ASROCK_GPU_CONTROLLER_NAME "ASRock GPU SMBus Controller"
#define ASROCK_GPU_SMBUS_ADDRESS 0x36
/*-----------------------------------------------------*\
| ASRock GPU Channel Names (from SignalRGB) |
\*-----------------------------------------------------*/
enum
{
ASROCK_GPU_CHANNEL_ARGB_HEADER = 3,
ASROCK_GPU_CHANNEL_TOP_SIDE = 6,
ASROCK_GPU_CHANNEL_FAN = 7,
};
class ASRockGPUSMBusController
{
public:
ASRockGPUSMBusController(i2c_smbus_interface* bus, asrock_gpu_dev_id dev, std::string name);
~ASRockGPUSMBusController();
std::string GetDeviceLocation();
std::string GetDeviceName();
void SetChannelColor(uint8_t channel_idx, uint8_t red, uint8_t green, uint8_t blue);
bool DetectChannels();
uint8_t enabled_channels[16];
uint8_t led_counts[16];
uint8_t num_channels;
private:
i2c_smbus_interface* bus;
asrock_gpu_dev_id dev;
std::string device_name;
bool WriteBlock(uint8_t command, uint8_t subcommand, const uint8_t* data, uint8_t len);
bool ReadBlock(uint8_t* response, uint8_t len);
};
@@ -1,46 +0,0 @@
/*---------------------------------------------------------*\
| ASRockGPUSMBusControllerDetect.cpp |
| |
| Detector for ASRock GPU RGB controllers |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DetectionManager.h"
#include "ASRockGPUSMBusController.h"
#include "LogManager.h"
#include "RGBController_ASRockGPUSMBus.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
DetectedControllers DetectASRockGPUSMBusControllers(i2c_smbus_interface* bus, uint8_t address, const std::string& name)
{
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)
{
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);
ASRockGPUSMBusController* controller = new ASRockGPUSMBusController(bus, address, name);
if(controller->DetectChannels())
{
detected_controllers.push_back(new RGBController_ASRockGPUSMBus(controller));
}
else
{
LOG_WARNING("[ASRock GPU] No active channels found, device not registered");
delete controller;
}
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);
@@ -1,127 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_ASRockGPUSMBus.cpp |
| |
| RGBController for ASRock GPU RGB controllers |
| |
| Based on SignalRGB ASRock GPU.js plugin |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_ASRockGPUSMBus.h"
RGBController_ASRockGPUSMBus::RGBController_ASRockGPUSMBus(ASRockGPUSMBusController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "ASRock";
type = DEVICE_TYPE_GPU;
description = "ASRock GPU RGB Controller";
location = controller->GetDeviceLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_ASRockGPUSMBus::~RGBController_ASRockGPUSMBus()
{
delete controller;
}
void RGBController_ASRockGPUSMBus::SetupZones()
{
/*-----------------------------------------------------*\
| Set up zones - one zone per channel |
\*-----------------------------------------------------*/
for(unsigned int i = 0; i < controller->num_channels; i++)
{
uint8_t channel_idx = controller->enabled_channels[i];
zone new_zone;
new_zone.type = ZONE_TYPE_SINGLE;
new_zone.leds_min = 1;
new_zone.leds_max = 1;
new_zone.leds_count = 1;
/*-----------------------------------------------------*\
| Channel names from SignalRGB |
\*-----------------------------------------------------*/
if(channel_idx == ASROCK_GPU_CHANNEL_ARGB_HEADER)
{
new_zone.name = "ARGB Header";
}
else if(channel_idx == ASROCK_GPU_CHANNEL_TOP_SIDE)
{
new_zone.name = "Top Side";
}
else if(channel_idx == ASROCK_GPU_CHANNEL_FAN)
{
new_zone.name = "Fan";
}
else
{
new_zone.name = "Channel " + std::to_string(channel_idx);
}
zones.push_back(new_zone);
/*-----------------------------------------------------*\
| Set up LED for this zone |
\*-----------------------------------------------------*/
led new_led;
new_led.name = new_zone.name;
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_ASRockGPUSMBus::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*-----------------------------------------------------*\
| This device does not support resizing zones |
\*-----------------------------------------------------*/
}
void RGBController_ASRockGPUSMBus::DeviceUpdateLEDs()
{
for(unsigned int i = 0; i < controller->num_channels; i++)
{
uint8_t channel_idx = controller->enabled_channels[i];
RGBColor color = colors[i];
controller->SetChannelColor(channel_idx,
RGBGetRValue(color),
RGBGetGValue(color),
RGBGetBValue(color));
}
}
void RGBController_ASRockGPUSMBus::UpdateZoneLEDs(int zone)
{
uint8_t channel_idx = controller->enabled_channels[zone];
RGBColor color = colors[zone];
controller->SetChannelColor(channel_idx,
RGBGetRValue(color),
RGBGetGValue(color),
RGBGetBValue(color));
}
void RGBController_ASRockGPUSMBus::UpdateSingleLED(int led)
{
UpdateZoneLEDs(led);
}
void RGBController_ASRockGPUSMBus::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -1,34 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_ASRockGPUSMBus.h |
| |
| RGBController for ASRock GPU RGB controllers |
| |
| Based on SignalRGB ASRock GPU.js plugin |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "ASRockGPUSMBusController.h"
class RGBController_ASRockGPUSMBus : public RGBController
{
public:
RGBController_ASRockGPUSMBus(ASRockGPUSMBusController* controller_ptr);
~RGBController_ASRockGPUSMBus();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
ASRockGPUSMBusController* controller;
};
@@ -238,6 +238,7 @@ void RGBController_ASRockPolychromeV2SMBus::SetupZones()
}
}
unsigned int led_count = 0;
/*---------------------------------------------------------*\
| Set up LEDs |
\*---------------------------------------------------------*/
@@ -267,6 +268,8 @@ void RGBController_ASRockPolychromeV2SMBus::SetupZones()
\*---------------------------------------------------------*/
leds.push_back(*new_led);
led_count++;
if(zone_idx == POLYCHROME_V2_ZONE_ADDRESSABLE)
{
break;
@@ -1,50 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidKeyboard.cpp |
| |
| Detector for Acer Nitro HID Keyboard |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "DetectionManager.h"
#include "AcerNitroHidKeyboardController.h"
#include "RGBController_AcerNitroHidKeyboard.h"
#include "RGBController_AcerNitroHidLed.h"
/*---------------------------------------------------------*\
| HID vendor and product IDs for ENEK EC in Acer Nitro |
\*---------------------------------------------------------*/
#define ACER_ENEC_VID 0x0CF2
#define ACER_ENEC_PID 0x5130
#define ACER_ENEC_USAGE_PAGE 0xFF5A
#define ACER_ENEC_USAGE 0x01
DetectedControllers DetectAcerHIDControllers(hid_device_info* info, const std::string&)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
/*-------------------------------------------------*\
| Controller is shared between keyboard and onboard |
| led |
\*-------------------------------------------------*/
std::shared_ptr<AcerNitroHidKeyboardController> controller = std::make_shared<AcerNitroHidKeyboardController>(dev, info->path);
RGBController_AcerNitroHidKeyboard* rgb_kb_controller = new RGBController_AcerNitroHidKeyboard(controller);
RGBController_AcerNitroHidLed* rgb_led_controller = new RGBController_AcerNitroHidLed(controller);
detected_controllers.push_back(rgb_kb_controller);
detected_controllers.push_back(rgb_led_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_PU("AcerNitroHidKeyboardController", DetectAcerHIDControllers, ACER_ENEC_VID, ACER_ENEC_PID, ACER_ENEC_USAGE_PAGE, ACER_ENEC_USAGE);
@@ -1,80 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidKeyboard.cpp |
| |
| Driver for Acer Nitro Keyboard |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "AcerNitroHidKeyboardController.h"
AcerNitroHidKeyboardController::AcerNitroHidKeyboardController(hid_device *dev_handle, const char *path)
{
this->location = path;
this->dev = dev_handle;
device_name = "Acer Nitro HID Keyboard";
}
AcerNitroHidKeyboardController::~AcerNitroHidKeyboardController()
{
if(dev)
{
hid_close(dev);
}
}
std::string AcerNitroHidKeyboardController::GetLocation() const
{
return("HID: " + location);
}
std::string AcerNitroHidKeyboardController::GetDeviceName() const
{
return(device_name);
}
void AcerNitroHidKeyboardController::SetLEDs(const std::vector<RGBColor>& colors, unsigned char brightness, unsigned char device_id)
{
std::lock_guard<std::mutex> guard(device_mutex);
for(unsigned int led_idx = 0; (led_idx < colors.size()) && (led_idx < ACER_HID_NUM_ZONES); led_idx++)
{
/*-------------------------------------------------*\
| Convert colors to RGB format |
\*-------------------------------------------------*/
unsigned char r = RGBGetRValue(colors[led_idx]);
unsigned char g = RGBGetGValue(colors[led_idx]);
unsigned char b = RGBGetBValue(colors[led_idx]);
/*-------------------------------------------------*\
| Send packet |
\*-------------------------------------------------*/
unsigned char zone_select = (unsigned char)(1<<led_idx);
unsigned char packet[ACER_HID_PACKET_SIZE] = {0xA4, device_id, ACER_HID_MODE_STATIC, brightness, 0, 1, r, g, b, zone_select, 0};
hid_send_feature_report(dev, packet, ACER_HID_PACKET_SIZE);
}
}
void AcerNitroHidKeyboardController::SetAllLEDs(const RGBColor &color, unsigned char brightness, unsigned char speed, unsigned char direction, unsigned char mode, unsigned char device_id)
{
std::lock_guard<std::mutex> guard(device_mutex);
/*-----------------------------------------------------*\
| Convert color to RGB format |
\*-----------------------------------------------------*/
unsigned char r = RGBGetRValue(color);
unsigned char g = RGBGetGValue(color);
unsigned char b = RGBGetBValue(color);
/*-----------------------------------------------------*\
| Send packet |
| Zone select = All zones |
\*-----------------------------------------------------*/
unsigned char zone_select = 0x0F;
unsigned char packet[ACER_HID_PACKET_SIZE] = {0xA4, device_id, mode, brightness, speed, direction, r, g, b, zone_select, 0};
hid_send_feature_report(dev, packet, ACER_HID_PACKET_SIZE);
}
@@ -1,56 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidKeyboard.cpp |
| |
| Driver for Acer Nitro Keyboard |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
enum
{
ACER_HID_MODE_DIRECT = 1,
ACER_HID_MODE_STATIC = 2,
ACER_HID_MODE_BREATHING = 4,
ACER_HID_MODE_NEON = 5,
ACER_HID_MODE_OPMODE = 6,
ACER_HID_MODE_WAVE = 7,
ACER_HID_MODE_SHIFTING = 8,
ACER_HID_MODE_ZOOM = 9,
ACER_HID_MODE_METEOR = 10,
ACER_HID_MODE_TWINKLING = 11,
};
#define ACER_HID_NAME_BUFFER_SIZE 255
#define ACER_HID_NUM_ZONES 4
#define ACER_HID_PACKET_SIZE 11
#include <mutex>
#include <string>
#include <vector>
#include <hidapi.h>
#include "RGBControllerInterface.h"
class AcerNitroHidKeyboardController
{
public:
AcerNitroHidKeyboardController(hid_device *dev_handle, const char *path);
~AcerNitroHidKeyboardController();
std::string GetDeviceName() const;
std::string GetSerial() const;
std::string GetLocation() const;
void SetLEDs(const std::vector<RGBColor> &colors, unsigned char brightness, unsigned char device_id);
void SetAllLEDs(const RGBColor &color, unsigned char brightness, unsigned char speed, unsigned char direction, unsigned char mode, unsigned char device_id);
private:
hid_device *dev;
std::string device_name;
std::string location;
std::mutex device_mutex;
};
@@ -1,231 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidKeyboard.cpp |
| |
| RGBController for Acer Nitro HID Keyboard |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_AcerNitroHidKeyboard.h"
// /**------------------------------------------------------------------*\
// @name Acer Nitro HID Keyboard
// @category Laptop
// @type HID
// @save :x:
// @direct :white_check_mark:
// @effects :white_check_mark:
// @detectors DetectAcerHIDControllers
// @comment
// \*-------------------------------------------------------------------*/
RGBController_AcerNitroHidKeyboard::RGBController_AcerNitroHidKeyboard(std::shared_ptr<AcerNitroHidKeyboardController> controller)
{
this->controller = controller;
device_id = 0x21;
name = "Acer Nitro HID Keyboard";
vendor = "Acer";
type = DEVICE_TYPE_LAPTOP;
description = "Acer Nitro HID Keyboard Device";
location = controller->GetLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = ACER_HID_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS ;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness_min = 0;
Direct.brightness_max = 100;
Direct.brightness = 100;
modes.push_back(Direct);
mode Static;
Static.name = "Static";
Static.value = ACER_HID_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.brightness_min = 0;
Static.brightness_max = 100;
Static.brightness = 100;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(1);
Static.speed = 0;
modes.push_back(Static);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = ACER_HID_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.brightness_min = 0;
Breathing.brightness_max = 100;
Breathing.brightness = 100;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.speed_min = 1;
Breathing.speed_max = 9;
Breathing.speed = 4;
Breathing.colors.resize(1);
modes.push_back(Breathing);
mode Neon;
Neon.name = "Neon";
Neon.value = ACER_HID_MODE_NEON;
Neon.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Neon.color_mode = MODE_COLORS_NONE;
Neon.brightness_min = 0;
Neon.brightness_max = 100;
Neon.brightness = 100;
Neon.speed_min = 1;
Neon.speed_max = 9;
Neon.speed = 4;
modes.push_back(Neon);
mode Wave;
Wave.name = "Wave";
Wave.value = ACER_HID_MODE_WAVE;
Wave.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
Wave.color_mode = MODE_COLORS_NONE;
Wave.brightness_min = 0;
Wave.brightness_max = 100;
Wave.brightness = 100;
Wave.speed_min = 1;
Wave.speed_max = 9;
Wave.speed = 4;
Wave.direction = 0;
modes.push_back(Wave);
mode Shifting;
Shifting.name = "Shifting";
Shifting.value = ACER_HID_MODE_SHIFTING;
Shifting.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Shifting.color_mode = MODE_COLORS_NONE;
Shifting.brightness_min = 0;
Shifting.brightness_max = 100;
Shifting.brightness = 100;
Shifting.speed_min = 1;
Shifting.speed_max = 9;
Shifting.speed = 4;
modes.push_back(Shifting);
mode Zoom;
Zoom.name = "Zoom";
Zoom.value = ACER_HID_MODE_ZOOM;
Zoom.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Zoom.color_mode = MODE_COLORS_NONE;
Zoom.brightness_min = 0;
Zoom.brightness_max = 100;
Zoom.brightness = 100;
Zoom.speed_min = 1;
Zoom.speed_max = 9;
Zoom.speed = 4;
modes.push_back(Zoom);
mode Meteor;
Meteor.name = "Meteor";
Meteor.value = ACER_HID_MODE_METEOR;
Meteor.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Meteor.color_mode = MODE_COLORS_NONE;
Meteor.brightness_min = 0;
Meteor.brightness_max = 100;
Meteor.brightness = 100;
Meteor.speed_min = 1;
Meteor.speed_max = 9;
Meteor.speed = 4;
modes.push_back(Meteor);
mode Twinkling;
Twinkling.name = "Twinkling";
Twinkling.value = ACER_HID_MODE_TWINKLING;
Twinkling.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Twinkling.color_mode = MODE_COLORS_NONE;
Twinkling.brightness_min = 0;
Twinkling.brightness_max = 100;
Twinkling.brightness = 100;
Twinkling.colors_min = 1;
Twinkling.colors_max = 1;
Twinkling.speed_min = 1;
Twinkling.speed_max = 9;
Twinkling.speed = 4;
modes.push_back(Twinkling);
SetupZones();
}
RGBController_AcerNitroHidKeyboard::~RGBController_AcerNitroHidKeyboard()
{
Shutdown();
}
void RGBController_AcerNitroHidKeyboard::SetupZones()
{
zone* new_zone = new zone;
new_zone->name = "Keyboard Backlight Zone";
new_zone->type = ZONE_TYPE_LINEAR;
new_zone->leds_min = 4;
new_zone->leds_max = 4;
new_zone->leds_count = 4;
zones.push_back(*new_zone);
for(std::size_t zone_idx = 0; zone_idx < ACER_HID_NUM_ZONES; zone_idx++)
{
led* new_led = new led();
new_led->name = "Keyboard Backlight Zone ";
new_led->name.append(std::to_string(zone_idx + 1));
new_led->value = (unsigned int)leds.size();
leds.push_back(*new_led);
}
SetupColors();
}
void RGBController_AcerNitroHidKeyboard::DeviceUpdateLEDs()
{
mode& current_mode = modes[active_mode];
if(current_mode.value == ACER_HID_MODE_DIRECT)
{
controller->SetLEDs(colors, current_mode.brightness, device_id);
}
else
{
RGBColor color = current_mode.colors.size()==0? (RGBColor)0 : current_mode.colors[0];
unsigned char direction = 1;
if((modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_LR) && modes[active_mode].direction)
{
direction = 2;
}
controller->SetAllLEDs(color, current_mode.brightness, current_mode.speed, direction, current_mode.value, device_id);
}
}
void RGBController_AcerNitroHidKeyboard::DeviceUpdateZoneLEDs(int)
{
DeviceUpdateLEDs();
}
void RGBController_AcerNitroHidKeyboard::DeviceUpdateSingleLED(int)
{
DeviceUpdateLEDs();
}
void RGBController_AcerNitroHidKeyboard::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidKeyboard.cpp |
| |
| RGBController for Acer Nitro HID Keyboard |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "AcerNitroHidKeyboardController.h"
class RGBController_AcerNitroHidKeyboard : public RGBController
{
public:
RGBController_AcerNitroHidKeyboard(std::shared_ptr<AcerNitroHidKeyboardController> controller);
~RGBController_AcerNitroHidKeyboard();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
std::shared_ptr<AcerNitroHidKeyboardController> controller;
unsigned int device_id;
};
@@ -1,152 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidLed.cpp |
| |
| RGBController for Acer Nitro HID LED |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_AcerNitroHidLed.h"
// /**------------------------------------------------------------------*\
// @name Acer Nitro HID Led
// @category Laptop
// @type HID
// @save :x:
// @direct :white_check_mark:
// @effects :white_check_mark:
// @detectors DetectAcerHIDControllers
// @comment
// \*-------------------------------------------------------------------*/
RGBController_AcerNitroHidLed::RGBController_AcerNitroHidLed(std::shared_ptr<AcerNitroHidKeyboardController> controller)
{
this->controller = controller;
device_id = 0x65;
name = "Acer Nitro HID LED Device";
vendor = "Acer";
type = DEVICE_TYPE_LIGHT;
description = "Acer Nitro HID LED Device";
location = controller->GetLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = ACER_HID_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS ;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness_min = 0;
Direct.brightness_max = 100;
Direct.brightness = 100;
modes.push_back(Direct);
mode Static;
Static.name = "Static";
Static.value = ACER_HID_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.brightness_min = 0;
Static.brightness_max = 100;
Static.brightness = 100;
Static.colors_min = 1;
Static.colors_max = 1;
Static.colors.resize(1);
Static.speed = 0;
modes.push_back(Static);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = ACER_HID_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.brightness_min = 0;
Breathing.brightness_max = 100;
Breathing.brightness = 100;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.speed_min = 1;
Breathing.speed_max = 5;
Breathing.speed = 4;
Breathing.colors.resize(1);
modes.push_back(Breathing);
mode Neon;
Neon.name = "Neon";
Neon.value = ACER_HID_MODE_NEON;
Neon.flags = MODE_FLAG_REQUIRES_ENTIRE_DEVICE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Neon.color_mode = MODE_COLORS_NONE;
Neon.brightness_min = 0;
Neon.brightness_max = 100;
Neon.brightness = 100;
Neon.speed_min = 1;
Neon.speed_max = 5;
Neon.speed = 4;
modes.push_back(Neon);
SetupZones();
}
RGBController_AcerNitroHidLed::~RGBController_AcerNitroHidLed()
{
Shutdown();
}
void RGBController_AcerNitroHidLed::SetupZones()
{
zone* new_zone = new zone;
new_zone->name = "LED";
new_zone->type = ZONE_TYPE_LINEAR;
new_zone->leds_min = 1;
new_zone->leds_max = 1;
new_zone->leds_count = 1;
zones.push_back(*new_zone);
led* new_led = new led();
new_led->name = "LED";
new_led->value = (unsigned int)leds.size();
leds.push_back(*new_led);
SetupColors();
}
void RGBController_AcerNitroHidLed::DeviceUpdateLEDs()
{
mode& current_mode = modes[active_mode];
if(current_mode.value == ACER_HID_MODE_DIRECT)
{
controller->SetLEDs(colors, current_mode.brightness, device_id);
}
else
{
RGBColor color = current_mode.colors.size()==0? (RGBColor)0 : current_mode.colors[0];
unsigned char direction = 1;
if((modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_LR) && modes[active_mode].direction)
{
direction = 2;
}
controller->SetAllLEDs(color, current_mode.brightness, current_mode.speed, direction, current_mode.value, device_id);
}
}
void RGBController_AcerNitroHidLed::DeviceUpdateZoneLEDs(int)
{
DeviceUpdateLEDs();
}
void RGBController_AcerNitroHidLed::DeviceUpdateSingleLED(int)
{
DeviceUpdateLEDs();
}
void RGBController_AcerNitroHidLed::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -1,35 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_AcerNitroHidLed.cpp |
| |
| RGBController for Acer Nitro HID LED |
| |
| Marek Pokropiński Jul 27 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "AcerNitroHidKeyboardController.h"
#include "RGBController_AcerNitroHidKeyboard.h"
class RGBController_AcerNitroHidLed : public RGBController
{
public:
RGBController_AcerNitroHidLed(std::shared_ptr<AcerNitroHidKeyboardController> controller);
~RGBController_AcerNitroHidLed();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
std::shared_ptr<AcerNitroHidKeyboardController> controller;
unsigned int device_id;
};
@@ -1,43 +0,0 @@
/*---------------------------------------------------------*\
| AlienwareAW510KControllerDetect.cpp |
| |
| Detector for Alienware AW510K Keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "AlienwareAW510KController.h"
#include "RGBController_AlienwareAW510K.h"
/*---------------------------------------------------------*\
| Alienware vendor ID |
\*---------------------------------------------------------*/
#define ALIENWARE_VID 0x04F2
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define ALIENWARE_AW510K_PID 0x1830
DetectedControllers DetectAlienwareAW510KControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
AlienwareAW510KController* controller = new AlienwareAW510KController(dev, info->path, name);
RGBController_AlienwareAW510K* rgb_controller = new RGBController_AlienwareAW510K(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Alienware AW510K", DetectAlienwareAW510KControllers, ALIENWARE_VID, ALIENWARE_AW510K_PID, 0x02, 0xFF00, 0x01);
@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| AlienwareAW410KControllerDetect.cpp |
| AlienwareKeyboardControllerDetect.cpp |
| |
| Detector for Alienware AW410K Keyboard |
| Detector for Alienware Keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -10,17 +10,38 @@
#include <hidapi.h>
#include "DetectionManager.h"
#include "AlienwareAW410KController.h"
#include "AlienwareAW510KController.h"
#include "RGBController_AlienwareAW410K.h"
#include "RGBController_AlienwareAW510K.h"
/*---------------------------------------------------------*\
| Alienware vendor ID |
\*---------------------------------------------------------*/
#define ALIENWARE_VID 0x04F2
#define ALIENWARE_VID 0x04F2
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define ALIENWARE_AW410K_PID 0x1968
#define ALIENWARE_AW510K_PID 0x1830
#define ALIENWARE_AW410K_PID 0x1968
DetectedControllers DetectAlienwareAW510KControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
AlienwareAW510KController* controller = new AlienwareAW510KController(dev, info->path, name);
RGBController_AlienwareAW510K* rgb_controller = new RGBController_AlienwareAW510K(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
DetectedControllers DetectAlienwareAW410KControllers(hid_device_info* info, const std::string& name)
{
@@ -40,4 +61,5 @@ DetectedControllers DetectAlienwareAW410KControllers(hid_device_info* info, cons
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Alienware AW510K", DetectAlienwareAW510KControllers, ALIENWARE_VID, ALIENWARE_AW510K_PID, 0x02, 0xFF00, 0x01);
REGISTER_HID_DETECTOR_IPU("Alienware AW410K", DetectAlienwareAW410KControllers, ALIENWARE_VID, ALIENWARE_AW410K_PID, 0x02, 0xFF00, 0x01);
@@ -21,13 +21,13 @@
DetectedControllers DetectArcticControllers()
{
DetectedControllers detected_controllers;
std::vector<std::string> ports;
std::vector<std::string *> ports;
ports = find_usb_serial_port(CH341_VID, CH341_PID);
for(unsigned int device = 0; device < ports.size(); device++)
{
ArcticController *controller = new ArcticController(ports[device]);
ArcticController *controller = new ArcticController(*ports[device]);
if(controller->IsPresent())
{
@@ -38,6 +38,8 @@ DetectedControllers DetectArcticControllers()
{
delete controller;
}
delete ports[device];
}
return(detected_controllers);
@@ -22,7 +22,6 @@
#define AURA_ROG_GLADIUS_II_WIRELESS_1_PID 0x189E
#define AURA_ROG_GLADIUS_II_WIRELESS_2_PID 0x18A0
#define AURA_ROG_GLADIUS_III_PID 0x197B
#define AURA_ROG_GLADIUS_III_CORE_PID 0x1C8D
#define AURA_ROG_GLADIUS_III_WIRELESS_USB_PID 0x197D
#define AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID 0x197F
#define AURA_ROG_GLADIUS_III_WIRELESS_BT_PID 0x1981
@@ -218,20 +217,6 @@ static std::map<int,mouse_type> aura_mouse_devices =
{ AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY }
}
},
{
AURA_ROG_GLADIUS_III_CORE_PID, // ROG Gladius III Core
{
0,
0,
0,
100,
false,
1,
false,
{ AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL },
{ AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE }
}
},
{
AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, // ROG Gladius III Wireless USB
{
@@ -221,7 +221,7 @@ void RGBController_AuraUSB::SetupZones()
new_led.name.append(std::to_string(led_idx));
new_led.value = (unsigned int)channel_idx;
new_led.value = channel_idx;
leds.push_back(new_led);
}
@@ -464,7 +464,6 @@ REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin COD",
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_1_PID, 1, 0xFF13);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_2_PID, 2, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_CORE_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, 0, 0xFF01);
REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, 0, 0xFF01);
@@ -24,12 +24,12 @@
DetectedControllers DetectBlinkyTapeControllers()
{
DetectedControllers detected_controllers;
std::vector<std::string> device_locations = find_usb_serial_port(BLINKINLABS_VID, BLINKYTAPE_PID);
std::vector<std::string *> device_locations = find_usb_serial_port(BLINKINLABS_VID, BLINKYTAPE_PID);
for(unsigned int device_idx = 0; device_idx < device_locations.size(); device_idx++)
{
BlinkyTapeController* controller = new BlinkyTapeController();
controller->Initialize(device_locations[device_idx]);
controller->Initialize(*device_locations[device_idx]);
RGBController_BlinkyTape* rgb_controller = new RGBController_BlinkyTape(controller);
@@ -1,25 +1,22 @@
/*---------------------------------------------------------*\
| ClevoKeyboardController.cpp |
| |
| Driver for Clevo per-key RGB keyboard |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| Driver for Clevo laptop per-key RGB keyboard (ITE 8291) |
| Protocol based on tuxedo-drivers ite_8291 module |
| |
| Kyle Cascade ([email protected]) 16 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <algorithm>
#include <cstring>
#include "ClevoKeyboardController.h"
#include "StringUtils.h"
ClevoKeyboardController::ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info, clevo_keyboard_type kb_type)
ClevoKeyboardController::ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info)
{
dev = dev_handle;
type = kb_type;
location = info.path;
version = info.release_number;
}
@@ -29,31 +26,6 @@ ClevoKeyboardController::~ClevoKeyboardController()
hid_close(dev);
}
clevo_keyboard_type ClevoKeyboardController::GetType()
{
return type;
}
int ClevoKeyboardController::GetNumRows()
{
return(type == CLEVO_KB_ITE829X) ? CLEVO_829X_NUM_ROWS : CLEVO_8291_NUM_ROWS;
}
int ClevoKeyboardController::GetNumCols()
{
return(type == CLEVO_KB_ITE829X) ? CLEVO_829X_NUM_COLS : CLEVO_8291_NUM_COLS;
}
int ClevoKeyboardController::GetNumLEDs()
{
return GetNumRows() * GetNumCols();
}
unsigned char ClevoKeyboardController::GetBrightnessMax()
{
return(type == CLEVO_KB_ITE829X) ? CLEVO_829X_BRIGHTNESS_MAX : CLEVO_8291_BRIGHTNESS_MAX;
}
std::string ClevoKeyboardController::GetDeviceLocation()
{
return("HID: " + location);
@@ -79,355 +51,147 @@ std::string ClevoKeyboardController::GetFirmwareVersion()
return(version_string);
}
/*---------------------------------------------------------*\
| ITE 8291: 8-byte feature report, no report ID |
\*---------------------------------------------------------*/
void ClevoKeyboardController::WriteControl8291(unsigned char* data)
void ClevoKeyboardController::WriteControl(unsigned char* data)
{
hid_send_feature_report(dev, data, CLEVO_8291_REPORT_SIZE);
hid_send_feature_report(dev, data, CLEVO_KEYBOARD_REPORT_SIZE);
}
void ClevoKeyboardController::WriteRowData(unsigned char* data)
{
hid_write(dev, data, CLEVO_8291_ROW_DATA_SIZE);
}
/*---------------------------------------------------------*\
| ITE 829x: 6-byte feature report with report ID 0xCC |
\*---------------------------------------------------------*/
void ClevoKeyboardController::SendCommand829x(unsigned char cmd, unsigned char d0, unsigned char d1, unsigned char d2, unsigned char d3)
{
unsigned char buf[CLEVO_829X_REPORT_SIZE];
buf[0] = CLEVO_829X_REPORT_ID;
buf[1] = cmd;
buf[2] = d0;
buf[3] = d1;
buf[4] = d2;
buf[5] = d3;
hid_send_feature_report(dev, buf, CLEVO_829X_REPORT_SIZE);
hid_write(dev, data, CLEVO_KEYBOARD_ROW_DATA_SIZE);
}
void ClevoKeyboardController::TurnOff()
{
if(type == CLEVO_KB_ITE829X)
{
SendCommand829x(CLEVO_829X_CMD_BRIGHTNESS);
return;
}
/*---------------------------------------------------------*\
| Turn off: 08 01 00 00 00 00 00 00 |
\*---------------------------------------------------------*/
unsigned char buf[CLEVO_KEYBOARD_REPORT_SIZE];
unsigned char buf[CLEVO_8291_REPORT_SIZE];
memset(buf, 0x00, CLEVO_8291_REPORT_SIZE);
buf[0] = CLEVO_8291_CMD_MODE;
buf[1] = CLEVO_8291_POWER_OFF;
WriteControl8291(buf);
memset(buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
buf[0] = 0x08;
buf[1] = 0x01;
WriteControl(buf);
}
void ClevoKeyboardController::SetMode(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char behaviour)
{
if(type == CLEVO_KB_ITE829X)
{
SendCommand829x(CLEVO_829X_CMD_BRIGHTNESS, brightness, speed);
return;
}
/*---------------------------------------------------------*\
| Set params: 08 [power] [mode] [speed] [brightness] 08 |
| [behaviour] 00 |
| power: 01=off, 02=on |
\*---------------------------------------------------------*/
unsigned char buf[CLEVO_KEYBOARD_REPORT_SIZE];
unsigned char buf[CLEVO_8291_REPORT_SIZE];
memset(buf, 0x00, CLEVO_8291_REPORT_SIZE);
buf[0] = CLEVO_8291_CMD_MODE;
buf[1] = CLEVO_8291_POWER_ON;
memset(buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
buf[0] = 0x08;
buf[1] = 0x02; // Power on
buf[2] = mode;
buf[3] = speed;
buf[4] = brightness;
buf[5] = CLEVO_8291_MODE_FLAG;
buf[5] = 0x08;
buf[6] = behaviour;
WriteControl8291(buf);
WriteControl(buf);
}
void ClevoKeyboardController::SetModeColor(unsigned char color_idx, RGBColor color)
void ClevoKeyboardController::SetModeColor(unsigned char color_idx, unsigned char red, unsigned char green, unsigned char blue)
{
if(type == CLEVO_KB_ITE829X)
{
return;
}
/*---------------------------------------------------------*\
| Set color define: 14 00 [index] R G B 00 00 |
| index: 1-7 for built-in effects |
\*---------------------------------------------------------*/
unsigned char buf[CLEVO_KEYBOARD_REPORT_SIZE];
unsigned char buf[CLEVO_8291_REPORT_SIZE];
memset(buf, 0x00, CLEVO_8291_REPORT_SIZE);
buf[0] = CLEVO_8291_CMD_COLOR;
memset(buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
buf[0] = 0x14;
buf[1] = 0x00;
buf[2] = color_idx;
buf[3] = RGBGetRValue(color);
buf[4] = RGBGetGValue(color);
buf[5] = RGBGetBValue(color);
WriteControl8291(buf);
buf[3] = red;
buf[4] = green;
buf[5] = blue;
WriteControl(buf);
}
void ClevoKeyboardController::SetBrightnessSpeed829x(unsigned char brightness, unsigned char speed)
void ClevoKeyboardController::SendColors(unsigned char* color_data, unsigned char brightness)
{
if(brightness > CLEVO_829X_BRIGHTNESS_MAX)
{
brightness = CLEVO_829X_BRIGHTNESS_MAX;
}
if(brightness != current_brightness_829x || speed != current_speed_829x)
{
current_brightness_829x = brightness;
current_speed_829x = speed;
SendCommand829x(CLEVO_829X_CMD_BRIGHTNESS, brightness, speed);
}
}
void ClevoKeyboardController::SendColorSlot829x(unsigned char cmd, unsigned char slot, RGBColor color)
{
SendCommand829x(cmd, slot, RGBGetRValue(color), RGBGetGValue(color), RGBGetBValue(color));
}
/*---------------------------------------------------------*\
| ITE 829x: Save/Clear BIOS keyboard state |
\*---------------------------------------------------------*/
void ClevoKeyboardController::SaveToBios829x()
{
SendCommand829x(CLEVO_829X_CMD_SAVE_BIOS, 0x01);
}
void ClevoKeyboardController::ClearBiosSave829x()
{
SendCommand829x(CLEVO_829X_CMD_SAVE_BIOS, 0x00);
}
void ClevoKeyboardController::StopAnimation829x()
{
SendCommand829x(CLEVO_829X_CMD_ANIM, CLEVO_829X_CMD_STOP_ANIM);
}
void ClevoKeyboardController::SetEffect829x(unsigned char mode_value, const std::vector<RGBColor>& colors, unsigned int direction, unsigned int color_mode)
{
bool mode_changed = (mode_value != current_mode_829x);
current_mode_829x = mode_value;
bool use_custom_color = (color_mode != MODE_COLORS_RANDOM) && !colors.empty();
/*---------------------------------------------------------*\
| Per-key RGB mode (mode 0x33) |
| 1. Set params with mode 0x33 and brightness |
| 2. For each row 0-5: |
| - Announce row: 16 00 [row] 00 00 00 00 00 |
| - Send 65 bytes row data via output report |
| |
| Row data format (65 bytes): |
| [0x00 padding][0x00 padding] |
| [B0..B20][G0..G20][R0..R20] |
\*---------------------------------------------------------*/
unsigned char ctrl_buf[CLEVO_KEYBOARD_REPORT_SIZE];
unsigned char row_buf[CLEVO_KEYBOARD_ROW_DATA_SIZE];
/*---------------------------------------------------------*\
| Animation modes: send [CC, 00, mode_id] on mode change |
| Clamp brightness |
\*---------------------------------------------------------*/
struct anim_entry { unsigned char mode; unsigned char anim_id; };
static const anim_entry anim_modes[] =
if(brightness > CLEVO_KEYBOARD_BRIGHTNESS_MAX)
{
{ CLEVO_829X_MODE_WAVE, 0x04 },
{ CLEVO_829X_MODE_RANDOM, 0x09 },
{ CLEVO_829X_MODE_SCAN, 0x0A },
{ CLEVO_829X_MODE_SNAKE, 0x0B },
{ CLEVO_829X_MODE_RAINBOW_CYCLE, 0x02 },
{ CLEVO_829X_MODE_RAINBOW_GRAD, 0x04 },
};
const anim_entry* anim_it = std::find_if(std::begin(anim_modes), std::end(anim_modes),
[mode_value](const anim_entry& e) { return e.mode == mode_value; });
if(anim_it != std::end(anim_modes) && mode_changed)
{
SendCommand829x(CLEVO_829X_CMD_ANIM, anim_it->anim_id);
brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
}
/*---------------------------------------------------------*\
| Direction-based effects (Wave/Snake) |
| Slot = base + direction_index |
| Custom color: base = 0xA1, Preset: base = 0x71 |
| Set params for per-key mode |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| Map OpenRGB direction enum to firmware slot index |
\*---------------------------------------------------------*/
static const unsigned char dir_to_wave_idx[] =
{
6, /* MODE_DIRECTION_LEFT */
7, /* MODE_DIRECTION_RIGHT */
4, /* MODE_DIRECTION_UP */
5, /* MODE_DIRECTION_DOWN */
6, /* MODE_DIRECTION_HORIZONTAL */
4, /* MODE_DIRECTION_VERTICAL */
0, /* MODE_DIRECTION_UP_LEFT */
1, /* MODE_DIRECTION_UP_RIGHT */
2, /* MODE_DIRECTION_DOWN_LEFT */
3, /* MODE_DIRECTION_DOWN_RIGHT */
};
static const unsigned char dir_to_snake_idx[] =
{
0, /* MODE_DIRECTION_LEFT */
0, /* MODE_DIRECTION_RIGHT */
0, /* MODE_DIRECTION_UP */
0, /* MODE_DIRECTION_DOWN */
0, /* MODE_DIRECTION_HORIZONTAL */
0, /* MODE_DIRECTION_VERTICAL */
0, /* MODE_DIRECTION_UP_LEFT */
1, /* MODE_DIRECTION_UP_RIGHT */
2, /* MODE_DIRECTION_DOWN_LEFT */
3, /* MODE_DIRECTION_DOWN_RIGHT */
};
if((mode_value == CLEVO_829X_MODE_WAVE || mode_value == CLEVO_829X_MODE_RAINBOW_GRAD) && direction < sizeof(dir_to_wave_idx))
{
unsigned char base = use_custom_color ? CLEVO_829X_COLOR_SLOT_BASE : CLEVO_829X_PRESET_SLOT_BASE;
unsigned char idx = dir_to_wave_idx[direction];
unsigned char slot = base + idx;
if(use_custom_color)
{
SendColorSlot829x(CLEVO_829X_CMD_WAVE_COLOR, slot, colors[0]);
}
if(!use_custom_color)
{
SendCommand829x(CLEVO_829X_CMD_WAVE_COLOR, slot);
}
}
if(mode_value == CLEVO_829X_MODE_SNAKE && direction < sizeof(dir_to_snake_idx))
{
unsigned char base = use_custom_color ? CLEVO_829X_COLOR_SLOT_BASE : CLEVO_829X_PRESET_SLOT_BASE;
unsigned char idx = dir_to_snake_idx[direction];
unsigned char slot = base + idx;
if(use_custom_color)
{
SendColorSlot829x(CLEVO_829X_CMD_SNAKE_COLOR, slot, colors[0]);
}
if(!use_custom_color)
{
SendCommand829x(CLEVO_829X_CMD_SNAKE_COLOR, slot);
}
}
/*---------------------------------------------------------*\
| Breathing/Flashing: random or custom color |
\*---------------------------------------------------------*/
if(mode_value == CLEVO_829X_MODE_BREATH && use_custom_color)
{
SendColorSlot829x(0x0A, CLEVO_829X_COLOR_CUSTOM, colors[0]);
}
if(mode_value == CLEVO_829X_MODE_BREATH && !use_custom_color)
{
SendCommand829x(0x0A);
}
if(mode_value == CLEVO_829X_MODE_BLINK && use_custom_color)
{
SendColorSlot829x(0x0B, CLEVO_829X_COLOR_CUSTOM, colors[0]);
}
if(mode_value == CLEVO_829X_MODE_BLINK && !use_custom_color)
{
SendCommand829x(0x0B);
}
/*---------------------------------------------------------*\
| Random: custom color only (multicolor is the default) |
\*---------------------------------------------------------*/
if(mode_value == CLEVO_829X_MODE_RANDOM && use_custom_color)
{
SendColorSlot829x(CLEVO_829X_CMD_RANDOM_COLOR, CLEVO_829X_COLOR_SLOT_BASE, colors[0]);
}
/*---------------------------------------------------------*\
| Scan: 2 custom color bands |
\*---------------------------------------------------------*/
if(mode_value == CLEVO_829X_MODE_SCAN)
{
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]);
}
}
/*---------------------------------------------------------*\
| Fn Highlight: per-key color on function keys |
\*---------------------------------------------------------*/
if(mode_value == CLEVO_829X_MODE_FN_COLOR && !colors.empty())
{
static const unsigned char fn_keys[] =
{
0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0A, 0x0B, 0x0C, 0x21, 0x23, 0x31, 0x32, 0x33,
0x53, 0x73, 0xA2
};
SendCommand829x(CLEVO_829X_CMD_ANIM, CLEVO_829X_CMD_CLEAR);
for(unsigned char key : fn_keys)
{
SendCommand829x(CLEVO_829X_CMD_SET_LED, key,
RGBGetRValue(colors[0]),
RGBGetGValue(colors[0]),
RGBGetBValue(colors[0]));
}
}
}
void ClevoKeyboardController::SendColors(const unsigned char* color_data, unsigned char brightness, unsigned char speed)
{
int num_rows = GetNumRows();
int num_cols = GetNumCols();
if(type == CLEVO_KB_ITE829X)
{
if(brightness > CLEVO_829X_BRIGHTNESS_MAX)
{
brightness = CLEVO_829X_BRIGHTNESS_MAX;
}
SendCommand829x(CLEVO_829X_CMD_BRIGHTNESS, brightness, speed);
for(int row = 0; row < num_rows; row++)
{
for(int col = 0; col < num_cols; col++)
{
int idx = (row * num_cols + col) * 3;
SendCommand829x(CLEVO_829X_CMD_SET_LED,
CLEVO_829X_LED_ID(row, col),
color_data[idx + 0],
color_data[idx + 1],
color_data[idx + 2]);
}
}
return;
}
/*---------------------------------------------------------*\
| ITE 8291: row-based color transfer |
\*---------------------------------------------------------*/
unsigned char ctrl_buf[CLEVO_8291_REPORT_SIZE];
unsigned char row_buf[CLEVO_8291_ROW_DATA_SIZE];
if(brightness > CLEVO_8291_BRIGHTNESS_MAX)
{
brightness = CLEVO_8291_BRIGHTNESS_MAX;
}
memset(ctrl_buf, 0x00, CLEVO_8291_REPORT_SIZE);
ctrl_buf[0] = CLEVO_8291_CMD_MODE;
ctrl_buf[1] = CLEVO_8291_POWER_ON;
ctrl_buf[2] = CLEVO_KEYBOARD_MODE_DIRECT;
memset(ctrl_buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
ctrl_buf[0] = 0x08;
ctrl_buf[1] = 0x02; // Power on
ctrl_buf[2] = CLEVO_KEYBOARD_MODE_DIRECT; // Per-key mode
ctrl_buf[3] = 0x00; // Speed (unused)
ctrl_buf[4] = brightness;
WriteControl8291(ctrl_buf);
ctrl_buf[5] = 0x00;
ctrl_buf[6] = 0x00;
for(int row = 0; row < num_rows; row++)
WriteControl(ctrl_buf);
/*---------------------------------------------------------*\
| Send each row |
\*---------------------------------------------------------*/
for(int row = 0; row < CLEVO_KEYBOARD_NUM_ROWS; row++)
{
memset(ctrl_buf, 0x00, CLEVO_8291_REPORT_SIZE);
ctrl_buf[0] = CLEVO_8291_CMD_ROW;
/*-----------------------------------------------------*\
| Announce row data |
\*-----------------------------------------------------*/
memset(ctrl_buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
ctrl_buf[0] = 0x16;
ctrl_buf[1] = 0x00;
ctrl_buf[2] = row;
WriteControl8291(ctrl_buf);
memset(row_buf, 0x00, CLEVO_8291_ROW_DATA_SIZE);
WriteControl(ctrl_buf);
for(int col = 0; col < num_cols; col++)
/*-----------------------------------------------------*\
| Build row data buffer |
| Format: [pad][pad][B0..B20][G0..G20][R0..R20] |
\*-----------------------------------------------------*/
memset(row_buf, 0x00, CLEVO_KEYBOARD_ROW_DATA_SIZE);
for(int col = 0; col < CLEVO_KEYBOARD_NUM_COLS; col++)
{
int idx = (row * num_cols + col) * 3;
int led_idx = (row * CLEVO_KEYBOARD_NUM_COLS) + col;
int color_offset = led_idx * 3;
row_buf[2 + col] = color_data[idx + 2];
row_buf[2 + num_cols + col] = color_data[idx + 1];
row_buf[2 + num_cols * 2 + col] = color_data[idx + 0];
unsigned char red = color_data[color_offset + 0];
unsigned char green = color_data[color_offset + 1];
unsigned char blue = color_data[color_offset + 2];
/*-------------------------------------------------*\
| Row data layout (after 2-byte padding): |
| Bytes 2-22: Blue values for columns 0-20 |
| Bytes 23-43: Green values for columns 0-20 |
| Bytes 44-64: Red values for columns 0-20 |
\*-------------------------------------------------*/
row_buf[2 + col] = blue;
row_buf[2 + CLEVO_KEYBOARD_NUM_COLS + col] = green;
row_buf[2 + CLEVO_KEYBOARD_NUM_COLS*2 + col] = red;
}
WriteRowData(row_buf);
@@ -1,11 +1,9 @@
/*---------------------------------------------------------*\
| ClevoKeyboardController.h |
| |
| Driver for Clevo per-key RGB keyboard |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| Driver for Clevo laptop per-key RGB keyboard (ITE 8291) |
| |
| Kyle Cascade ([email protected]) 16 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -14,75 +12,27 @@
#pragma once
#include <string>
#include <vector>
#include <hidapi.h>
#include "RGBController.h"
/*---------------------------------------------------------*\
| Device type enumeration |
\*---------------------------------------------------------*/
enum clevo_keyboard_type
{
CLEVO_KB_ITE8291,
CLEVO_KB_ITE829X,
};
/*-----------------------------------------------------*\
| ITE 8291 keyboard defines |
\*-----------------------------------------------------*/
#define CLEVO_KEYBOARD_REPORT_SIZE 8
#define CLEVO_KEYBOARD_ROW_DATA_SIZE 65
/*---------------------------------------------------------*\
| ITE 8291 keyboard defines (PID 0x600B) |
| 8 bytes, no report ID, row-based color data |
\*---------------------------------------------------------*/
#define CLEVO_8291_REPORT_SIZE 8
#define CLEVO_8291_ROW_DATA_SIZE 65
#define CLEVO_8291_NUM_ROWS 6
#define CLEVO_8291_NUM_COLS 21
#define CLEVO_8291_NUM_LEDS (CLEVO_8291_NUM_ROWS * CLEVO_8291_NUM_COLS)
#define CLEVO_8291_BRIGHTNESS_MAX 0x32
#define CLEVO_8291_CMD_MODE 0x08
#define CLEVO_8291_CMD_COLOR 0x14
#define CLEVO_8291_CMD_ROW 0x16
#define CLEVO_8291_POWER_OFF 0x01
#define CLEVO_8291_POWER_ON 0x02
#define CLEVO_8291_MODE_FLAG 0x08
#define CLEVO_KEYBOARD_NUM_ROWS 6
#define CLEVO_KEYBOARD_NUM_COLS 21
#define CLEVO_KEYBOARD_NUM_LEDS (CLEVO_KEYBOARD_NUM_ROWS * CLEVO_KEYBOARD_NUM_COLS)
/*---------------------------------------------------------*\
| ITE 829x keyboard defines (PID 0x8910) |
| 6 bytes with report ID 0xCC, per-key color commands |
| Protocol: [0xCC, cmd, d0, d1, d2, d3] |
| LED ID: ((row & 0x07) << 5) | (col & 0x1F) |
\*---------------------------------------------------------*/
#define CLEVO_829X_REPORT_ID 0xCC
#define CLEVO_829X_REPORT_SIZE 6
#define CLEVO_829X_NUM_ROWS 6
#define CLEVO_829X_NUM_COLS 20
#define CLEVO_829X_NUM_LEDS (CLEVO_829X_NUM_ROWS * CLEVO_829X_NUM_COLS)
#define CLEVO_829X_BRIGHTNESS_MAX 0x0A
#define CLEVO_829X_LED_ID(row, col) (unsigned char)((((row) & 0x07) << 5) | ((col) & 0x1F))
#define CLEVO_829X_CMD_SET_LED 0x01
#define CLEVO_829X_CMD_BRIGHTNESS 0x09
#define CLEVO_829X_CMD_ANIM 0x00
#define CLEVO_829X_CMD_CLEAR 0x0C
#define CLEVO_829X_CMD_WAVE_COLOR 0x15
#define CLEVO_829X_CMD_SNAKE_COLOR 0x16
#define CLEVO_829X_CMD_SCAN_COLOR 0x17
#define CLEVO_829X_CMD_RANDOM_COLOR 0x18
#define CLEVO_829X_COLOR_CUSTOM 0xAA
#define CLEVO_829X_COLOR_SLOT_BASE 0xA1
#define CLEVO_829X_PRESET_SLOT_BASE 0x71
#define CLEVO_829X_CMD_SAVE_BIOS 0x20
#define CLEVO_829X_CMD_STOP_ANIM 0x03
/*---------------------------------------------------------*\
| Shared defines |
\*---------------------------------------------------------*/
#define CLEVO_KEYBOARD_BRIGHTNESS_MIN 0x00
#define CLEVO_KEYBOARD_SPEED_MIN 0x00
#define CLEVO_KEYBOARD_SPEED_MAX 0x0A
#define CLEVO_KEYBOARD_SPEED_DEFAULT 0x00
#define CLEVO_KEYBOARD_BRIGHTNESS_MAX 0x32
/*---------------------------------------------------------*\
| ITE 8291 modes |
\*---------------------------------------------------------*/
#define CLEVO_KEYBOARD_SPEED_MIN 0x01
#define CLEVO_KEYBOARD_SPEED_MAX 0x0A
/*-----------------------------------------------------*\
| ITE 8291 modes |
\*-----------------------------------------------------*/
enum
{
CLEVO_KEYBOARD_MODE_DIRECT = 0x33,
@@ -97,36 +47,9 @@ enum
CLEVO_KEYBOARD_MODE_SPARK = 0x11,
};
/*---------------------------------------------------------*\
| ITE 829x firmware modes |
| Two command styles: |
| cmd=0x00, d0=mode_id (animation select) |
| cmd=mode_id, d0=0x00 (standalone effects) |
\*---------------------------------------------------------*/
enum
{
CLEVO_829X_MODE_DIRECT = 0xFD,
CLEVO_829X_MODE_WAVE = 0xA0,
CLEVO_829X_MODE_WAVE_COLOR = 0xB0,
CLEVO_829X_MODE_BREATH = 0xA1,
CLEVO_829X_MODE_BREATH_COLOR = 0xB1,
CLEVO_829X_MODE_BLINK = 0xA2,
CLEVO_829X_MODE_BLINK_COLOR = 0xB2,
CLEVO_829X_MODE_RANDOM = 0xA3,
CLEVO_829X_MODE_RANDOM_COLOR = 0xA9,
CLEVO_829X_MODE_SCAN = 0xA4,
/* Ripple (0x07) requires Insyde BIOS EC config, not supported */
CLEVO_829X_MODE_SNAKE = 0xA6,
CLEVO_829X_MODE_SNAKE_COLOR = 0xB6,
CLEVO_829X_MODE_RAINBOW_CYCLE = 0xA7,
CLEVO_829X_MODE_RAINBOW_GRAD = 0xA8,
CLEVO_829X_MODE_FN_COLOR = 0xAF,
CLEVO_829X_MODE_OFF = 0xFF,
};
/*---------------------------------------------------------*\
| Wave/reactive behaviour |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Wave/reactive behaviour |
\*-----------------------------------------------------*/
enum
{
CLEVO_KEYBOARD_DIRECTION_LEFT = 0x01,
@@ -144,40 +67,23 @@ enum
class ClevoKeyboardController
{
public:
ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info, clevo_keyboard_type kb_type);
ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info);
~ClevoKeyboardController();
clevo_keyboard_type GetType();
int GetNumRows();
int GetNumCols();
int GetNumLEDs();
unsigned char GetBrightnessMax();
std::string GetDeviceLocation();
std::string GetSerialString();
std::string GetFirmwareVersion();
void TurnOff();
void SetMode(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char behaviour);
void SetModeColor(unsigned char color_idx, RGBColor color);
void SendColors(const unsigned char* color_data, unsigned char brightness, unsigned char speed);
void SetEffect829x(unsigned char mode_value, const std::vector<RGBColor>& colors, unsigned int direction = 0, unsigned int color_mode = 0);
void SetBrightnessSpeed829x(unsigned char brightness, unsigned char speed);
void SaveToBios829x();
void ClearBiosSave829x();
void StopAnimation829x();
void SetModeColor(unsigned char color_idx, unsigned char red, unsigned char green, unsigned char blue);
void SendColors(unsigned char* color_data, unsigned char brightness);
private:
hid_device* dev;
clevo_keyboard_type type;
std::string location;
unsigned short version;
unsigned char current_mode_829x = 0xFF;
unsigned char current_brightness_829x = 0xFF;
unsigned char current_speed_829x = 0xFF;
hid_device* dev;
std::string location;
unsigned short version;
void WriteControl8291(unsigned char* data);
void WriteControl(unsigned char* data);
void WriteRowData(unsigned char* data);
void SendCommand829x(unsigned char cmd, unsigned char d0 = 0, unsigned char d1 = 0, unsigned char d2 = 0, unsigned char d3 = 0);
void SendColorSlot829x(unsigned char cmd, unsigned char slot, RGBColor color);
};
@@ -1,11 +1,9 @@
/*---------------------------------------------------------*\
| ClevoKeyboardControllerDetect.cpp |
| |
| Detector for Clevo per-key RGB keyboard |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| Detector for Clevo per-key RGB keyboard (ITE 8291) |
| |
| Kyle Cascade ([email protected]) 16 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -24,12 +22,11 @@
/*---------------------------------------------------------*\
| Clevo Keyboard product IDs |
| ITE 8291 and ITE 829x per-key RGB keyboard controllers |
| These are ITE 8291 per-key RGB keyboard controllers |
\*---------------------------------------------------------*/
#define CLEVO_KEYBOARD_PID_8291 0x600B
#define CLEVO_KEYBOARD_PID_829X 0x8910
#define CLEVO_KEYBOARD_PID_600B 0x600B
static DetectedControllers DetectClevoKeyboard(hid_device_info* info, clevo_keyboard_type kb_type)
DetectedControllers DetectClevoKeyboardControllers(hid_device_info* info, const std::string& /*name*/)
{
DetectedControllers detected_controllers;
hid_device* dev;
@@ -38,7 +35,7 @@ static DetectedControllers DetectClevoKeyboard(hid_device_info* info, clevo_keyb
if(dev)
{
ClevoKeyboardController* controller = new ClevoKeyboardController(dev, *info, kb_type);
ClevoKeyboardController* controller = new ClevoKeyboardController(dev, *info);
RGBController_ClevoKeyboard* rgb_controller = new RGBController_ClevoKeyboard(controller);
detected_controllers.push_back(rgb_controller);
@@ -47,15 +44,4 @@ static DetectedControllers DetectClevoKeyboard(hid_device_info* info, clevo_keyb
return(detected_controllers);
}
DetectedControllers DetectClevoKeyboard8291(hid_device_info* info, const std::string& /*name*/)
{
return(DetectClevoKeyboard(info, CLEVO_KB_ITE8291));
}
DetectedControllers DetectClevoKeyboard829x(hid_device_info* info, const std::string& /*name*/)
{
return(DetectClevoKeyboard(info, CLEVO_KB_ITE829X));
}
REGISTER_HID_DETECTOR_PU("Clevo Keyboard (ITE 8291)", DetectClevoKeyboard8291, ITE_VID, CLEVO_KEYBOARD_PID_8291, 0xFF03, 0x01);
REGISTER_HID_DETECTOR_PU("Clevo Keyboard (ITE 829x)", DetectClevoKeyboard829x, ITE_VID, CLEVO_KEYBOARD_PID_829X, 0xFF89, 0xCC);
REGISTER_HID_DETECTOR_PU("CLEVO Keyboard", DetectClevoKeyboardControllers, 0x048D, 0x600B, 0xFF03, 0x01);
@@ -1,11 +1,9 @@
/*---------------------------------------------------------*\
| ClevoKeyboardDevices.cpp |
| |
| Device list for Clevo per-key RGB keyboards |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| Device list for Clevo per-key RGB keyboards (ITE 8291) |
| |
| Kyle Cascade ([email protected]) 21 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -114,48 +112,6 @@ static const std::vector<unsigned int> clevo_tkl_values =
15, // Right
};
/*---------------------------------------------------------*\
| ITE 829x LED value mapping |
| LED ID = ((row & 7) << 5) | col |
| Row 5 (F-keys) = 0xA0+, Row 4 (numbers) = 0x80+ |
| Row 3 (QWERTY) = 0x60+, Row 2 (home) = 0x40+ |
| Row 1 (Z row) = 0x20+, Row 0 (mods) = 0x00+ |
\*---------------------------------------------------------*/
static const std::vector<unsigned int> clevo_829x_full_values =
{
/*---------------------------------------------------------*\
| Values in FULL layout visual order (same as CM keyboard) |
| LED ID = ((row & 7) << 5) | col |
| Row counts: 16, 21, 21, 17, 18, 13 |
\*---------------------------------------------------------*/
/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0, 0,
/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC INS HOME PGUP NMLK NMDV NMTM NMMI */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2D, 0x2E, 0x0E, 0x10, 0x12, 0x30, 0x31, 0x32, 0x33,
/* TAB Q W E R T Y U I O P [ ] ANSI\ DEL END PGDN NM7 NM8 NM9 NMPL */
0x40, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x0F, 0x11, 0x13, 0x50, 0x51, 0x52, 0x53,
/* CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */
0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0, 0x6E, 0x70, 0x71, 0x72,
/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */
0x80, 0, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x92, 0x93,
/* LCTL LFNC LWIN LALT SPACE RALT RMNU RCTL ARWL ARDN ARWR NM0 NMPD */
0xA0, 0xA2, 0xA3, 0xA4, 0xA5, 0xAA, 0xAB, 0xAC, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2,
};
keyboard_keymap_overlay_values clevo_829x_keyboard_layout
{
KEYBOARD_SIZE_FULL,
{
clevo_829x_full_values,
{
/* No regional overlays needed */
}
},
{
/* No edit keys needed - all keys defined in full layout */
}
};
keyboard_keymap_overlay_values clevo_keyboard_layout
{
KEYBOARD_SIZE_TKL,
@@ -166,9 +122,10 @@ keyboard_keymap_overlay_values clevo_keyboard_layout
}
},
{
/*---------------------------------------------------------*\
| Edit Keys |
\*---------------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------------------------------------*\
| Edit Keys |
| Zone, Row, Column, Value, Key, Alternate Name, OpCode, |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------*\
| Remove keys not present on Clevo keyboard |
@@ -1,11 +1,9 @@
/*---------------------------------------------------------*\
| ClevoKeyboardDevices.h |
| |
| Device list for Clevo per-key RGB keyboards |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| Device list for Clevo per-key RGB keyboards (ITE 8291) |
| |
| Kyle Cascade ([email protected]) 21 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -16,8 +14,7 @@
#include <string>
#include "KeyboardLayoutManager.h"
/*---------------------------------------------------------*\
| Clevo keyboard layout definitions |
\*---------------------------------------------------------*/
/*-----------------------------------------------------*\
| Clevo keyboard layout definitions |
\*-----------------------------------------------------*/
extern keyboard_keymap_overlay_values clevo_keyboard_layout;
extern keyboard_keymap_overlay_values clevo_829x_keyboard_layout;
@@ -1,17 +1,14 @@
/*---------------------------------------------------------*\
| RGBController_ClevoKeyboard.cpp |
| |
| RGBController for Clevo per-key RGB keyboard |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| RGBController for Clevo per-key RGB keyboard (ITE 8291) |
| |
| Kyle Cascade ([email protected]) 16 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "RGBController_ClevoKeyboard.h"
#include "KeyboardLayoutManager.h"
@@ -43,306 +40,152 @@ RGBController_ClevoKeyboard::RGBController_ClevoKeyboard(ClevoKeyboardController
Direct.value = CLEVO_KEYBOARD_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Direct.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Direct.brightness_max = controller->GetBrightnessMax();
Direct.brightness = controller->GetBrightnessMax();
Direct.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Direct.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
/*---------------------------------------------------------*\
| ITE 8291 built-in effects (not available on ITE 829x) |
\*---------------------------------------------------------*/
if(controller->GetType() == CLEVO_KB_ITE8291)
{
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CLEVO_KEYBOARD_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Rainbow.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Rainbow.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Rainbow.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Rainbow.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Rainbow.brightness_max = controller->GetBrightnessMax();
Rainbow.brightness = controller->GetBrightnessMax();
Rainbow.color_mode = MODE_COLORS_NONE;
modes.push_back(Rainbow);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CLEVO_KEYBOARD_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Rainbow.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Rainbow.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Rainbow.speed = 0x05;
Rainbow.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Rainbow.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Rainbow.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Rainbow.color_mode = MODE_COLORS_NONE;
modes.push_back(Rainbow);
mode Wave;
Wave.name = "Wave";
Wave.value = CLEVO_KEYBOARD_MODE_WAVE;
Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Wave.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Wave.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Wave.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Wave.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Wave.brightness_max = controller->GetBrightnessMax();
Wave.brightness = controller->GetBrightnessMax();
Wave.direction = MODE_DIRECTION_LEFT;
Wave.colors_min = 1;
Wave.colors_max = 1;
Wave.colors.resize(1);
Wave.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Wave);
mode Wave;
Wave.name = "Wave";
Wave.value = CLEVO_KEYBOARD_MODE_WAVE;
Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Wave.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Wave.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Wave.speed = 0x05;
Wave.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Wave.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Wave.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Wave.direction = MODE_DIRECTION_LEFT;
Wave.colors_min = 1;
Wave.colors_max = 1;
Wave.colors.resize(1);
Wave.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Wave);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = CLEVO_KEYBOARD_MODE_BREATH;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Breathing.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Breathing.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Breathing.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Breathing.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Breathing.brightness_max = controller->GetBrightnessMax();
Breathing.brightness = controller->GetBrightnessMax();
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(1);
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Breathing);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = CLEVO_KEYBOARD_MODE_BREATH;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Breathing.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Breathing.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Breathing.speed = 0x05;
Breathing.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Breathing.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Breathing.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(1);
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Breathing);
mode Reactive;
Reactive.name = "Reactive";
Reactive.value = CLEVO_KEYBOARD_MODE_REACTIVE;
Reactive.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Reactive.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Reactive.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Reactive.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Reactive.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Reactive.brightness_max = controller->GetBrightnessMax();
Reactive.brightness = controller->GetBrightnessMax();
Reactive.colors_min = 1;
Reactive.colors_max = 1;
Reactive.colors.resize(1);
Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Reactive);
mode Reactive;
Reactive.name = "Reactive";
Reactive.value = CLEVO_KEYBOARD_MODE_REACTIVE;
Reactive.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Reactive.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Reactive.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Reactive.speed = 0x05;
Reactive.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Reactive.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Reactive.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Reactive.colors_min = 1;
Reactive.colors_max = 1;
Reactive.colors.resize(1);
Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Reactive);
mode Ripple;
Ripple.name = "Ripple";
Ripple.value = CLEVO_KEYBOARD_MODE_RIPPLE;
Ripple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Ripple.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Ripple.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Ripple.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Ripple.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Ripple.brightness_max = controller->GetBrightnessMax();
Ripple.brightness = controller->GetBrightnessMax();
Ripple.colors_min = 1;
Ripple.colors_max = 1;
Ripple.colors.resize(1);
Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Ripple);
mode Ripple;
Ripple.name = "Ripple";
Ripple.value = CLEVO_KEYBOARD_MODE_RIPPLE;
Ripple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Ripple.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Ripple.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Ripple.speed = 0x05;
Ripple.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Ripple.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Ripple.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Ripple.colors_min = 1;
Ripple.colors_max = 1;
Ripple.colors.resize(1);
Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Ripple);
mode Marquee;
Marquee.name = "Marquee";
Marquee.value = CLEVO_KEYBOARD_MODE_MARQUEE;
Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Marquee.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Marquee.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Marquee.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Marquee.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Marquee.brightness_max = controller->GetBrightnessMax();
Marquee.brightness = controller->GetBrightnessMax();
Marquee.colors_min = 1;
Marquee.colors_max = 1;
Marquee.colors.resize(1);
Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Marquee);
mode Marquee;
Marquee.name = "Marquee";
Marquee.value = CLEVO_KEYBOARD_MODE_MARQUEE;
Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Marquee.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Marquee.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Marquee.speed = 0x05;
Marquee.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Marquee.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Marquee.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Marquee.colors_min = 1;
Marquee.colors_max = 1;
Marquee.colors.resize(1);
Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Marquee);
mode Raindrop;
Raindrop.name = "Raindrop";
Raindrop.value = CLEVO_KEYBOARD_MODE_RAINDROP;
Raindrop.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Raindrop.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Raindrop.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Raindrop.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Raindrop.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Raindrop.brightness_max = controller->GetBrightnessMax();
Raindrop.brightness = controller->GetBrightnessMax();
Raindrop.colors_min = 1;
Raindrop.colors_max = 1;
Raindrop.colors.resize(1);
Raindrop.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Raindrop);
mode Raindrop;
Raindrop.name = "Raindrop";
Raindrop.value = CLEVO_KEYBOARD_MODE_RAINDROP;
Raindrop.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Raindrop.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Raindrop.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Raindrop.speed = 0x05;
Raindrop.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Raindrop.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Raindrop.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Raindrop.colors_min = 1;
Raindrop.colors_max = 1;
Raindrop.colors.resize(1);
Raindrop.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Raindrop);
mode Aurora;
Aurora.name = "Aurora";
Aurora.value = CLEVO_KEYBOARD_MODE_AURORA;
Aurora.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Aurora.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Aurora.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Aurora.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Aurora.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Aurora.brightness_max = controller->GetBrightnessMax();
Aurora.brightness = controller->GetBrightnessMax();
Aurora.colors_min = 1;
Aurora.colors_max = 1;
Aurora.colors.resize(1);
Aurora.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Aurora);
mode Aurora;
Aurora.name = "Aurora";
Aurora.value = CLEVO_KEYBOARD_MODE_AURORA;
Aurora.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Aurora.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Aurora.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Aurora.speed = 0x05;
Aurora.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Aurora.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Aurora.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Aurora.colors_min = 1;
Aurora.colors_max = 1;
Aurora.colors.resize(1);
Aurora.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Aurora);
mode Spark;
Spark.name = "Spark";
Spark.value = CLEVO_KEYBOARD_MODE_SPARK;
Spark.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Spark.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Spark.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Spark.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Spark.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Spark.brightness_max = controller->GetBrightnessMax();
Spark.brightness = controller->GetBrightnessMax();
Spark.colors_min = 1;
Spark.colors_max = 1;
Spark.colors.resize(1);
Spark.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Spark);
}
/*---------------------------------------------------------*\
| ITE 829x firmware effects |
\*---------------------------------------------------------*/
if(controller->GetType() == CLEVO_KB_ITE829X)
{
unsigned char bmax = controller->GetBrightnessMax();
mode Wave;
Wave.name = "Wave";
Wave.value = CLEVO_829X_MODE_WAVE;
Wave.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_DIRECTION_DIAG;
Wave.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
Wave.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
Wave.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Wave.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Wave.brightness_max = bmax;
Wave.brightness = bmax;
Wave.direction = MODE_DIRECTION_LEFT;
Wave.colors_min = 1;
Wave.colors_max = 1;
Wave.colors.resize(1, ToRGBColor(255, 0, 0));
Wave.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Wave);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = CLEVO_829X_MODE_BREATH;
Breathing.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
Breathing.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
Breathing.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
Breathing.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Breathing.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Breathing.brightness_max = bmax;
Breathing.brightness = bmax;
Breathing.colors_min = 1;
Breathing.colors_max = 1;
Breathing.colors.resize(1, ToRGBColor(255, 0, 0));
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Breathing);
mode Flashing;
Flashing.name = "Flashing";
Flashing.value = CLEVO_829X_MODE_BLINK;
Flashing.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
Flashing.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
Flashing.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
Flashing.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Flashing.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Flashing.brightness_max = bmax;
Flashing.brightness = bmax;
Flashing.colors_min = 1;
Flashing.colors_max = 1;
Flashing.colors.resize(1, ToRGBColor(255, 0, 0));
Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Flashing);
mode Random;
Random.name = "Random";
Random.value = CLEVO_829X_MODE_RANDOM;
Random.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR;
Random.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
Random.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
Random.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Random.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Random.brightness_max = bmax;
Random.brightness = bmax;
Random.colors_min = 1;
Random.colors_max = 1;
Random.colors.resize(1, ToRGBColor(255, 0, 0));
Random.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Random);
mode Scan;
Scan.name = "Scan";
Scan.value = CLEVO_829X_MODE_SCAN;
Scan.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Scan.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
Scan.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
Scan.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Scan.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Scan.brightness_max = bmax;
Scan.brightness = bmax;
Scan.colors_min = 2;
Scan.colors_max = 2;
Scan.colors.resize(2);
Scan.colors[0] = ToRGBColor(255, 0, 0);
Scan.colors[1] = ToRGBColor(0, 0, 255);
Scan.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Scan);
mode Snake;
Snake.name = "Snake";
Snake.value = CLEVO_829X_MODE_SNAKE;
Snake.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_DIAG;
Snake.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
Snake.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
Snake.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
Snake.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Snake.brightness_max = bmax;
Snake.brightness = bmax;
Snake.direction = MODE_DIRECTION_UP_LEFT;
Snake.colors_min = 1;
Snake.colors_max = 1;
Snake.colors.resize(1, ToRGBColor(255, 0, 0));
Snake.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Snake);
mode RainbowCycle;
RainbowCycle.name = "Spectrum Cycle";
RainbowCycle.value = CLEVO_829X_MODE_RAINBOW_CYCLE;
RainbowCycle.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
RainbowCycle.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
RainbowCycle.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
RainbowCycle.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
RainbowCycle.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
RainbowCycle.brightness_max = bmax;
RainbowCycle.brightness = bmax;
RainbowCycle.color_mode = MODE_COLORS_NONE;
modes.push_back(RainbowCycle);
mode RainbowGrad;
RainbowGrad.name = "Rainbow Wave";
RainbowGrad.value = CLEVO_829X_MODE_RAINBOW_GRAD;
RainbowGrad.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_DIRECTION_DIAG;
RainbowGrad.speed_min = CLEVO_KEYBOARD_SPEED_MIN;
RainbowGrad.speed_max = CLEVO_KEYBOARD_SPEED_MAX;
RainbowGrad.speed = CLEVO_KEYBOARD_SPEED_DEFAULT;
RainbowGrad.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
RainbowGrad.brightness_max = bmax;
RainbowGrad.brightness = bmax;
RainbowGrad.direction = MODE_DIRECTION_LEFT;
RainbowGrad.color_mode = MODE_COLORS_NONE;
modes.push_back(RainbowGrad);
mode FnColor;
FnColor.name = "Fn Highlight";
FnColor.value = CLEVO_829X_MODE_FN_COLOR;
FnColor.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
FnColor.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
FnColor.brightness_max = bmax;
FnColor.brightness = bmax;
FnColor.colors_min = 1;
FnColor.colors_max = 1;
FnColor.colors.resize(1, ToRGBColor(255, 0, 0));
FnColor.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(FnColor);
}
mode Spark;
Spark.name = "Spark";
Spark.value = CLEVO_KEYBOARD_MODE_SPARK;
Spark.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
Spark.speed_min = CLEVO_KEYBOARD_SPEED_MAX;
Spark.speed_max = CLEVO_KEYBOARD_SPEED_MIN;
Spark.speed = 0x05;
Spark.brightness_min = CLEVO_KEYBOARD_BRIGHTNESS_MIN;
Spark.brightness_max = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Spark.brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
Spark.colors_min = 1;
Spark.colors_max = 1;
Spark.colors.resize(1);
Spark.color_mode = MODE_COLORS_MODE_SPECIFIC;
modes.push_back(Spark);
mode Off;
Off.name = "Off";
@@ -364,22 +207,16 @@ RGBController_ClevoKeyboard::~RGBController_ClevoKeyboard()
void RGBController_ClevoKeyboard::SetupZones()
{
/*---------------------------------------------------------*\
| Select layout based on device type |
| Create keyboard layout using KeyboardLayoutManager |
\*---------------------------------------------------------*/
bool is_829x = (controller->GetType() == CLEVO_KB_ITE829X);
keyboard_keymap_overlay_values& layout = is_829x
? clevo_829x_keyboard_layout
: clevo_keyboard_layout;
KeyboardLayoutManager new_kb(KEYBOARD_LAYOUT_ISO_QWERTY,
layout.base_size,
layout.key_values);
clevo_keyboard_layout.base_size,
clevo_keyboard_layout.key_values);
new_kb.ChangeKeys(layout);
new_kb.ChangeKeys(clevo_keyboard_layout);
/*---------------------------------------------------------*\
| Create keyboard zone from KLM |
| Create a matrix zone for the keyboard |
\*---------------------------------------------------------*/
zone keyboard_zone;
@@ -396,6 +233,9 @@ void RGBController_ClevoKeyboard::SetupZones()
zones.push_back(keyboard_zone);
/*---------------------------------------------------------*\
| Create LEDs from the KeyboardLayoutManager data |
\*---------------------------------------------------------*/
for(unsigned int led_idx = 0; led_idx < keyboard_zone.leds_count; led_idx++)
{
led new_led;
@@ -409,48 +249,36 @@ void RGBController_ClevoKeyboard::SetupZones()
SetupColors();
/*---------------------------------------------------------*\
| Build buffer map from LED values to color pointers |
| 829x LED IDs have gaps (stride 32), need larger map |
| Create buffer map to translate OpenRGB LED order to |
| hardware LED order. The hardware expects 126 color values |
| indexed by LED position (0-125). |
\*---------------------------------------------------------*/
null_color = 0x00000000;
size_t map_size = is_829x
? CLEVO_829X_LED_ID(CLEVO_829X_NUM_ROWS - 1, CLEVO_829X_NUM_COLS - 1) + 1
: (size_t)controller->GetNumLEDs();
buffer_map.resize(map_size, &null_color);
buffer_map.resize(CLEVO_KEYBOARD_NUM_LEDS, &null_color);
for(size_t led_idx = 0; led_idx < leds.size(); led_idx++)
{
if(leds[led_idx].value < buffer_map.size())
{
buffer_map[leds[led_idx].value] = &colors[led_idx];
}
buffer_map[leds[led_idx].value] = &colors[led_idx];
}
}
void RGBController_ClevoKeyboard::DeviceUpdateLEDs()
{
int num_rows = controller->GetNumRows();
int num_cols = controller->GetNumCols();
bool is_829x = (controller->GetType() == CLEVO_KB_ITE829X);
/*---------------------------------------------------------*\
| Build color data array using buffer map and send to device|
| The buffer_map translates from hardware LED index to the |
| corresponding color pointer for that LED. |
\*---------------------------------------------------------*/
unsigned char color_data[CLEVO_KEYBOARD_NUM_LEDS * 3];
std::vector<unsigned char> color_data(num_rows * num_cols * 3);
for(int row = 0; row < num_rows; row++)
for(int i = 0; i < CLEVO_KEYBOARD_NUM_LEDS; i++)
{
for(int col = 0; col < num_cols; col++)
{
int seq = row * num_cols + col;
int led_id = is_829x ? CLEVO_829X_LED_ID(row, col) : seq;
color_data[seq * 3 + 0] = RGBGetRValue(*buffer_map[led_id]);
color_data[seq * 3 + 1] = RGBGetGValue(*buffer_map[led_id]);
color_data[seq * 3 + 2] = RGBGetBValue(*buffer_map[led_id]);
}
color_data[i * 3 + 0] = RGBGetRValue(*buffer_map[i]);
color_data[i * 3 + 1] = RGBGetGValue(*buffer_map[i]);
color_data[i * 3 + 2] = RGBGetBValue(*buffer_map[i]);
}
controller->SendColors(color_data.data(), modes[active_mode].brightness, modes[active_mode].speed);
controller->SendColors(color_data, modes[active_mode].brightness);
}
void RGBController_ClevoKeyboard::DeviceUpdateZoneLEDs(int /*zone*/)
@@ -476,16 +304,6 @@ void RGBController_ClevoKeyboard::DeviceUpdateMode()
return;
}
/*---------------------------------------------------------*\
| Handle ITE 829x firmware effects |
\*---------------------------------------------------------*/
if(controller->GetType() == CLEVO_KB_ITE829X && mode_value != CLEVO_KEYBOARD_MODE_DIRECT)
{
controller->SetEffect829x(mode_value, modes[active_mode].colors, modes[active_mode].direction, modes[active_mode].color_mode);
controller->SetBrightnessSpeed829x(modes[active_mode].brightness, modes[active_mode].speed);
return;
}
/*---------------------------------------------------------*\
| Handle Direct (per-key) mode |
\*---------------------------------------------------------*/
@@ -500,26 +318,41 @@ void RGBController_ClevoKeyboard::DeviceUpdateMode()
\*---------------------------------------------------------*/
unsigned char brightness = modes[active_mode].brightness;
unsigned char speed = modes[active_mode].speed;
unsigned char behaviour = (mode_value == CLEVO_KEYBOARD_MODE_WAVE)
? modes[active_mode].direction + 1
: 0x00;
unsigned char behaviour = 0x00;
/*---------------------------------------------------------*\
| Set direction for wave mode |
\*---------------------------------------------------------*/
if(mode_value == CLEVO_KEYBOARD_MODE_WAVE)
{
switch(modes[active_mode].direction)
{
case MODE_DIRECTION_LEFT:
behaviour = CLEVO_KEYBOARD_DIRECTION_LEFT;
break;
case MODE_DIRECTION_RIGHT:
behaviour = CLEVO_KEYBOARD_DIRECTION_RIGHT;
break;
case MODE_DIRECTION_UP:
behaviour = CLEVO_KEYBOARD_DIRECTION_UP;
break;
case MODE_DIRECTION_DOWN:
behaviour = CLEVO_KEYBOARD_DIRECTION_DOWN;
break;
}
}
/*---------------------------------------------------------*\
| Set mode color if applicable |
\*---------------------------------------------------------*/
if(modes[active_mode].colors.size() > 0)
{
controller->SetModeColor(1, modes[active_mode].colors[0]);
unsigned char red = RGBGetRValue(modes[active_mode].colors[0]);
unsigned char green = RGBGetGValue(modes[active_mode].colors[0]);
unsigned char blue = RGBGetBValue(modes[active_mode].colors[0]);
controller->SetModeColor(1, red, green, blue);
}
controller->SetMode(mode_value, brightness, speed, behaviour);
}
void RGBController_ClevoKeyboard::DeviceSaveMode()
{
if(controller->GetType() == CLEVO_KB_ITE829X)
{
DeviceUpdateMode();
controller->SaveToBios829x();
}
}
@@ -1,11 +1,9 @@
/*---------------------------------------------------------*\
| RGBController_ClevoKeyboard.h |
| |
| RGBController for Clevo per-key RGB keyboard |
| Supports ITE 8291 (PID 0x600B) and ITE 829x (0x8910) |
| RGBController for Clevo per-key RGB keyboard (ITE 8291) |
| |
| Kyle Cascade ([email protected]) 16 Jan 2026 |
| Valentin Lobstein ([email protected]) 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -20,7 +18,7 @@
class RGBController_ClevoKeyboard : public RGBController
{
public:
explicit RGBController_ClevoKeyboard(ClevoKeyboardController* controller_ptr);
RGBController_ClevoKeyboard(ClevoKeyboardController* controller_ptr);
~RGBController_ClevoKeyboard();
void SetupZones();
@@ -30,7 +28,6 @@ public:
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
void DeviceSaveMode();
private:
ClevoKeyboardController* controller;
@@ -45,8 +45,7 @@ void ColorfulGPUController::SetDirect(RGBColor color)
uint8_t g = RGBGetGValue(color);
uint8_t b = RGBGetBValue(color);
if(this->bus->info.pci_subsystem_device == COLORFUL_IGAME_RTX_4070_VULCAN_OCV
|| this->bus->info.pci_subsystem_device == COLORFUL_IGAME_RTX_4090_NEPTUNE_OCV)
if(this->bus->info.pci_subsystem_device == COLORFUL_IGAME_RTX_4070_VULCAN_OCV)
{
uint8_t data_pkt[COLORFUL_PACKET_LENGTH_V2] = { 0xAA, 0xEF, 0x01, 0x04, 0x88, 0x26 };
for(int i=6; i < COLORFUL_PACKET_LENGTH_V2 -2; i = i + 3)
@@ -52,7 +52,7 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Advanced OC 12G L-V", Detec
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA106_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060TI_ADVANCED_OC, 0x61);
@@ -71,17 +71,11 @@ REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ti SUPER Advanced OC-V", Detec
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ti SUPER Ultra W", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070TI_SUPER_ULTRA_W, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 SUPER Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070_SUPER_ULTRA_W_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Vulcan OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070_VULCAN_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070_ULTRAW_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 SUPER Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070S_ULTRAW_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Neptune OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_NEPTUNE_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060_ULTRAW_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060_ULTRAW_OC_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC_2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5060 Ti Ultra W DUO OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5060TI_ULTRAW_DUO_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV2, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ti Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070TI_ULTRAW_OC, 0x61);
REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 5070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_5070_ULTRAW_OCV2, 0x61);
@@ -340,6 +340,7 @@ void CorsairCommanderCoreController::SetDirectColor
lastzones = zones;
int packet_offset = 0;
int led_idx = 0;
int channel_idx = 0;
int packet_len = CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH;
if(pid == CORSAIR_COMMANDER_CORE_XT_PID)
@@ -368,6 +369,8 @@ void CorsairCommanderCoreController::SetDirectColor
{
packet_offset += 3 * (34 - zones[zone_idx].leds_count);
}
channel_idx++;
}
/*-----------------------------------------------------*\
@@ -26,7 +26,6 @@ CorsairDRAMController::CorsairDRAMController(i2c_smbus_interface *bus, corsair_d
this->bus = bus;
this->dev = dev;
device_index = 0;
direct_mode = true;
pid = 0;
vid = 0;
protocol_version = 0;
@@ -133,77 +132,13 @@ void CorsairDRAMController::SetColorsPerLED(RGBColor* colors)
| bytes, use a second block write to the second |
| block write address for the remaining data |
\*-------------------------------------------------*/
s32 ret = bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_1, 32, direct_packet);
bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_1, 32, direct_packet);
if((ret >= 0) && (direct_packet_size > 32))
if(direct_packet_size > 32)
{
bus->i2c_smbus_write_block_data(dev, CORSAIR_DRAM_REG_COLOR_BUFFER_BLOCK_2, direct_packet_size - 32, direct_packet + 32);
}
/*-------------------------------------------------*\
| Corsair DRAM supports an alternate means of |
| writing block data without using SMBus block |
| operations. If block operations are not |
| available, fall back to this scheme. |
| |
| Blocks are split up into word data writes. |
| Some data bytes are packed into the lower nibble |
| of the register address byte. |
\*-------------------------------------------------*/
if(ret < 0)
{
unsigned int block_index = 0;
while(block_index < direct_packet_size)
{
unsigned char reg_value_0 = 0xA0;
unsigned char reg_value_1 = 0x00;
unsigned short word_value_0 = 0;
unsigned short word_value_1 = 0;
if(block_index == 0)
{
reg_value_0 = 0x90;
}
word_value_0 = (direct_packet[block_index]);
block_index++;
if(block_index < direct_packet_size)
{
word_value_0 |= (direct_packet[block_index] << 8);
block_index++;
}
if(block_index < direct_packet_size)
{
reg_value_1 = 0xA0;
reg_value_0 |= (direct_packet[block_index] & 0x0F);
reg_value_1 |= (direct_packet[block_index] & 0xF0) >> 4;
block_index++;
}
if(block_index < direct_packet_size)
{
word_value_1 = (direct_packet[block_index]);
block_index++;
}
if(block_index < direct_packet_size)
{
word_value_1 |= (direct_packet[block_index] << 8);
block_index++;
}
bus->i2c_smbus_write_word_data(dev, reg_value_0, word_value_0);
if(reg_value_1 > 0)
{
bus->i2c_smbus_write_word_data(dev, reg_value_1, word_value_1);
}
}
}
/*-------------------------------------------------*\
| Remember to delete the data buffer |
\*-------------------------------------------------*/
@@ -24,15 +24,18 @@ using namespace std::chrono_literals;
bool TestForCorsairDRAMController(i2c_smbus_interface *bus, unsigned char address)
{
LOG_DEBUG("[%s] Trying address %02X", CORSAIR_DRAM_NAME, address);
int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE);
int res = bus->i2c_smbus_read_byte_data(address, 0x43);
LOG_DEBUG("[%s] Trying address %02X", CORSAIR_DRAM_NAME, address);
if(res < 0)
{
LOG_DEBUG("[%s] Failed: res was %04X", CORSAIR_DRAM_NAME, res);
return false;
}
res = bus->i2c_smbus_read_byte_data(address, 0x43);
if(!(res == 0x1A || res == 0x1B || res == 0x1C))
{
LOG_DEBUG("[%s] Failed: expected 0x1A, 0x1B, or 0x1C, got %04X", CORSAIR_DRAM_NAME, res);
@@ -98,16 +98,7 @@ void RGBController_CorsairICueLink::SetupZones()
lcd_zone.leds_min = controller->GetEndpoints()[lcd_idx]->led_channels;
lcd_zone.leds_max = lcd_zone.leds_min;
lcd_zone.leds_count = lcd_zone.leds_min;
zones.push_back(lcd_zone);
for(unsigned int led_idx = 0; led_idx < lcd_zone.leds_count; led_idx++)
{
led new_led;
new_led.name = "LED " + std::to_string(led_idx + 1);
leds.push_back(new_led);
}
}
}
}
@@ -365,7 +365,7 @@ void RGBController_CorsairLightingNode::SetupZones()
new_led.name = zones[zone_idx].name + ", LED " + std::to_string(led_ch_idx + 1);
leds.push_back(new_led);
leds_channel.push_back((unsigned int)zone_idx);
leds_channel.push_back(zone_idx);
}
}
@@ -413,7 +413,7 @@ void RGBController_CorsairLightingNode::DeviceUpdateMode()
{
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
DeviceUpdateZoneMode((int)zone_idx);
DeviceUpdateZoneMode(zone_idx);
}
}
@@ -526,26 +526,27 @@ void CorsairPeripheralController::ReadFirmwareInfo()
char offset = 0;
/*-----------------------------------------------------*\
| Some Corsair keyboards (e.g. K70 RGB MK.2) do not |
| answer the firmware-info query on the control |
| interface until several seconds after the host first |
| talks to them following a cold boot. A single read |
| attempt returns all zeros, the device type comes back |
| as 0x00, and the device is discarded as UNKNOWN. |
| Retry the query until a valid device type byte is |
| returned or the attempt cap is reached. Each failed |
| attempt is paced by the 1s hid_read_timeout below, so |
| the cap also bounds the detection stall for a device |
| that opens but never answers. Observed need |
| on a K70 RGB MK.2 cold boot is 2 attempts; the cap |
| leaves generous headroom. |
| Zero out buffer |
\*-----------------------------------------------------*/
int attempt = 0;
memset(usb_buf, 0x00, CORSAIR_PERIPHERAL_PACKET_LENGTH);
do
/*-----------------------------------------------------*\
| Set up Read Firmware Info packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_COMMAND_READ;
usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO;
/*-----------------------------------------------------*\
| Send packet and try reading it using an HID read |
| If that fails, repeat the send and read the reply as |
| a feature report. |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
actual = hid_read_timeout(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH, 1000);
if(actual == 0)
{
offset = 0;
/*-------------------------------------------------*\
| Zero out buffer |
\*-------------------------------------------------*/
@@ -558,48 +559,10 @@ void CorsairPeripheralController::ReadFirmwareInfo()
usb_buf[0x01] = CORSAIR_COMMAND_READ;
usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO;
/*-------------------------------------------------*\
| Send packet and try reading it using an HID read |
| If that fails, repeat the send and read the reply |
| as a feature report. |
\*-------------------------------------------------*/
hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
actual = hid_read_timeout(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH, 1000);
if(actual == 0)
{
/*---------------------------------------------*\
| Zero out buffer |
\*---------------------------------------------*/
memset(usb_buf, 0x00, CORSAIR_PERIPHERAL_PACKET_LENGTH);
/*---------------------------------------------*\
| Set up Read Firmware Info packet |
\*---------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_COMMAND_READ;
usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO;
hid_send_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
actual = hid_get_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
offset = 1;
}
attempt++;
LOG_DEBUG("[%s] Firmware info attempt %d/%d: device type %02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, attempt, CORSAIR_FW_INFO_MAX_ATTEMPTS, usb_buf[0x14 + offset]);
/*-------------------------------------------------*\
| Stop as soon as a valid device type is returned |
| 0xC0 keyboard / 0xC1 mouse / 0xC2 pad or stand |
\*-------------------------------------------------*/
if(usb_buf[0x14 + offset] == 0xC0
|| usb_buf[0x14 + offset] == 0xC1
|| usb_buf[0x14 + offset] == 0xC2)
{
break;
}
} while(attempt < CORSAIR_FW_INFO_MAX_ATTEMPTS);
hid_send_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
actual = hid_get_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH);
offset = 1;
}
/*-----------------------------------------------------*\
| Get device type |
@@ -607,7 +570,7 @@ void CorsairPeripheralController::ReadFirmwareInfo()
| 0xC1 Device is a mouse |
| 0xC2 Device is a mousepad or headset stand |
\*-----------------------------------------------------*/
LOG_DEBUG("[%s] Device type %02X after %d attempt(s)", CORSAIR_PERIPHERAL_CONTROLLER_NAME, usb_buf[0x14 + offset], attempt);
LOG_DEBUG("[%s] Device type %02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, usb_buf[0x14 + offset]);
switch(usb_buf[0x14 + offset])
{
@@ -16,7 +16,6 @@
#include "RGBController.h"
#define CORSAIR_PERIPHERAL_PACKET_LENGTH 65
#define CORSAIR_FW_INFO_MAX_ATTEMPTS 10
enum
{
@@ -35,12 +35,6 @@ CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_han
write_cmd = CORSAIR_V2_WRITE_WIRELESS_ID;
pid = GetAddress(0x12);
break;
case CORSAIR_K57_RGB_WIRED_PID:
write_cmd = 0x80;
light_ctrl = CORSAIR_V2_LIGHT_CTRL1;
skip_reads = true;
break;
}
/*---------------------------------------------------------*\
@@ -99,17 +93,14 @@ CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_han
| If lighting control endpoint 2 is unavailable |
| then use endpoint 1. |
\*---------------------------------------------------------*/
if(light_ctrl == CORSAIR_V2_LIGHT_CTRL2)
result = StartTransaction(0);
if(result > 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);
light_ctrl = CORSAIR_V2_LIGHT_CTRL1;
StartTransaction(0);
}
StopTransaction(0);
LOG_DEBUG("[%s] Lighting Endpoint set to %02X", device_name.c_str(), light_ctrl);
}
CorsairPeripheralV2Controller::~CorsairPeripheralV2Controller()
@@ -180,11 +171,7 @@ void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode)
buffer[5] = mode;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1)
@@ -204,11 +191,7 @@ void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1)
buffer[5] = 0x00;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
unsigned int CorsairPeripheralV2Controller::GetKeyboardLayout()
@@ -257,11 +240,7 @@ unsigned char CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1)
buffer[4] = light_ctrl;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
return buffer[2];
}
@@ -278,20 +257,11 @@ void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1)
buffer[4] = opt1;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT);
}
void CorsairPeripheralV2Controller::ClearPacketBuffer()
{
if(skip_reads)
{
return;
}
uint8_t result = 0;
uint8_t buffer[CORSAIR_V2_PACKET_SIZE];
@@ -334,11 +304,7 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
memcpy(&buffer[offset1], &data[0], copy_bytes);
hid_write(dev, buffer, pkt_sze);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
}
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
remaining -= copy_bytes;
buffer[2] = CORSAIR_V2_CMD_BLK_WN;
@@ -359,11 +325,7 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
memcpy(&buffer[offset2], &data[index], copy_bytes);
hid_write(dev, buffer, pkt_sze);
if(!skip_reads)
{
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
}
hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT);
remaining -= copy_bytes;
}
@@ -109,7 +109,6 @@ private:
uint8_t write_cmd = CORSAIR_V2_WRITE_WIRED_ID;
uint16_t pkt_sze = CORSAIR_V2_WRITE_SIZE;
bool skip_reads = false;
std::string firmware_version;
std::string location;
};
@@ -67,7 +67,6 @@ DetectedControllers DetectCorsairV2SoftwareControllers(hid_device_info* info, co
| Keyboards |
\*---------------------------------------------------------*/
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 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);
@@ -48,31 +48,6 @@ std::vector<unsigned int> corsair_full_size_values =
/*-------------------------------------------------------------------------*\
| KEYMAPS |
\*-------------------------------------------------------------------------*/
keyboard_keymap_overlay_values corsair_K57_layout
{
KEYBOARD_SIZE::KEYBOARD_SIZE_FULL,
{
corsair_full_size_values,
{
/* Add more regional layout fixes here */
}
},
{
/*-------------------------------------------------------------------------------------------------------------------------------------*\
| Edit Keys |
| Zone, Row, Column, Value, Name, Alternate Name, OpCode |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
{ 0, 0, 17, 0, "Power/Wireless Indicator", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Profile into new row
{ 0, 0, 18, 1, "Lock/Macro Indicator", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Light key
{ 0, 1, 0, 131, "Key: G1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert G1 key
{ 0, 2, 0, 132, "Key: G2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert G2 key
{ 0, 3, 0, 133, "Key: G3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert G3 key
{ 0, 4, 0, 134, "Key: G4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert G4 key
{ 0, 5, 0, 135, "Key: G5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert G5 key
{ 0, 6, 0, 136, "Key: G6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert G6 key
}
};
keyboard_keymap_overlay_values corsair_K60_layout
{
KEYBOARD_SIZE::KEYBOARD_SIZE_FULL,
@@ -141,14 +116,12 @@ keyboard_keymap_overlay_values corsair_k70_pro_layout
{ 0, 0, 0, 128, "Profile", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Profile into new row
{ 0, 0, 1, 113, "Light", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Light key
{ 0, 0, 2, 114, "Lock", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lock Key
{ 0, 0, 10, 138, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Logo
{ 0, 0, 10, 191, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Logo
{ 0, 0, 18, 102, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Mute Key
{ 0, 1, 17, 123, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Stop Key
{ 0, 1, 18, 126, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Previous Track Key
{ 0, 1, 19, 124, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Play Pause Key
{ 0, 1, 20, 125, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Next Tack Key
{ 0, 6, 5, 140, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert spacebar L
{ 0, 6, 7, 141, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert spacebar R
}
};
@@ -194,10 +167,10 @@ keyboard_keymap_overlay_values corsair_K70_CORE_TKL_layout
| Edit Keys |
| Zone, Row, Column, Value, Name, Alternate Name, OpCode, |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
{ 0, 0, 14, 70, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRSC with Mute
{ 0, 0, 14, 70, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRSC with Mute
{ 0, 0, 15, 71, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove SCLK
{ 0, 0, 16, 72, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PSBK with Volume Potion Up
{ 0, 0, 16, 72, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PSBK with Volume Potion Up
}
};
@@ -799,38 +772,6 @@ static const corsair_v2_device k55_rgb_pro_device =
nullptr
};
/*-------------------------------------------------------------*\
| Corsair K57 RGB (Wired) 1B1C:1B6E |
| |
| Zone "Keyboard" |
| Matrix |
| 7 Rows, 22 Columns |
\*-------------------------------------------------------------*/
static const corsair_v2_zone k57_rgb_wired_zone =
{
ZONE_EN_KEYBOARD,
ZONE_TYPE_MATRIX,
7,
22
};
static const corsair_v2_device k57_rgb_wired_device =
{
CORSAIR_K57_RGB_WIRED_PID,
DEVICE_TYPE_KEYBOARD,
7,
22,
{
&k57_rgb_wired_zone,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
},
&corsair_K57_layout
};
/*-------------------------------------------------------------*\
| Corsair K60 RGB Pro 1B1C:1BA0 |
| |
@@ -1520,7 +1461,6 @@ const corsair_v2_device* corsair_v2_device_list_data[] =
| KEYBOARDS |
\*-----------------------------------------------------------------*/
&k55_rgb_pro_device,
&k57_rgb_wired_device,
&k60_rgb_pro_device,
&k60_rgb_pro_lp_device,
&k60_rgb_pro_tkl_device_b,
@@ -69,8 +69,6 @@ typedef struct
| Corsair V2 Protocol Keyboards |
\*-----------------------------------------------------*/
#define CORSAIR_K55_RGB_PRO_PID 0x1BA4
#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_LP_PID 0x1BAD
#define CORSAIR_K60_RGB_PRO_TKL_B_PID 0x1BC7
@@ -0,0 +1,217 @@
/*---------------------------------------------------------*\
| CorsairWirelessController.cpp |
| |
| Driver for Corsair wireless keyboard |
| |
| Adam Honse (CalcProgrammer1) 08 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "CorsairWirelessController.h"
#include "StringUtils.h"
using namespace std::chrono_literals;
CorsairWirelessController::CorsairWirelessController(hid_device* dev_handle, const char* path)
{
dev = dev_handle;
location = path;
type = DEVICE_TYPE_KEYBOARD;
EnterDirectMode();
}
CorsairWirelessController::~CorsairWirelessController()
{
hid_close(dev);
}
device_type CorsairWirelessController::GetDeviceType()
{
return type;
}
std::string CorsairWirelessController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string CorsairWirelessController::GetFirmwareString()
{
return firmware_version;
}
std::string CorsairWirelessController::GetName()
{
return name;
}
std::string CorsairWirelessController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void CorsairWirelessController::SetLEDs(std::vector<RGBColor>colors)
{
unsigned char buf[3 * 137];
for(int color = 0; color < 137; color++)
{
buf[0 + color] = RGBGetRValue(colors[color]);
buf[137 + color] = RGBGetGValue(colors[color]);
buf[274+color] = RGBGetBValue(colors[color]);
}
StartDirectMode();
SendDirectFrame(true, &buf[0]);
SendDirectFrame(false, &buf[57]);
SendDirectFrame(false, &buf[118]);
SendDirectFrame(false, &buf[179]);
SendDirectFrame(false, &buf[240]);
SendDirectFrame(false, &buf[301]);
SendDirectFrame(false, &buf[362]);
}
void CorsairWirelessController::SetName(std::string device_name)
{
name = device_name;
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void CorsairWirelessController::EnterDirectMode()
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Submit Mouse Colors packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x80;
usb_buf[0x02] = 0x01;
usb_buf[0x03] = 0x03;
usb_buf[0x04] = 0x00;
usb_buf[0x05] = 0x02;
/*-----------------------------------------------------*\
| Send packet using feature reports, as headset stand |
| seems to not update completely using HID writes |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
}
void CorsairWirelessController::StartDirectMode()
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Submit Mouse Colors packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x80;
usb_buf[0x02] = 0x0D;
usb_buf[0x03] = 0x00;
usb_buf[0x04] = 0x01;
/*-----------------------------------------------------*\
| Send packet using feature reports, as headset stand |
| seems to not update completely using HID writes |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
}
void CorsairWirelessController::ExitDirectMode()
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Submit Mouse Colors packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x80;
usb_buf[0x02] = 0x01;
usb_buf[0x03] = 0x03;
usb_buf[0x04] = 0x00;
usb_buf[0x05] = 0x01;
/*-----------------------------------------------------*\
| Send packet using feature reports, as headset stand |
| seems to not update completely using HID writes |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
}
void CorsairWirelessController::SendDirectFrame(bool first_frame, unsigned char* data)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Submit Mouse Colors packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x80;
usb_buf[0x02] = first_frame ? 0x06 : 0x07;
usb_buf[0x03] = 0x00;
if(first_frame)
{
usb_buf[0x04] = 0x9B;
usb_buf[0x05] = 0x01;
}
/*-----------------------------------------------------*\
| Copy in colors in <RED> <GREEN> <BLUE> order |
\*-----------------------------------------------------*/
if(first_frame)
{
memcpy(&usb_buf[0x08], data, 57);
}
else
{
memcpy(&usb_buf[0x04], data, 61);
}
/*-----------------------------------------------------*\
| Send packet using feature reports, as headset stand |
| seems to not update completely using HID writes |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
}
@@ -0,0 +1,45 @@
/*---------------------------------------------------------*\
| CorsairWirelessController.h |
| |
| Driver for Corsair wireless keyboard |
| |
| Adam Honse (CalcProgrammer1) 08 May 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"
class CorsairWirelessController
{
public:
CorsairWirelessController(hid_device* dev_handle, const char* path);
~CorsairWirelessController();
device_type GetDeviceType();
std::string GetDeviceLocation();
std::string GetFirmwareString();
std::string GetName();
std::string GetSerialString();
void SetLEDs(std::vector<RGBColor> colors);
void SetName(std::string device_name);
private:
hid_device* dev;
std::string firmware_version;
std::string location;
std::string name;
device_type type;
void EnterDirectMode();
void ExitDirectMode();
void StartDirectMode();
void SendDirectFrame(bool first_frame, unsigned char* data);
};
@@ -0,0 +1,59 @@
/*---------------------------------------------------------*\
| CorsairWirelessControllerDetect.cpp |
| |
| Detector for Corsair wireless keyboard |
| |
| Adam Honse (CalcProgrammer1) 08 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "CorsairWirelessController.h"
#include "RGBController.h"
#include "RGBController_CorsairWireless.h"
/*---------------------------------------------------------*\
| Corsair vendor ID |
\*---------------------------------------------------------*/
#define CORSAIR_VID 0x1B1C
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define CORSAIR_K57_RGB_WIRED_PID 0x1B6E
#define CORSAIR_K57_RGB_WIRELESS_PID 0x1B62
DetectedControllers DetectCorsairWirelessControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
CorsairWirelessController* controller = new CorsairWirelessController(dev, info->path);
controller->SetName(name);
if(controller->GetDeviceType() != DEVICE_TYPE_UNKNOWN)
{
RGBController_CorsairWireless* rgb_controller = new RGBController_CorsairWireless(controller);
detected_controllers.push_back(rgb_controller);
}
else
{
delete controller;
}
}
return(detected_controllers);
}
/*---------------------------------------------------------*\
| Keyboards |
\*---------------------------------------------------------*/
REGISTER_HID_DETECTOR_IPU("Corsair K57 RGB (Wired)", DetectCorsairWirelessControllers, CORSAIR_VID, CORSAIR_K57_RGB_WIRED_PID, 1, 0xFF42, 1);
//REGISTER_HID_DETECTOR_IPU("Corsair K57 RGB (Wireless)", DetectCorsairWirelessControllers, CORSAIR_VID, CORSAIR_K57_RGB_WIRELESS_PID, 1, 0xFF42, 1);
@@ -0,0 +1,319 @@
/*---------------------------------------------------------*\
| RGBController_CorsairWireless.cpp |
| |
| RGBController for Corsair wireless keyboard |
| |
| Adam Honse (CalcProgrammer1) 08 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_CorsairWireless.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[7][24] =
{ { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 1, NA, NA, NA },
{ 131, 41, NA, 58, 59, 60, 61, NA, 62, 63, 64, 65, NA, 66, 67, 68, 69, 70, 71, 72, NA, NA, NA, NA },
{ 132, 53, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, NA, 45, 46, 42, NA, 73, 74, 75, 83, 84, 85, 86 },
{ 133, 43, NA, 20, 26, 8, 21, NA, 23, 28, 24, 12, 18, 19, 47, 48, 49, 76, 77, 78, 95, 96, 97, 87 },
{ 134, 57, NA, 4, 22, 7, 9, NA, 10, 11, 13, 14, 15, 51, 52, NA, 40, NA, NA, NA, 92, 93, 94, NA },
{ 135, 106, NA, 29, 27, 6, 25, NA, 5, NA, 17, 16, 54, 55, 56, 110, NA, NA, 82, NA, 89, 90, 91, 88 },
{ 136, 105, 108, 107, NA, NA, NA, NA, 44, NA, NA, NA, NA, 111, 122, 101, 109, 80, 81, 79, 98, NA, 99, NA } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static const unsigned int zone_sizes[] =
{
137
};
static const zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const char* led_names[] =
{
"Power/Wireless Indicator",
"Lock/Macro Indicator",
"N/A",
"N/A",
KEY_EN_A,
KEY_EN_B,
KEY_EN_C,
KEY_EN_D,
KEY_EN_E,
KEY_EN_F,
KEY_EN_G,
KEY_EN_H,
KEY_EN_I,
KEY_EN_J,
KEY_EN_K,
KEY_EN_L,
KEY_EN_M,
KEY_EN_N,
KEY_EN_O,
KEY_EN_P,
KEY_EN_Q,
KEY_EN_R,
KEY_EN_S,
KEY_EN_T,
KEY_EN_U,
KEY_EN_V,
KEY_EN_W,
KEY_EN_X,
KEY_EN_Y,
KEY_EN_Z,
KEY_EN_1,
KEY_EN_2,
KEY_EN_3,
KEY_EN_4,
KEY_EN_5,
KEY_EN_6,
KEY_EN_7,
KEY_EN_8,
KEY_EN_9,
KEY_EN_0,
KEY_EN_ANSI_ENTER,
KEY_EN_ESCAPE,
KEY_EN_BACKSPACE,
KEY_EN_TAB,
KEY_EN_SPACE,
KEY_EN_MINUS,
KEY_EN_EQUALS,
KEY_EN_LEFT_BRACKET,
KEY_EN_RIGHT_BRACKET,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_UNUSED,
KEY_EN_SEMICOLON,
KEY_EN_QUOTE,
KEY_EN_BACK_TICK,
KEY_EN_COMMA,
KEY_EN_PERIOD,
KEY_EN_FORWARD_SLASH,
KEY_EN_CAPS_LOCK,
KEY_EN_F1,
KEY_EN_F2,
KEY_EN_F3,
KEY_EN_F4,
KEY_EN_F5,
KEY_EN_F6,
KEY_EN_F7,
KEY_EN_F8,
KEY_EN_F9,
KEY_EN_F10,
KEY_EN_F11,
KEY_EN_F12,
KEY_EN_PRINT_SCREEN,
KEY_EN_SCROLL_LOCK,
KEY_EN_PAUSE_BREAK,
KEY_EN_INSERT,
KEY_EN_HOME,
KEY_EN_PAGE_UP,
KEY_EN_DELETE,
KEY_EN_END,
KEY_EN_PAGE_DOWN,
KEY_EN_RIGHT_ARROW,
KEY_EN_LEFT_ARROW,
KEY_EN_DOWN_ARROW,
KEY_EN_UP_ARROW,
KEY_EN_NUMPAD_LOCK,
KEY_EN_NUMPAD_DIVIDE,
KEY_EN_NUMPAD_TIMES,
KEY_EN_NUMPAD_MINUS,
KEY_EN_NUMPAD_PLUS,
KEY_EN_NUMPAD_ENTER,
KEY_EN_NUMPAD_1,
KEY_EN_NUMPAD_2,
KEY_EN_NUMPAD_3,
KEY_EN_NUMPAD_4,
KEY_EN_NUMPAD_5,
KEY_EN_NUMPAD_6,
KEY_EN_NUMPAD_7,
KEY_EN_NUMPAD_8,
KEY_EN_NUMPAD_9,
KEY_EN_NUMPAD_0,
KEY_EN_NUMPAD_PERIOD,
KEY_EN_UNUSED,
KEY_EN_MENU,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_LEFT_CONTROL,
KEY_EN_LEFT_SHIFT,
KEY_EN_LEFT_ALT,
KEY_EN_LEFT_WINDOWS,
KEY_EN_RIGHT_CONTROL,
KEY_EN_RIGHT_SHIFT,
KEY_EN_RIGHT_ALT,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_RIGHT_FUNCTION,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
"Key: G1",
"Key: G2",
"Key: G3",
"Key: G4",
"Key: G5",
"Key: G6",
};
/**------------------------------------------------------------------*\
@name Corsair Wireless Peripheral
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectCorsairWirelessControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_CorsairWireless::RGBController_CorsairWireless(CorsairWirelessController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetName();
vendor = "Corsair";
description = "Corsair RGB Peripheral Device";
type = controller->GetDeviceType();
version = controller->GetFirmwareString();
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
/*-----------------------------------------------------*\
| The Corsair Lighting Node Pro requires a packet within|
| 20 seconds of sending the lighting change in order |
| to not revert back into rainbow mode. Start a thread |
| to continuously send a keepalive packet every 5s |
\*-----------------------------------------------------*/
keepalive_thread_run = true;
keepalive_thread = new std::thread(&RGBController_CorsairWireless::KeepaliveThread, this);
}
RGBController_CorsairWireless::~RGBController_CorsairWireless()
{
Shutdown();
/*-----------------------------------------------------*\
| Close keepalive thread |
\*-----------------------------------------------------*/
keepalive_thread_run = false;
keepalive_thread->join();
delete keepalive_thread;
delete controller;
}
void RGBController_CorsairWireless::SetupZones()
{
/*---------------------------------------------------------*\
| Determine number of zones |
| For now, keyboard has 2 zones and mousemat has 1 |
\*---------------------------------------------------------*/
unsigned int num_zones = 1;
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < num_zones; 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, 24, (unsigned int *)&matrix_map);
}
zones.push_back(new_zone);
total_led_count += new_zone.leds_count;
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_CorsairWireless::DeviceUpdateLEDs()
{
last_update_time = std::chrono::steady_clock::now();
controller->SetLEDs(colors);
}
void RGBController_CorsairWireless::DeviceUpdateZoneLEDs(int /*zone*/)
{
controller->SetLEDs(colors);
}
void RGBController_CorsairWireless::DeviceUpdateSingleLED(int /*led*/)
{
controller->SetLEDs(colors);
}
void RGBController_CorsairWireless::DeviceUpdateMode()
{
}
void RGBController_CorsairWireless::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(5000))
{
DeviceUpdateLEDs();
}
}
std::this_thread::sleep_for(1000ms);
}
}
@@ -1,37 +1,41 @@
/*---------------------------------------------------------*\
| RGBController_HyperXEve1800.h |
| |
| RGBController for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXEve1800Controller.h"
class RGBController_HyperXEve1800 : public RGBController
{
public:
RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr);
~RGBController_HyperXEve1800();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXEve1800Controller* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
/*---------------------------------------------------------*\
| RGBController_CorsairWireless.h |
| |
| RGBController for Corsair wireless keyboard |
| |
| Adam Honse (CalcProgrammer1) 08 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "CorsairWirelessController.h"
class RGBController_CorsairWireless : public RGBController
{
public:
RGBController_CorsairWireless(CorsairWirelessController* controller_ptr);
~RGBController_CorsairWireless();
int physical_layout;
int logical_layout;
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
CorsairWirelessController* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -134,14 +134,7 @@ void CrucialController::CrucialRegisterWriteBlock(crucial_register reg, unsigned
bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF));
//Write Crucial block data
if(bus->i2c_smbus_write_block_data(dev, 0x03, sz, data) == -1)
{
//Fall back to individual byte operations if the block operation fails
for(unsigned int block_byte = 0; block_byte < sz; block_byte++)
{
bus->i2c_smbus_write_byte_data(dev, 0x01, data[block_byte]);
}
}
bus->i2c_smbus_write_block_data(dev, 0x03, sz, data);
}
void CrucialController::SendEffectColor
@@ -28,6 +28,12 @@ using namespace std::chrono_literals;
static const unsigned char crucial_addresses[] =
{
/*---------------------------------------------------------*\
| These addresses have been disabled due to conflict with |
| ENE DRAM. Since the detection scheme is the same, ENE |
| RAM will be detected as Crucial. We need to improve the |
| Crucial detection scheme. |
\*---------------------------------------------------------*/
0x39,
0x3A,
0x3B,
@@ -65,19 +71,19 @@ bool TestForCrucialController(i2c_smbus_interface* bus, unsigned char address)
{
bool pass = false;
int res = bus->i2c_smbus_read_byte(address);
int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE);
if(res >= 0)
if (res >= 0)
{
pass = true;
LOG_DEBUG("[%s] Detected an I2C device at address %02X", CRUCIAL_CONTROLLER_NAME, address);
for(int i = 0xA0; i < 0xB0; i++)
for (int i = 0xA0; i < 0xB0; i++)
{
res = bus->i2c_smbus_read_byte_data(address, i);
if(res != (i - 0xA0))
if (res != (i - 0xA0))
{
LOG_VERBOSE("[%s] Detection failed testing register %02X. Expected %02X, got %02X.", CRUCIAL_CONTROLLER_NAME, i, (i - 0xA0), res);
@@ -143,7 +149,7 @@ DetectedControllers DetectCrucialControllers(std::vector<i2c_smbus_interface*> &
{
for(unsigned int slot = 0; slot < 4; slot++)
{
int res = buses[bus]->i2c_smbus_read_byte(0x27);
int res = buses[bus]->i2c_smbus_write_quick(0x27, I2C_SMBUS_WRITE);
if(res < 0)
{
@@ -157,7 +163,7 @@ DetectedControllers DetectCrucialControllers(std::vector<i2c_smbus_interface*> &
if(address_list_idx < CRUCIAL_ADDRESS_COUNT)
{
res = buses[bus]->i2c_smbus_read_byte(crucial_addresses[address_list_idx]);
res = buses[bus]->i2c_smbus_write_quick(crucial_addresses[address_list_idx], I2C_SMBUS_WRITE);
}
else
{
@@ -116,7 +116,7 @@ void RGBController_DRGB::SetupZones()
led new_led;
new_led.name = zones[channel_idx].name + ", LED " + std::to_string(led_ch_idx);
leds.push_back(new_led);
leds_channel.push_back((unsigned int)channel_idx);
leds_channel.push_back(channel_idx);
}
}
@@ -220,7 +220,7 @@ void RGBController_Debug::SetupZones()
/*-------------------------------------------------*\
| Clear any existing color/LED configuration |
\*-------------------------------------------------*/
led_display_names.clear();
led_alt_names.clear();
leds.clear();
colors.clear();
@@ -409,7 +409,7 @@ void RGBController_Debug::SetupZones()
leds.push_back(single_led);
led_display_names.push_back("");
led_alt_names.push_back("");
nlohmann::json configuration_json;
JsonUtils::JsonParse(configuration, configuration_json);
@@ -461,7 +461,7 @@ void RGBController_Debug::SetupZones()
leds.push_back(linear_led);
led_display_names.push_back("");
led_alt_names.push_back("");
}
zone_idx++;
@@ -505,7 +505,7 @@ void RGBController_Debug::SetupZones()
if(zones[zone_idx].flags & ZONE_FLAG_MANUALLY_CONFIGURED_DEVICE_SPECIFIC)
{
if(configuration_json.contains("zones") && (zone_idx < configuration_json["zones"].size()))
if(configuration_json.contains("zones") && (zone_idx < (int)configuration_json["zones"].size()))
{
if(configuration_json["zones"][zone_idx].contains("configuration"))
{
@@ -604,7 +604,7 @@ void RGBController_Debug::SetupZones()
leds.push_back(keyboard_led);
led_display_names.push_back(new_kb.GetKeyAltNameAt(led_idx));
led_alt_names.push_back(new_kb.GetKeyAltNameAt(led_idx));
}
if(first_run)
@@ -663,7 +663,7 @@ void RGBController_Debug::SetupZones()
leds.push_back(underglow_led);
led_display_names.push_back("");
led_alt_names.push_back("");
}
zone_idx++;
@@ -719,7 +719,7 @@ void RGBController_Debug::SetupZones()
leds.push_back(resizable_led);
led_display_names.push_back("");
led_alt_names.push_back("");
}
zone_idx++;
@@ -767,7 +767,7 @@ void RGBController_Debug::DeviceUpdateDeviceSpecificConfiguration()
}
void RGBController_Debug::DeviceUpdateDeviceSpecificZoneConfiguration(int /*zone*/)
void RGBController_Debug::DeviceUpdateDeviceSpecificZoneConfiguration(int zone)
{
SetupZones();
}
@@ -21,14 +21,14 @@
DetectedControllers DetectDygmaRaiseControllers()
{
DetectedControllers detected_controllers;
std::vector<std::string> ports = find_usb_serial_port(DYGMA_RAISE_VID, DYGMA_RAISE_PID);
std::vector<std::string *> ports = find_usb_serial_port(DYGMA_RAISE_VID, DYGMA_RAISE_PID);
for(std::size_t i = 0; i < ports.size(); i++)
{
if(ports[i] != "")
if(*ports[i] != "")
{
DygmaRaiseController* controller = new DygmaRaiseController();
controller->Initialize((char *)ports[i].c_str());
controller->Initialize((char *)ports[i]->c_str());
RGBController_DygmaRaise* rgb_controller = new RGBController_DygmaRaise(controller);
@@ -160,7 +160,7 @@ DetectedControllers DetectENESMBusDRAMControllers(std::vector<i2c_smbus_interfac
for(unsigned int slot = 0; slot < 8; slot++)
{
int res = buses[bus]->i2c_smbus_read_byte(0x77);
int res = buses[bus]->i2c_smbus_write_quick(0x77, I2C_SMBUS_WRITE);
if(res < 0)
{
@@ -176,7 +176,7 @@ DetectedControllers DetectENESMBusDRAMControllers(std::vector<i2c_smbus_interfac
{
LOG_DEBUG("[ENE SMBus DRAM] Testing address %02X to see if there is a device there", ene_ram_addresses[address_list_idx]);
res = buses[bus]->i2c_smbus_read_byte(ene_ram_addresses[address_list_idx]);
res = buses[bus]->i2c_smbus_write_quick(ene_ram_addresses[address_list_idx], I2C_SMBUS_WRITE);
}
else
{
@@ -411,11 +411,8 @@ REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White OC",
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_WHITE_2, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG MATRIX PLATINUM GeForce RTX 4090", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_MATRIX_PLATINUM_RTX_4090_24G, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5060_O8G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5060 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5060TI_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070_O12G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming BTF White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING_BTF_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_5070TI_O16G_GAMING_OC, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5080_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5090_O32G_GAMING, 0x67);
@@ -423,9 +420,7 @@ REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming",
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_2, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC BTF", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_BTF, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_WHITE, 0x67);
REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL LC GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_LC_RTX_5090_O32G_GAMING, 0x67);
@@ -61,12 +61,5 @@ void ENESMBusInterface_i2c_smbus::ENERegisterWriteBlock(ene_dev_id dev, ene_regi
bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF));
//Write ENE block data
if(bus->i2c_smbus_write_block_data(dev, 0x03, sz, data) == -1)
{
//Fall back to individual byte operations if the block operation fails
for(unsigned int block_byte = 0; block_byte < sz; block_byte++)
{
bus->i2c_smbus_write_byte_data(dev, 0x01, data[block_byte]);
}
}
bus->i2c_smbus_write_block_data(dev, 0x03, sz, data);
}
@@ -1,49 +0,0 @@
/*---------------------------------------------------------*\
| EVGAKeyboardControllerDetect.cpp |
| |
| Detector for EVGA keyboard devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "RGBController_EVGAKeyboard.h"
/*---------------------------------------------------------*\
| EVGA USB vendor ID |
\*---------------------------------------------------------*/
#define EVGA_USB_VID 0x3842
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define Z15_ISO_PID 0x260E
#define Z15_ANSI_PID 0x2608
#define Z20_ANSI_PID 0x260A
#define Z20_UK_PID 0x2610
DetectedControllers DetectEVGAKeyboardControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
EVGAKeyboardController* controller = new EVGAKeyboardController(dev, info->path, info->product_id, name);
RGBController_EVGAKeyboard* rgb_controller = new RGBController_EVGAKeyboard(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ISO_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ANSI_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_ANSI_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_UK_PID, 1, 0x08, 0x4B);
@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| EVGAMouseControllerDetect.cpp |
| EVGAUSBControllerDetect.cpp |
| |
| Detector for EVGA mouse devices |
| Detector for EVGA USB devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -9,18 +9,45 @@
#include <hidapi.h>
#include "DetectionManager.h"
#include "RGBController_EVGAKeyboard.h"
#include "RGBController_EVGAMouse.h"
/*---------------------------------------------------------*\
| EVGA USB vendor ID |
\*---------------------------------------------------------*/
#define EVGA_USB_VID 0x3842
#define EVGA_USB_VID 0x3842
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define Z15_ISO_PID 0x260E
#define Z15_ANSI_PID 0x2608
#define Z20_ANSI_PID 0x260A
#define Z20_UK_PID 0x2610
/*---------------------------------------------------------*\
| Mouse product IDs |
\*---------------------------------------------------------*/
#define X20_WIRED_PID 0x2420
#define X20_WIRELESS_ADAPTER_PID 0x2402
#define X20_WIRED_PID 0x2420
#define X20_WIRELESS_ADAPTER_PID 0x2402
DetectedControllers DetectEVGAKeyboardControllers(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
EVGAKeyboardController* controller = new EVGAKeyboardController(dev, info->path, info->product_id, name);
RGBController_EVGAKeyboard* rgb_controller = new RGBController_EVGAKeyboard(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
DetectedControllers DetectEVGAMouse(hid_device_info* info, const std::string &name, int connection_type)
{
@@ -50,5 +77,10 @@ DetectedControllers DetectWirelessEVGAMouse(hid_device_info* info, const std::st
return(DetectEVGAMouse(info, name, EVGA_PERIPHERAL_CONNECTION_TYPE_WIRELESS));
}
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ISO_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA Z15 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z15_ANSI_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_ANSI_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA Z20 Keyboard", DetectEVGAKeyboardControllers, EVGA_USB_VID, Z20_UK_PID, 1, 0x08, 0x4B);
REGISTER_HID_DETECTOR_IPU("EVGA X20 Gaming Mouse", DetectWiredEVGAMouse, EVGA_USB_VID, X20_WIRED_PID, 2, 0xFFFF, 0);
REGISTER_HID_DETECTOR_IPU("EVGA X20 USB Receiver", DetectWirelessEVGAMouse, EVGA_USB_VID, X20_WIRELESS_ADAPTER_PID, 2, 0xFFFF, 0);
@@ -1,81 +0,0 @@
/*---------------------------------------------------------*\
| EVisionKeyboardControllerDetect.cpp |
| |
| Detector for EVision/Huafenda keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "EVisionKeyboardController.h"
#include "RGBController_EVisionKeyboard.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
/*---------------------------------------------------------*\
| EVision vendor ID |
| NOTE: EVision (and Huafenda) use rebranded Sonix MCUs |
| Some EVision/Huafenda keyboards use the Sonix VID while |
| others use EVision's VID |
\*---------------------------------------------------------*/
#define SONIX_VID 0x0C45
#define EVISION_VID 0x320F
/*---------------------------------------------------------*\
| EVision Usage Page |
\*---------------------------------------------------------*/
#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define EVISION_SONIX_5004_PID 0x5004
#define EVISION_SONIX_5104_PID 0x5104
#define EVISION_SONIX_5204_PID 0x5204
#define EVISION_SONIX_652F_PID 0x652F
#define EVISION_SONIX_7672_PID 0x7672
#define EVISION_SONIX_7698_PID 0x7698
#define EVISION_SONIX_8520_PID 0x8520
#define EVISION_5000_PID 0x5000
#define EVISION_502A_PID 0x502A
#define EVISION_505B_PID 0x505B
#define EVISION_5064_PID 0x5064
#define EVISION_5078_PID 0x5078
#define EVISION_5084_PID 0x5084
DetectedControllers DetectEVisionKeyboards(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
EVisionKeyboardController* controller = new EVisionKeyboardController(dev, info->path, name);
RGBController_EVisionKeyboard* rgb_controller = new RGBController_EVisionKeyboard(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
/*---------------------------------------------------------*\
| Keyboards |
\*---------------------------------------------------------*/
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5004", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_5004_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5104", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_5104_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5204", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_5204_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:652F", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_652F_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7672", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_7672_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7698", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_7698_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:8520", DetectEVisionKeyboards, SONIX_VID, EVISION_SONIX_8520_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5000", DetectEVisionKeyboards, EVISION_VID, EVISION_5000_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:502A", DetectEVisionKeyboards, EVISION_VID, EVISION_502A_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:505B", DetectEVisionKeyboards, EVISION_VID, EVISION_505B_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5078", DetectEVisionKeyboards, EVISION_VID, EVISION_5078_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5064", DetectEVisionKeyboards, EVISION_VID, EVISION_5064_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5084", DetectEVisionKeyboards, EVISION_VID, EVISION_5084_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
@@ -0,0 +1,129 @@
/*---------------------------------------------------------*\
| EVisionKeyboardControllerDetect.cpp |
| |
| Detector for EVision keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "EVisionKeyboardController.h"
#include "EVisionV2KeyboardController.h"
#include "RGBController_EVisionKeyboard.h"
#include "RGBController_EVisionV2Keyboard.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define EVISION_KEYBOARD_VID 0x0C45
#define EVISION_KEYBOARD2_VID 0x320F
#define EVISION_KEYBOARD3_VID 0x3299
#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C
#define ENDORFY_OMNIS_PID 0x0012
#define DEXP_BLAZE_PID 0x5084
#define GLORIOUS_GMMK_TKL_PID 0x5064
#define REDRAGON_K550_PID 0x5204
#define MARS_GAMING_MKMINI_PID 0x5078
#define SKILLKORP_K5_PID 0x505B
#define REDRAGON_K552_PID 0x5104
#define REDRAGON_K552_V2_PID 0x5000
#define REDRAGON_K556_PID 0x5004
#define TECWARE_PHANTOM_ELITE_PID 0x652F
#define WARRIOR_KANE_TC235 0x8520
#define WOMIER_K87_PID 0x502A
#define WOMIER_K66_PID 0x7698
#define BYGG_CSB_ICL01_PID 0x5041
#define GAMEPOWER_OGRE_RGB_PID 0x7672
DetectedControllers DetectEVisionKeyboards(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
EVisionKeyboardController* controller = new EVisionKeyboardController(dev, info->path, name);
RGBController_EVisionKeyboard* rgb_controller = new RGBController_EVisionKeyboard(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
DetectedControllers DetectEVisionV2Keyboards(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EVision2Settings");
hid_device* dev = hid_open_path(info->path);
if(dev)
{
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, EVISION_V2_KEYBOARD_LAYOUT, name);
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
detected_controllers.push_back(rgb_controller);
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
{
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_LOGO);
detected_controllers.push_back(rgb_controller);
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_EDGE);
detected_controllers.push_back(rgb_controller);
}
}
return(detected_controllers);
}
DetectedControllers DetectEndorfyKeyboards(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EndorfySettings");
hid_device* dev = hid_open_path(info->path);
if(dev)
{
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, ENDORFY_KEYBOARD_LAYOUT, name);
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
detected_controllers.push_back(rgb_controller);
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
{
rgb_controller = new RGBController_EVisionV2Keyboard(controller, ENDORFY_KEYBOARD_PART_EDGE);
detected_controllers.push_back(rgb_controller);
}
}
return(detected_controllers);
}
/*---------------------------------------------------------------------------------------------------------------------------------------------*\
| Keyboards |
\*---------------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5078", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, MARS_GAMING_MKMINI_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5204", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K550_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5104", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K552_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5000", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, REDRAGON_K552_V2_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5004", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K556_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:652F", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, TECWARE_PHANTOM_ELITE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:8520", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WARRIOR_KANE_TC235, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:502A", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, WOMIER_K87_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7698", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WOMIER_K66_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5064", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, GLORIOUS_GMMK_TKL_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5084", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, DEXP_BLAZE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:505B", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, SKILLKORP_K5_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("Endorfy Omnis", DetectEndorfyKeyboards, EVISION_KEYBOARD3_VID, ENDORFY_OMNIS_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("CSB/ICL01 Keyboard", DetectEVisionV2Keyboards, EVISION_KEYBOARD2_VID, BYGG_CSB_ICL01_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("Gamepower Ogre RGB 0C45:7672", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, GAMEPOWER_OGRE_RGB_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
@@ -1,90 +0,0 @@
/*---------------------------------------------------------*\
| EVisionKeyboardV2ControllerDetect.cpp |
| |
| Detector for EVision V2 keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "EVisionV2KeyboardController.h"
#include "RGBController_EVisionV2Keyboard.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
/*---------------------------------------------------------*\
| EVision vendor ID |
\*---------------------------------------------------------*/
#define EVISION_VID 0x320F
#define SPCGEAR_VID 0x3299
/*---------------------------------------------------------*\
| EVision Usage Page |
\*---------------------------------------------------------*/
#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C
/*---------------------------------------------------------*\
| Keyboard product IDs |
\*---------------------------------------------------------*/
#define ENDORFY_OMNIS_PID 0x0012
#define BYGG_CSB_ICL01_PID 0x5041
DetectedControllers DetectEVisionV2Keyboards(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EVision2Settings");
hid_device* dev = hid_open_path(info->path);
if(dev)
{
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, EVISION_V2_KEYBOARD_LAYOUT, name);
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
detected_controllers.push_back(rgb_controller);
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
{
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_LOGO);
detected_controllers.push_back(rgb_controller);
rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_EDGE);
detected_controllers.push_back(rgb_controller);
}
}
return(detected_controllers);
}
DetectedControllers DetectEndorfyKeyboards(hid_device_info* info, const std::string& name)
{
DetectedControllers detected_controllers;
json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EndorfySettings");
hid_device* dev = hid_open_path(info->path);
if(dev)
{
EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, ENDORFY_KEYBOARD_LAYOUT, name);
RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD);
detected_controllers.push_back(rgb_controller);
if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true)
{
rgb_controller = new RGBController_EVisionV2Keyboard(controller, ENDORFY_KEYBOARD_PART_EDGE);
detected_controllers.push_back(rgb_controller);
}
}
return(detected_controllers);
}
/*---------------------------------------------------------*\
| Keyboards |
\*---------------------------------------------------------*/
REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5041", DetectEVisionV2Keyboards, EVISION_VID, BYGG_CSB_ICL01_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
REGISTER_HID_DETECTOR_IP("Endorfy Omnis", DetectEndorfyKeyboards, SPCGEAR_VID, ENDORFY_OMNIS_PID, 1, EVISION_KEYBOARD_USAGE_PAGE);
@@ -1,205 +0,0 @@
/*---------------------------------------------------------*\
| EdifierHaloController.cpp |
| |
| Driver for Edifier Halo series USB/HID devices |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "LogManager.h"
#include "EdifierHaloController.h"
#include "StringUtils.h"
EdifierHaloController::EdifierHaloController(hid_device* dev_handle, const char* path)
{
dev = dev_handle;
location = path;
wchar_t name_string[256];
int result;
result = hid_get_manufacturer_string(dev, name_string, 256);
if(result == 0)
{
device_name = StringUtils::wstring_to_string(name_string);
}
else
{
device_name = "Edifier";
LOG_WARNING("[EdifierHaloController] Failed to read manufacturer string for %s", path);
}
result = hid_get_product_string(dev, name_string, 256);
if(result == 0)
{
device_name.append(" ").append(StringUtils::wstring_to_string(name_string));
}
else
{
device_name.append(" Halo PixelBar");
LOG_WARNING("[EdifierHaloController] Failed to read product string for %s", path);
}
wchar_t serial_string[128];
result = hid_get_serial_number_string(dev, serial_string, 128);
if(result == 0)
{
serial = StringUtils::wstring_to_string(serial_string);
}
else
{
serial = "";
LOG_DEBUG("[EdifierHaloController] No serial number available for %s", path);
}
}
EdifierHaloController::~EdifierHaloController()
{
if(dev)
{
hid_close(dev);
}
}
std::string EdifierHaloController::GetDeviceName() const
{
return(device_name);
}
std::string EdifierHaloController::GetSerial() const
{
return(serial);
}
std::string EdifierHaloController::GetLocation() const
{
return("HID: " + location);
}
void EdifierHaloController::SetAmbientLightPower(bool enabled)
{
unsigned char mode = enabled ? 0x01 : 0x00;
unsigned char payload[] =
{
0x00,
0x00,
0x00,
0x00,
mode,
0xFF,
0xFF
};
SendEdifierPacket(0x6b, payload, sizeof(payload));
}
void EdifierHaloController::SetAmbientLight(unsigned char effect, unsigned char r, unsigned char g, unsigned char b, unsigned char brightness, unsigned char speed)
{
unsigned char raw_brightness = 0x3c;
if (brightness == 1) raw_brightness = 0x14;
else if (brightness == 2) raw_brightness = 0x28;
else if (brightness == 3) raw_brightness = 0x3c;
if (speed < 1) speed = 1;
if (speed > 10) speed = 10;
unsigned char payload[] =
{
0x13,
effect,
r,
g,
b,
raw_brightness,
speed
};
SendEdifierPacket(0x6b, payload, sizeof(payload));
}
void EdifierHaloController::SetPixelScreenColor(unsigned char r, unsigned char g, unsigned char b)
{
unsigned char payload[] =
{
0x03,
r,
g,
b
};
SendEdifierPacket(0xef, payload, sizeof(payload));
}
void EdifierHaloController::SetScreenUIModel(unsigned char model_id, unsigned char r, unsigned char g, unsigned char b)
{
unsigned char payload[] =
{
0x02,
r,
g,
b,
0x00,
0x01,
model_id,
0xff,
0xff
};
SendEdifierPacket(0xef, payload, sizeof(payload));
}
void EdifierHaloController::SetScreenScene(unsigned char category, unsigned char index, unsigned char r, unsigned char g, unsigned char b)
{
unsigned char payload[] =
{
0x01, // group
r,
g,
b,
0x00,
0x01,
category,
index,
0xff // option
};
SendEdifierPacket(0xef, payload, sizeof(payload));
}
void EdifierHaloController::SendEdifierPacket(unsigned char commandIndex, const unsigned char* payload, unsigned int payload_size)
{
if(!dev)
{
return;
}
unsigned char packet[64];
memset(packet, 0x00, sizeof(packet));
packet[0] = 0x2e;
packet[1] = 0xaa;
packet[2] = 0xec;
packet[3] = commandIndex;
packet[4] = (unsigned char)((payload_size >> 8) & 0xff);
packet[5] = (unsigned char)(payload_size & 0xff);
if(payload_size > 0 && payload != nullptr)
{
memcpy(&packet[6], payload, payload_size);
}
// Calculate checksum
unsigned int sum = 0;
for(unsigned int i = 1; i < 6 + payload_size; i++)
{
sum += packet[i];
}
packet[6 + payload_size] = (unsigned char)(sum & 0xff);
std::lock_guard<std::mutex> guard(device_mutex);
int bytes_written = hid_write(dev, packet, sizeof(packet));
if(bytes_written != sizeof(packet))
{
LOG_ERROR("[EdifierHaloController] Failed to write HID packet (%d/%d bytes): %ls",
bytes_written, (int)sizeof(packet), hid_error(dev));
}
}
@@ -1,64 +0,0 @@
/*---------------------------------------------------------*\
| EdifierHaloController.h |
| |
| Driver for Edifier Halo series USB/HID devices |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <mutex>
#include <string>
#include <hidapi.h>
enum
{
EDIFIER_HALO_AMBIENT_MODE_BREATHING = 1, // Breathing
EDIFIER_HALO_AMBIENT_MODE_TIDE = 2, // Rainbow
EDIFIER_HALO_AMBIENT_MODE_STATIC = 3, // Static
EDIFIER_HALO_AMBIENT_MODE_RIPPLE = 4, // Glittering and colorful
EDIFIER_HALO_AMBIENT_MODE_FLOW = 5, // Light-flow
EDIFIER_HALO_AMBIENT_MODE_DYNAMIC = 6 // Dynamic Shadows
};
enum
{
EDIFIER_HALO_AMBIENT_SPEED_SLOWEST = 1,
EDIFIER_HALO_AMBIENT_SPEED_FASTEST = 10
};
enum
{
EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST = 1,
EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST = 3
};
class EdifierHaloController
{
public:
EdifierHaloController(hid_device* dev_handle, const char* path);
~EdifierHaloController();
std::string GetDeviceName() const;
std::string GetSerial() const;
std::string GetLocation() const;
void SetAmbientLight(unsigned char effect, unsigned char r, unsigned char g, unsigned char b, unsigned char brightness, unsigned char speed);
void SetAmbientLightPower(bool enabled);
void SetPixelScreenColor(unsigned char r, unsigned char g, unsigned char b);
void SetScreenUIModel(unsigned char model_id, unsigned char r, unsigned char g, unsigned char b);
void SetScreenScene(unsigned char category, unsigned char index, unsigned char r, unsigned char g, unsigned char b);
private:
hid_device* dev;
std::string device_name;
std::string serial;
std::string location;
std::mutex device_mutex;
void SendEdifierPacket(unsigned char commandIndex, const unsigned char* payload, unsigned int payload_size);
};
@@ -1,56 +0,0 @@
/*---------------------------------------------------------*\
| EdifierHaloControllerDetect.cpp |
| |
| Detector for Edifier Halo PixelBar USB/HID devices |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include <memory>
#include "DetectionManager.h"
#include "LogManager.h"
#include "RGBController_EdifierHaloPixelbarAmbient.h"
#include "RGBController_EdifierHaloPixelbarScreen.h"
#include "EdifierHaloController.h"
/*---------------------------------------------------------*\
| Edifier HID vendor and product IDs |
\*---------------------------------------------------------*/
#define EDIFIER_VID 0x2D99
#define EDIFIER_PIXELBAR_PID 0xA106
#define EDIFIER_PIXELBAR_INTERFACE 4
#define EDIFIER_PIXELBAR_USAGE_PAGE 0xFF14
#define EDIFIER_PIXELBAR_USAGE 0x01
DetectedControllers DetectEdifierHaloControllers(hid_device_info* info, const std::string&)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
EdifierHaloController* controller = new EdifierHaloController(dev, info->path);
RGBController_EdifierHaloPixelbarAmbient* ambient_controller = new RGBController_EdifierHaloPixelbarAmbient(controller);
RGBController_EdifierHaloPixelbarScreen* screen_controller = new RGBController_EdifierHaloPixelbarScreen(controller);
detected_controllers.push_back(ambient_controller);
detected_controllers.push_back(screen_controller);
LOG_INFO("[EdifierHaloPixelbarDetect] Detected Edifier Halo PixelBar at %s (Instantiated Ambient & Screen controllers)", info->path);
}
else
{
LOG_WARNING("[EdifierHaloPixelbarDetect] Failed to open Edifier Halo PixelBar at %s", info->path);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Edifier Halo Pixelbar", DetectEdifierHaloControllers, EDIFIER_VID, EDIFIER_PIXELBAR_PID, EDIFIER_PIXELBAR_INTERFACE, EDIFIER_PIXELBAR_USAGE_PAGE, EDIFIER_PIXELBAR_USAGE);
@@ -1,182 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_EdifierHaloPixelbarAmbient.cpp |
| |
| RGBController for Edifier Halo PixelBar Ambient Light |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_EdifierHaloPixelbarAmbient.h"
/**------------------------------------------------------------------*\
@name Edifier Halo Pixelbar
@category Speaker
@type USB
@save :robot:
@direct :x:
@effects :white_check_mark:
@detectors DetectEdifierHaloControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_EdifierHaloPixelbarAmbient::RGBController_EdifierHaloPixelbarAmbient(EdifierHaloController* controller_ptr)
{
controller = controller_ptr;
first_leds_update_ignored = false;
first_mode_update_ignored = false;
name = "Edifier Halo Pixelbar - Light Effects";
vendor = "Edifier";
type = DEVICE_TYPE_SPEAKER;
description = "Edifier Halo PixelBar Light Effects";
serial = controller->GetSerial();
location = controller->GetLocation();
// Setup modes
mode breathing_mode;
breathing_mode.name = "Breathing";
breathing_mode.value = EDIFIER_HALO_AMBIENT_MODE_BREATHING;
breathing_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
breathing_mode.color_mode = MODE_COLORS_PER_LED;
breathing_mode.speed_min = EDIFIER_HALO_AMBIENT_SPEED_SLOWEST;
breathing_mode.speed_max = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
breathing_mode.speed = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
breathing_mode.brightness_min = EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST;
breathing_mode.brightness_max = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
breathing_mode.brightness = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
modes.push_back(breathing_mode);
mode tide_mode;
tide_mode.name = "Rainbow";
tide_mode.value = EDIFIER_HALO_AMBIENT_MODE_TIDE;
tide_mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
tide_mode.color_mode = MODE_COLORS_NONE;
tide_mode.speed_min = EDIFIER_HALO_AMBIENT_SPEED_SLOWEST;
tide_mode.speed_max = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
tide_mode.speed = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
tide_mode.brightness_min = EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST;
tide_mode.brightness_max = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
tide_mode.brightness = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
modes.push_back(tide_mode);
mode static_mode;
static_mode.name = "Static";
static_mode.value = EDIFIER_HALO_AMBIENT_MODE_STATIC;
static_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
static_mode.color_mode = MODE_COLORS_MODE_SPECIFIC;
static_mode.brightness_min = EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST;
static_mode.brightness_max = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
static_mode.brightness = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
modes.push_back(static_mode);
mode ripple_mode;
ripple_mode.name = "Glittering and colorful";
ripple_mode.value = EDIFIER_HALO_AMBIENT_MODE_RIPPLE;
ripple_mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
ripple_mode.color_mode = MODE_COLORS_NONE;
ripple_mode.speed_min = EDIFIER_HALO_AMBIENT_SPEED_SLOWEST;
ripple_mode.speed_max = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
ripple_mode.speed = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
ripple_mode.brightness_min = EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST;
ripple_mode.brightness_max = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
ripple_mode.brightness = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
modes.push_back(ripple_mode);
mode flow_mode;
flow_mode.name = "Light-flow";
flow_mode.value = EDIFIER_HALO_AMBIENT_MODE_FLOW;
flow_mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
flow_mode.color_mode = MODE_COLORS_NONE;
flow_mode.speed_min = EDIFIER_HALO_AMBIENT_SPEED_SLOWEST;
flow_mode.speed_max = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
flow_mode.speed = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
flow_mode.brightness_min = EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST;
flow_mode.brightness_max = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
flow_mode.brightness = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
modes.push_back(flow_mode);
mode dynamic_mode;
dynamic_mode.name = "Dynamic Shadows";
dynamic_mode.value = EDIFIER_HALO_AMBIENT_MODE_DYNAMIC;
dynamic_mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
dynamic_mode.color_mode = MODE_COLORS_NONE;
dynamic_mode.speed_min = EDIFIER_HALO_AMBIENT_SPEED_SLOWEST;
dynamic_mode.speed_max = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
dynamic_mode.speed = EDIFIER_HALO_AMBIENT_SPEED_FASTEST;
dynamic_mode.brightness_min = EDIFIER_HALO_AMBIENT_BRIGHTNESS_LOWEST;
dynamic_mode.brightness_max = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
dynamic_mode.brightness = EDIFIER_HALO_AMBIENT_BRIGHTNESS_HIGHEST;
modes.push_back(dynamic_mode);
// Default to Static mode
active_mode = 2;
SetupZones();
}
RGBController_EdifierHaloPixelbarAmbient::~RGBController_EdifierHaloPixelbarAmbient()
{
}
void RGBController_EdifierHaloPixelbarAmbient::SetupZones()
{
zone ambient_zone;
ambient_zone.name = "Light Effects";
ambient_zone.type = ZONE_TYPE_SINGLE;
ambient_zone.leds_min = 1;
ambient_zone.leds_max = 1;
ambient_zone.leds_count = 1;
zones.push_back(ambient_zone);
led ambient_led;
ambient_led.name = "Light Effects";
leds.push_back(ambient_led);
SetupColors();
}
void RGBController_EdifierHaloPixelbarAmbient::DeviceUpdateLEDs()
{
if(!first_leds_update_ignored)
{
first_leds_update_ignored = true;
return;
}
int active_idx = GetActiveMode();
RGBColor color = colors[0];
unsigned char r = RGBGetRValue(color);
unsigned char g = RGBGetGValue(color);
unsigned char b = RGBGetBValue(color);
unsigned char effect = modes[active_idx].value;
unsigned char brightness = modes[active_idx].brightness;
unsigned char speed = modes[active_idx].speed;
controller->SetAmbientLightPower(true);
controller->SetAmbientLight(effect, r, g, b, brightness, speed);
}
void RGBController_EdifierHaloPixelbarAmbient::DeviceUpdateZoneLEDs(int)
{
DeviceUpdateLEDs();
}
void RGBController_EdifierHaloPixelbarAmbient::DeviceUpdateSingleLED(int)
{
DeviceUpdateLEDs();
}
void RGBController_EdifierHaloPixelbarAmbient::DeviceUpdateMode()
{
if(!first_mode_update_ignored)
{
first_mode_update_ignored = true;
return;
}
DeviceUpdateLEDs();
}
@@ -1,35 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_EdifierHaloPixelbarAmbient.h |
| |
| RGBController for Edifier Halo PixelBar Ambient Light |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <memory>
#include "RGBController.h"
#include "EdifierHaloController.h"
class RGBController_EdifierHaloPixelbarAmbient : public RGBController
{
public:
RGBController_EdifierHaloPixelbarAmbient(EdifierHaloController* controller_ptr);
~RGBController_EdifierHaloPixelbarAmbient();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
EdifierHaloController* controller;
bool first_leds_update_ignored;
bool first_mode_update_ignored;
};
@@ -1,173 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_EdifierHaloPixelbarScreen.cpp |
| |
| RGBController for Edifier Halo PixelBar Screen Color |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_EdifierHaloPixelbarScreen.h"
/**------------------------------------------------------------------*\
@name Edifier Halo Pixelbar - Screen
@category Speaker
@type USB
@save :robot:
@direct :x:
@effects :white_check_mark:
@detectors DetectEdifierHaloControllers
@comment
\*-------------------------------------------------------------------*/
struct CategoryDefinition
{
std::string name;
unsigned char category_id;
};
RGBController_EdifierHaloPixelbarScreen::RGBController_EdifierHaloPixelbarScreen(EdifierHaloController* controller_ptr)
{
controller = controller_ptr;
first_leds_update_ignored = false;
first_mode_update_ignored = false;
name = "Edifier Halo Pixelbar - Pixel Display";
vendor = "Edifier";
type = DEVICE_TYPE_SPEAKER;
description = "Edifier Halo PixelBar Pixel Display Color";
serial = controller->GetSerial();
location = controller->GetLocation();
// Clock 1 to Clock 11 (11 built-in clock styles)
for(unsigned char i = 0; i < 11; ++i)
{
mode m;
m.name = "Clock " + std::to_string(i + 1);
m.value = (0 << 8) | i;
m.flags = MODE_FLAG_HAS_PER_LED_COLOR;
m.color_mode = MODE_COLORS_PER_LED;
modes.push_back(m);
}
// Default built-in layouts for other categories
std::vector<CategoryDefinition> categories =
{
{ "Gaming", 1 },
{ "Work", 2 },
{ "Study", 3 },
{ "Cats", 4 },
{ "Dogs", 5 },
{ "Buzzwords", 6 },
{ "Cyberpunk", 7 },
{ "Spectrum", 8 }
};
for(const CategoryDefinition& cat : categories)
{
mode m;
m.name = cat.name;
m.value = (cat.category_id << 8) | 0;
m.flags = MODE_FLAG_HAS_PER_LED_COLOR;
m.color_mode = MODE_COLORS_PER_LED;
modes.push_back(m);
}
// Default to Clock 1 mode
active_mode = 0;
SetupZones();
}
RGBController_EdifierHaloPixelbarScreen::~RGBController_EdifierHaloPixelbarScreen()
{
delete controller;
}
void RGBController_EdifierHaloPixelbarScreen::SetupZones()
{
zone screen_zone;
screen_zone.name = "Screen Color";
screen_zone.type = ZONE_TYPE_SINGLE;
screen_zone.leds_min = 1;
screen_zone.leds_max = 1;
screen_zone.leds_count = 1;
zones.push_back(screen_zone);
led screen_led;
screen_led.name = "Screen Text";
leds.push_back(screen_led);
SetupColors();
}
void RGBController_EdifierHaloPixelbarScreen::DeviceUpdateLEDs()
{
if(!first_leds_update_ignored)
{
first_leds_update_ignored = true;
return;
}
unsigned char r = 255;
unsigned char g = 255;
unsigned char b = 255;
if(!colors.empty())
{
RGBColor color = colors[0];
r = RGBGetRValue(color);
g = RGBGetGValue(color);
b = RGBGetBValue(color);
}
// For all other modes, color updates are sent using SetPixelScreenColor
controller->SetPixelScreenColor(r, g, b);
}
void RGBController_EdifierHaloPixelbarScreen::DeviceUpdateZoneLEDs(int)
{
DeviceUpdateLEDs();
}
void RGBController_EdifierHaloPixelbarScreen::DeviceUpdateSingleLED(int)
{
DeviceUpdateLEDs();
}
void RGBController_EdifierHaloPixelbarScreen::DeviceUpdateMode()
{
if(!first_mode_update_ignored)
{
first_mode_update_ignored = true;
return;
}
int active_idx = GetActiveMode();
unsigned char r = 255;
unsigned char g = 255;
unsigned char b = 255;
if(!colors.empty())
{
RGBColor color = colors[0];
r = RGBGetRValue(color);
g = RGBGetGValue(color);
b = RGBGetBValue(color);
}
unsigned int mode_val = modes[active_idx].value;
unsigned char category = (mode_val >> 8) & 0xFF;
unsigned char index = mode_val & 0xFF;
if(category == 0) // Clock category (11 built-in styles)
{
controller->SetScreenScene(0, index, r, g, b);
}
else // Other categories (Gaming, Working, etc.) use the default built-in layouts
{
controller->SetScreenUIModel(category, r, g, b);
}
}
@@ -1,35 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_EdifierHaloPixelbarScreen.h |
| |
| RGBController for Edifier Halo PixelBar Screen Color |
| |
| Bartholomew Ho <[email protected]> 20 Jul 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <memory>
#include "RGBController.h"
#include "EdifierHaloController.h"
class RGBController_EdifierHaloPixelbarScreen : public RGBController
{
public:
RGBController_EdifierHaloPixelbarScreen(EdifierHaloController* controller_ptr);
~RGBController_EdifierHaloPixelbarScreen();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
EdifierHaloController* controller;
bool first_leds_update_ignored;
bool first_mode_update_ignored;
};
@@ -0,0 +1,133 @@
/*---------------------------------------------------------*\
| EpomakerController.cpp |
| |
| Driver for Epomaker keyboard |
| |
| Alvaro Munoz (alvaromunoz) 05 Jun 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <math.h>
#include "EpomakerController.h"
#include "LogManager.h"
#include "StringUtils.h"
EpomakerController::EpomakerController(hid_device* dev_handle, char *_path)
{
dev = dev_handle;
location = _path;
/*---------------------------------------------------------*\
| Get device name from HID manufacturer and product strings |
\*---------------------------------------------------------*/
wchar_t name_string[HID_MAX_STR];
hid_get_manufacturer_string(dev, name_string, HID_MAX_STR);
device_name = StringUtils::wstring_to_string(name_string);
hid_get_product_string(dev, name_string, HID_MAX_STR);
device_name.append(" ").append(StringUtils::wstring_to_string(name_string));
current_mode = EPOMAKER_MODE_ALWAYS_ON;
current_speed = EPOMAKER_SPEED_DEFAULT;
current_brightness = EPOMAKER_BRIGHTNESS_DEFAULT;
current_dazzle = EPOMAKER_OPTION_DAZZLE_OFF;
current_option = EPOMAKER_OPTION_DEFAULT;
}
EpomakerController::~EpomakerController()
{
hid_close(dev);
}
std::string EpomakerController::GetDeviceName()
{
return(device_name);
}
std::string EpomakerController::GetSerial()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
std::string EpomakerController::GetLocation()
{
return("HID: " + location);
}
void EpomakerController::SetMode(unsigned char mode, unsigned char speed, unsigned char brightness)
{
current_mode = mode;
current_speed = speed;
current_brightness = brightness;
SendUpdate();
}
void EpomakerController::SetColor(unsigned char red, unsigned char green, unsigned char blue)
{
current_red = red;
current_green = green;
current_blue = blue;
SendUpdate();
}
void EpomakerController::SetDazzle(bool is_dazzle)
{
if(is_dazzle)
{
current_dazzle = EPOMAKER_OPTION_DAZZLE_ON;
}
else
{
current_dazzle = EPOMAKER_OPTION_DAZZLE_OFF;
}
}
void EpomakerController::SetOption(unsigned char option)
{
current_option = option;
}
void EpomakerController::SendUpdate()
{
unsigned char buffer[EPOMAKER_PACKET_LENGTH + 1] = { 0x00 };
buffer[EPOMAKER_BYTE_COMMAND] = EPOMAKER_COMMAND_RGB;
buffer[EPOMAKER_BYTE_MODE] = current_mode;
buffer[EPOMAKER_BYTE_SPEED] = current_speed;
buffer[EPOMAKER_BYTE_BRIGHTNESS] = current_brightness;
buffer[EPOMAKER_BYTE_FLAGS] = current_option | current_dazzle;
buffer[EPOMAKER_BYTE_RED] = current_red;
buffer[EPOMAKER_BYTE_GREEN] = current_green;
buffer[EPOMAKER_BYTE_BLUE] = current_blue;
int sum_bits = 0;
for(int i = EPOMAKER_BYTE_COMMAND; i <= EPOMAKER_BYTE_BLUE; i++)
{
sum_bits += buffer[i];
}
int next_pow2 = (int)(pow(2, ceil(log2((double)(sum_bits)))));
int filler = next_pow2 - sum_bits - 1;
buffer[EPOMAKER_BYTE_FILLER] = filler;
int send_buffer_result = hid_send_feature_report(dev, buffer, (sizeof(buffer) / sizeof(buffer[0])));
if(send_buffer_result<0)
{
LOG_ERROR("[EPOMAKER]: Send Buffer Error. HIDAPI Error: %ls", hid_error(dev));
}
}
@@ -13,7 +13,6 @@
#include <string>
#include <hidapi.h>
#include "../RoyuanKeyboardController/RoyuanKeyboardController.h"
#define EPOMAKER_PACKET_LENGTH 0x40
#define EPOMAKER_COMMAND_RGB 0x07
@@ -91,9 +90,36 @@ enum
EPOMAKER_OPTION_PEAK_TURN_CLOCKWISE = 0x10,
};
class EpomakerController : public RoyuanKeyboardController
class EpomakerController
{
public:
EpomakerController(hid_device* dev_handle, char* path);
EpomakerController(hid_device* dev_handle, char *_path);
~EpomakerController();
std::string GetDeviceName();
std::string GetSerial();
std::string GetLocation();
void SetDazzle(bool is_dazzle);
void SetOption(unsigned char option);
void SetMode(unsigned char mode, unsigned char speed, unsigned char brightness);
void SetColor(unsigned char red, unsigned char green, unsigned char blue);
private:
std::string device_name;
std::string location;
hid_device* dev;
unsigned char current_mode;
unsigned char current_speed;
unsigned char current_brightness;
unsigned char current_dazzle;
unsigned char current_option;
unsigned char current_red;
unsigned char current_green;
unsigned char current_blue;
void SendUpdate();
};
@@ -0,0 +1,50 @@
/*---------------------------------------------------------*\
| EpomakerControllerDetect.cpp |
| |
| Detector for Epomaker keyboard |
| |
| Alvaro Munoz (alvaromunoz) 05 Jun 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "EpomakerController.h"
#include "RGBController_EpomakerController.h"
#define EPOMAKER_VID 0x3151
#define EPOMAKER_TH80_Pro_USB_PID 0x4010
#define ATTACKSHARK_K86_USB_PID 0x4015
#define EPOMAKER_TH80_Pro_Dongle_PID 0x4011 /* Attack shark's Dongle is the same. */
#define EPOMAKER_TH80_Pro_BT_PID 0x4013
#define ATTACKSHARK_K86_BT_PID 0x401
DetectedControllers DetectEpomakerControllers(hid_device_info* info, const std::string&)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
EpomakerController* controller = new EpomakerController(dev, info->path);
RGBController_EpomakerController* rgb_controller = new RGBController_EpomakerController(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_I("Epomaker TH80 Pro (USB Cable)", DetectEpomakerControllers, EPOMAKER_VID, EPOMAKER_TH80_Pro_USB_PID, 2);
REGISTER_HID_DETECTOR_I("Epomaker TH80 Pro (USB Dongle)", DetectEpomakerControllers, EPOMAKER_VID, EPOMAKER_TH80_Pro_Dongle_PID, 2);
REGISTER_HID_DETECTOR_I("Attack Shark K86 (USB Cable)", DetectEpomakerControllers, EPOMAKER_VID, ATTACKSHARK_K86_USB_PID, 2);
/*---------------------------------------------------------*\
| Bluetooth Not implemented |
\*---------------------------------------------------------*/
//REGISTER_HID_DETECTOR("Epomaker TH80 Pro (Bluetooth)", DetectEpomakerControllers, EPOMAKER_VID, EPOMAKER_TH80_Pro_BT_PID);
//REGISTER_HID_DETECTOR("Attack Shark K86 (Bluetooth)", DetectEpomakerControllers, EPOMAKER_VID, ATTACKSHARK_K86_BT_PID);
@@ -19,7 +19,7 @@
@save :robot:
@direct :x:
@effects :white_check_mark:
@detectors DetectRoyuanLegacyKeyboardControllers
@detectors DetectEpomakerControllers
@comment
\*-------------------------------------------------------------------*/
@@ -230,41 +230,16 @@ void FnaticStreakController::SetLEDsDirect(std::vector<led> leds, std::vector<RG
void FnaticStreakController::SendRGBToDevice()
{
if(keyboard_type == FNATIC_STREAK_TYPE_65)
{
unsigned char data[64];
memset(data, 0x00, sizeof(data));
unsigned int total_leds = GetLEDCount();
unsigned int data_size = total_leds * 3;
data[0] = 0x0F;
data[1] = 0x15;
data[7] = 0x0F;
data[8] = 0x03;
for(unsigned int i = 9; i < 25; i++)
{
data[i] = 0xFF;
}
data[25] = color_buf[0];
data[26] = color_buf[1];
data[27] = color_buf[2];
hid_write(dev, data, sizeof(data));
}
else
{
unsigned int total_leds = GetLEDCount();
unsigned int data_size = total_leds * 3;
/*-----------------------------------------------------*\
| For direct/software control, use command 0x0f |
| This bypasses the profile and allows immediate update |
| The 0x03 subcommand indicates per-key color data |
\*-----------------------------------------------------*/
unsigned char prefix[] = { 0x0f, 0x03 };
SendRequest(prefix, sizeof(prefix), color_buf, data_size);
}
/*-----------------------------------------------------*\
| For direct/software control, use command 0x0f |
| This bypasses the profile and allows immediate update |
| The 0x03 subcommand indicates per-key color data |
\*-----------------------------------------------------*/
unsigned char prefix[] = { 0x0f, 0x03 };
SendRequest(prefix, sizeof(prefix), color_buf, data_size);
}
void FnaticStreakController::SetPulse(unsigned char color_mode, unsigned char r, unsigned char g, unsigned char b, unsigned char speed)
@@ -51,8 +51,7 @@
enum FnaticStreakType
{
FNATIC_STREAK_TYPE_FULL,
FNATIC_STREAK_TYPE_MINI,
FNATIC_STREAK_TYPE_65
FNATIC_STREAK_TYPE_MINI
};
class FnaticStreakController
@@ -26,7 +26,6 @@
#define FNATIC_STREAK_PID 0x0101
#define FNATIC_MINISTREAK_PID 0x0102
#define FNATIC_STREAK65_PID 0x0105
DetectedControllers DetectFnaticStreakKeyboard(hid_device_info* info, const std::string& name)
{
@@ -43,10 +42,6 @@ DetectedControllers DetectFnaticStreakKeyboard(hid_device_info* info, const std:
{
kb_type = FNATIC_STREAK_TYPE_MINI;
}
else if(info->product_id == FNATIC_STREAK65_PID)
{
kb_type = FNATIC_STREAK_TYPE_65;
}
else
{
kb_type = FNATIC_STREAK_TYPE_FULL;
@@ -63,4 +58,3 @@ DetectedControllers DetectFnaticStreakKeyboard(hid_device_info* info, const std:
REGISTER_HID_DETECTOR_I("Fnatic Streak", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_STREAK_PID, 1);
REGISTER_HID_DETECTOR_I("Fnatic miniStreak", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_MINISTREAK_PID, 1);
REGISTER_HID_DETECTOR_I("Fnatic Streak65", DetectFnaticStreakKeyboard, FNATIC_VID, FNATIC_STREAK65_PID, 1);
@@ -563,7 +563,7 @@ void RGBController_GaiZhongGaiKeyboard::SetupZones()
break;
case GAIZHONGGAI_RGB_HUB_GREEN_PID:
temp = controller->GetChannelLen((uint8_t)zone_idx);//get led_len
temp = controller->GetChannelLen(zone_idx);//get led_len
zones[zone_idx].leds_min = 0;
zones[zone_idx].leds_max = 637;
@@ -600,7 +600,7 @@ void RGBController_GaiZhongGaiKeyboard::SetupZones()
break;
case GAIZHONGGAI_RGB_HUB_BLUE_PID:
temp = controller->GetChannelLen((uint8_t)zone_idx);//get led_len
temp = controller->GetChannelLen(zone_idx);//get led_len
zones[zone_idx].leds_min = 0;
zones[zone_idx].leds_max = 633;
@@ -99,4 +99,3 @@ REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Phoenix", DetectGa
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080TI_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3090_DEV, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Ti Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3090TI_PHANTOM, 0x49);
REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 4080 Phantom GS", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4080_PHANTOM_GS_SUB_DEV, 0x49);
@@ -29,13 +29,10 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
\*-------------------------------------------------*/
case 0x32:
res = bus->i2c_smbus_read_byte_data(address, 0x00);
if(res == 0x27 || res == 0x26)
{
if(res == 0x27 || res == 0x26) {
res = bus->i2c_smbus_read_byte_data(address, 0x01);
if(res == 0x10 || res == 0x20)
{
if (res == 0x10 || res == 0x20)
pass = true;
}
}
break;
@@ -44,7 +41,7 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
\*-------------------------------------------------*/
case 0x23:
res = bus->i2c_smbus_read_byte_data(address, 0x00);
if(res == 0x27 || res == 0x30)
if(res == 0x30)
{
pass = true;
}
@@ -55,10 +52,8 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address)
\*-------------------------------------------------*/
case 0x51:
res = bus->i2c_smbus_read_byte_data(address, 0x00);
if(res == 0x80)
{
if (res == 0x80)
pass = true;
}
break;
}
@@ -1,238 +0,0 @@
/*---------------------------------------------------------*\
| GigabyteCastor3Controller.cpp |
| |
| Driver for Gigabyte Aorus Waterforce X II 360 AIO |
| (Castor3 USB HID controller) |
| |
| RGB ring control only — LCD not implemented |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "GigabyteCastor3Controller.h"
#include "StringUtils.h"
GigabyteCastor3Controller::GigabyteCastor3Controller(hid_device* dev_handle, const char* path)
{
dev = dev_handle;
location = path;
/*---------------------------------------------------------*\
| Query firmware version via de 00 |
| Response: de [version_byte] |
| Observed: de 02 -> version 2 |
\*---------------------------------------------------------*/
unsigned char de_payload[] = { 0xDE, 0x00 };
SendPacket(de_payload, 2);
unsigned char response[CASTOR3_IN_SIZE];
int bytes_read = hid_read_timeout(dev, response, CASTOR3_IN_SIZE, CASTOR3_IN_TIMEOUT_MS);
if(bytes_read > 1)
{
/*-----------------------------------------------------*\
| Strip report ID 0x99 if present on IN packets |
\*-----------------------------------------------------*/
int offset = 0;
if(response[0] == CASTOR3_REPORT_ID)
{
offset = 1;
}
if(response[offset] == 0xDE && bytes_read > offset + 1)
{
firmware_version = std::to_string(response[offset + 1]);
}
}
}
GigabyteCastor3Controller::~GigabyteCastor3Controller()
{
hid_close(dev);
}
std::string GigabyteCastor3Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string GigabyteCastor3Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
std::string GigabyteCastor3Controller::GetFirmwareVersion()
{
return firmware_version;
}
void GigabyteCastor3Controller::SetEffect
(
unsigned char style,
unsigned char speed,
unsigned char brightness,
unsigned char b4,
unsigned char b5,
castor3_color_type color_type,
std::vector<RGBColor> colors
)
{
/*---------------------------------------------------------*\
| Wire protocol for LED effect apply |
| (from castor3.py led_set_effect, confirmed from |
| led_profile.pcapng + .cled.dat cross-reference) |
| |
| Step 1: c9 [Style] [Speed*20] [Bright] [b4] [b5] |
| Step 2: cd [R] [G] [B] (single-color only) |
| -OR- b0..b3 palette registers (palette effects) |
| Step 3: b6 (commit) |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| Step 1: c9 — effect select + parameters |
\*---------------------------------------------------------*/
unsigned char c9_payload[] =
{
0xC9,
style,
(unsigned char)(speed * 20),
brightness,
b4,
b5
};
SendPacket(c9_payload, sizeof(c9_payload));
/*---------------------------------------------------------*\
| Step 2a: cd — primary color for single-color effects |
| Effects: static, pulse, flash, dflash, gradient, off |
\*---------------------------------------------------------*/
if(color_type == CASTOR3_COLORS_SINGLE)
{
unsigned char r = 0xFF, g = 0x66, b = 0x00;
if(colors.size() > 0)
{
r = RGBGetRValue(colors[0]);
g = RGBGetGValue(colors[0]);
b = RGBGetBValue(colors[0]);
}
unsigned char cd_payload[] = { 0xCD, r, g, b };
SendPacket(cd_payload, sizeof(cd_payload));
}
/*---------------------------------------------------------*\
| Step 2b: b0..b3 — palette registers for multi-color |
| Each register carries 2 colors (6 bytes RGB + 1 pad): |
| bN [Style] [R1 G1 B1] [R2 G2 B2] 0x00 |
| b0=colors 1+2, b1=colors 3+4, b2=colors 5+6, b3=7+8 |
| |
| Effects: colorshift(8), tricolor(3), spin(3), switch(2) |
\*---------------------------------------------------------*/
else if(color_type == CASTOR3_COLORS_PALETTE)
{
/*-----------------------------------------------------*\
| Build palette: pad to 8 colors by repeating last |
\*-----------------------------------------------------*/
RGBColor palette[8];
for(int i = 0; i < 8; i++)
{
if(i < (int)colors.size())
{
palette[i] = colors[i];
}
else if(colors.size() > 0)
{
palette[i] = colors[colors.size() - 1];
}
else
{
palette[i] = ToRGBColor(0xFF, 0x00, 0x00);
}
}
unsigned char regs[] = { 0xB0, 0xB1, 0xB2, 0xB3 };
for(int i = 0; i < 4; i++)
{
RGBColor c1 = palette[i * 2];
RGBColor c2 = palette[i * 2 + 1];
unsigned char bN_payload[] =
{
regs[i],
style,
(unsigned char)RGBGetRValue(c1), (unsigned char)RGBGetGValue(c1), (unsigned char)RGBGetBValue(c1),
(unsigned char)RGBGetRValue(c2), (unsigned char)RGBGetGValue(c2), (unsigned char)RGBGetBValue(c2),
0x00
};
SendPacket(bN_payload, sizeof(bN_payload));
}
}
/*---------------------------------------------------------*\
| Step 3: b6 — commit/apply |
\*---------------------------------------------------------*/
unsigned char b6_payload[] = { 0xB6 };
SendPacket(b6_payload, sizeof(b6_payload));
}
void GigabyteCastor3Controller::SetOff()
{
/*---------------------------------------------------------*\
| Off = Style 0x01 (Static) with Speed=0 |
| From castor3.py: off uses style 0x01, speed_wire=0 |
\*---------------------------------------------------------*/
std::vector<RGBColor> black;
black.push_back(ToRGBColor(0x00, 0x00, 0x00));
unsigned char c9_payload[] =
{
0xC9,
CASTOR3_STYLE_STATIC,
0x00, /* speed_wire = 0 for off */
CASTOR3_BRIGHTNESS_DEFAULT,
0x02, /* b4 */
0x01 /* b5 */
};
SendPacket(c9_payload, sizeof(c9_payload));
unsigned char cd_payload[] = { 0xCD, 0x00, 0x00, 0x00 };
SendPacket(cd_payload, sizeof(cd_payload));
unsigned char b6_payload[] = { 0xB6 };
SendPacket(b6_payload, sizeof(b6_payload));
}
void GigabyteCastor3Controller::SendPacket(const unsigned char* payload, unsigned int payload_len)
{
/*---------------------------------------------------------*\
| Castor3 HID OUT transport: |
| - Byte 0: Report ID (0x99) |
| - Bytes 1..6143: payload, zero-padded |
| Total write size: 6144 bytes |
\*---------------------------------------------------------*/
unsigned char buf[CASTOR3_OUT_TOTAL];
memset(buf, 0x00, CASTOR3_OUT_TOTAL);
buf[0] = CASTOR3_REPORT_ID;
if(payload_len > CASTOR3_OUT_PAYLOAD)
{
payload_len = CASTOR3_OUT_PAYLOAD;
}
memcpy(&buf[1], payload, payload_len);
hid_write(dev, buf, CASTOR3_OUT_TOTAL);
}
@@ -1,123 +0,0 @@
/*---------------------------------------------------------*\
| GigabyteCastor3Controller.h |
| |
| Driver for Gigabyte Aorus Waterforce X II 360 AIO |
| (Castor3 USB HID controller) |
| |
| RGB ring control only — LCD not implemented |
| |
| Protocol reference: castor3.py reverse engineering |
| VID=0x0414 PID=0x7A5E Report ID=0x99 |
| OUT size: 6144 (report ID + 6143 payload) |
| IN size: 255 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <vector>
#include <hidapi.h>
#include "RGBController.h"
/*---------------------------------------------------------*\
| Castor3 USB IDs |
\*---------------------------------------------------------*/
#define CASTOR3_VID 0x0414
#define CASTOR3_PID 0x7A5E
/*---------------------------------------------------------*\
| Castor3 HID transport |
\*---------------------------------------------------------*/
#define CASTOR3_REPORT_ID 0x99
#define CASTOR3_OUT_PAYLOAD 6143 /* payload after report ID */
#define CASTOR3_OUT_TOTAL 6144 /* report ID + payload */
#define CASTOR3_IN_SIZE 255
#define CASTOR3_IN_TIMEOUT_MS 2000
/*---------------------------------------------------------*\
| LED effect style IDs (c9 byte[1]) |
| From castor3.py LED_EFFECTS, cross-referenced with |
| .cled.dat profile files and led_profile.pcapng |
\*---------------------------------------------------------*/
#define CASTOR3_STYLE_STATIC 0x01
#define CASTOR3_STYLE_PULSE 0x02
#define CASTOR3_STYLE_CYCLE 0x03
#define CASTOR3_STYLE_FLASH 0x04
#define CASTOR3_STYLE_DFLASH 0x05
#define CASTOR3_STYLE_GRADIENT 0x06
#define CASTOR3_STYLE_COLORSHIFT 0x07
#define CASTOR3_STYLE_WAVE 0x08
#define CASTOR3_STYLE_RAINBOW 0x0A
#define CASTOR3_STYLE_TRICOLOR 0x0B
#define CASTOR3_STYLE_SPIN 0x0C
#define CASTOR3_STYLE_SWITCH 0x0D
/*---------------------------------------------------------*\
| LED speed range: 1-5 (wire value = speed * 20) |
| LED brightness range: 1-10 (direct on wire) |
\*---------------------------------------------------------*/
#define CASTOR3_SPEED_MIN 1
#define CASTOR3_SPEED_MAX 5
#define CASTOR3_SPEED_DEFAULT 5
#define CASTOR3_BRIGHTNESS_MIN 1
#define CASTOR3_BRIGHTNESS_MAX 10
#define CASTOR3_BRIGHTNESS_DEFAULT 10
/*---------------------------------------------------------*\
| Color type for effects |
\*---------------------------------------------------------*/
enum castor3_color_type
{
CASTOR3_COLORS_NONE = 0, /* cycle, wave, rainbow */
CASTOR3_COLORS_SINGLE = 1, /* static, pulse, flash... */
CASTOR3_COLORS_PALETTE = 2, /* colorshift, tricolor... */
};
class GigabyteCastor3Controller
{
public:
GigabyteCastor3Controller(hid_device* dev_handle, const char* path);
~GigabyteCastor3Controller();
std::string GetDeviceLocation();
std::string GetSerialString();
std::string GetFirmwareVersion();
/*---------------------------------------------------------*\
| LED effect application |
| |
| Wire sequence per effect apply: |
| c9 [Style] [Speed*20] [Bright] [b4] [b5] |
| cd [R] [G] [B] — single-color only |
| b0 [Style] [R1G1B1] [R2G2B2] 00 — palette colors 1+2 |
| b1 [Style] [R3G3B3] [R4G4B4] 00 — colors 3+4 |
| b2 [Style] [R5G5B5] [R6G6B6] 00 — colors 5+6 |
| b3 [Style] [R7G7B7] [R8G8B8] 00 — colors 7+8 |
| b6 — commit/apply |
\*---------------------------------------------------------*/
void SetEffect(unsigned char style,
unsigned char speed,
unsigned char brightness,
unsigned char b4,
unsigned char b5,
castor3_color_type color_type,
std::vector<RGBColor> colors);
void SetOff();
private:
hid_device* dev;
std::string location;
std::string firmware_version;
void SendPacket(const unsigned char* payload, unsigned int payload_len);
};
@@ -1,37 +0,0 @@
/*---------------------------------------------------------*\
| GigabyteCastor3ControllerDetect.cpp |
| |
| Detector for Gigabyte Aorus Waterforce X II 360 AIO |
| (Castor3 USB HID controller) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "DetectionManager.h"
#include "GigabyteCastor3Controller.h"
#include "RGBController_GigabyteCastor3.h"
#define GIGABYTE_CASTOR3_VID 0x0414
#define GIGABYTE_CASTOR3_PID 0x7A5E
DetectedControllers DetectGigabyteCastor3Controllers(hid_device_info* info, const std::string& /*name*/)
{
DetectedControllers detected_controllers;
hid_device* dev;
dev = hid_open_path(info->path);
if(dev)
{
GigabyteCastor3Controller* controller = new GigabyteCastor3Controller(dev, info->path);
RGBController_GigabyteCastor3* rgb_controller = new RGBController_GigabyteCastor3(controller);
detected_controllers.push_back(rgb_controller);
}
return(detected_controllers);
}
REGISTER_HID_DETECTOR_IPU("Gigabyte Aorus Waterforce X II 360", DetectGigabyteCastor3Controllers, GIGABYTE_CASTOR3_VID, GIGABYTE_CASTOR3_PID, 0, 0x0000, 0x0002);
@@ -1,440 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_GigabyteCastor3.cpp |
| |
| RGBController for Gigabyte Aorus Waterforce X II 360 |
| AIO Cooler (Castor3 controller) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_GigabyteCastor3.h"
/**------------------------------------------------------------------*\
@name Gigabyte Aorus Waterforce X II 360
@category Cooler
@type USB
@save :o:
@direct :o:
@effects :white_check_mark:
@detectors DetectGigabyteCastor3Controllers
@comment Controls the LED ring on the pump head of the
Gigabyte Aorus Waterforce X II 360 AIO cooler.
Uses the Castor3 USB HID controller (VID 0x0414, PID 0x7A5E).
The LED ring and fans share the same controller — they are
not independently addressable and follow the same effect.
LCD display control is not implemented.
No direct/per-LED mode available — all modes are hardware
effects with a single color or palette.
\*-------------------------------------------------------------------*/
RGBController_GigabyteCastor3::RGBController_GigabyteCastor3(GigabyteCastor3Controller* controller_ptr)
{
controller = controller_ptr;
name = "Gigabyte Aorus Waterforce X II 360";
vendor = "Gigabyte";
type = DEVICE_TYPE_COOLER;
description = "Gigabyte Aorus Waterforce X II 360 AIO Cooler";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
version = controller->GetFirmwareVersion();
/*---------------------------------------------------------*\
| All modes from castor3.py LED_EFFECTS (12 effects + off) |
| |
| The Castor3 has no direct/per-LED mode. All effects are |
| hardware-driven, either single-color, palette, or |
| firmware-color (no user color). |
| |
| Speed: 1-5 mapped to MODE_FLAG_HAS_SPEED |
| Brightness: 1-10 mapped to MODE_FLAG_HAS_BRIGHTNESS |
| |
| mode.value stores the style byte for the c9 command. |
| mode.speed stores 1-5 (scaled to speed*20 on wire). |
| mode.brightness stores 1-10 (direct on wire). |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| Off |
| Wire: Style=0x01 (Static) with speed_wire=0 |
\*---------------------------------------------------------*/
mode Off;
Off.name = "Off";
Off.value = 0xFF; /* sentinel — handled specially */
Off.flags = 0;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
/*---------------------------------------------------------*\
| Static — single color, no speed |
\*---------------------------------------------------------*/
mode Static;
Static.name = "Static";
Static.value = CASTOR3_STYLE_STATIC;
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Static.colors_min = 1;
Static.colors_max = 1;
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
Static.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Static.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Static.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
Static.colors.resize(1);
modes.push_back(Static);
/*---------------------------------------------------------*\
| Pulse — single color, speed + brightness |
\*---------------------------------------------------------*/
mode Pulse;
Pulse.name = "Pulse";
Pulse.value = CASTOR3_STYLE_PULSE;
Pulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Pulse.speed_min = CASTOR3_SPEED_MIN;
Pulse.speed_max = CASTOR3_SPEED_MAX;
Pulse.speed = CASTOR3_SPEED_DEFAULT;
Pulse.colors_min = 1;
Pulse.colors_max = 1;
Pulse.color_mode = MODE_COLORS_MODE_SPECIFIC;
Pulse.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Pulse.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Pulse.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
Pulse.colors.resize(1);
modes.push_back(Pulse);
/*---------------------------------------------------------*\
| Flash — single color, speed + brightness |
\*---------------------------------------------------------*/
mode Flash;
Flash.name = "Flash";
Flash.value = CASTOR3_STYLE_FLASH;
Flash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Flash.speed_min = CASTOR3_SPEED_MIN;
Flash.speed_max = CASTOR3_SPEED_MAX;
Flash.speed = CASTOR3_SPEED_DEFAULT;
Flash.colors_min = 1;
Flash.colors_max = 1;
Flash.color_mode = MODE_COLORS_MODE_SPECIFIC;
Flash.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Flash.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Flash.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
Flash.colors.resize(1);
modes.push_back(Flash);
/*---------------------------------------------------------*\
| Double Flash — single color, speed + brightness |
\*---------------------------------------------------------*/
mode DFlash;
DFlash.name = "Double Flash";
DFlash.value = CASTOR3_STYLE_DFLASH;
DFlash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
DFlash.speed_min = CASTOR3_SPEED_MIN;
DFlash.speed_max = CASTOR3_SPEED_MAX;
DFlash.speed = CASTOR3_SPEED_DEFAULT;
DFlash.colors_min = 1;
DFlash.colors_max = 1;
DFlash.color_mode = MODE_COLORS_MODE_SPECIFIC;
DFlash.brightness_min = CASTOR3_BRIGHTNESS_MIN;
DFlash.brightness_max = CASTOR3_BRIGHTNESS_MAX;
DFlash.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
DFlash.colors.resize(1);
modes.push_back(DFlash);
/*---------------------------------------------------------*\
| Cycle — firmware colors, speed only |
\*---------------------------------------------------------*/
mode Cycle;
Cycle.name = "Spectrum Cycle";
Cycle.value = CASTOR3_STYLE_CYCLE;
Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Cycle.speed_min = CASTOR3_SPEED_MIN;
Cycle.speed_max = CASTOR3_SPEED_MAX;
Cycle.speed = CASTOR3_SPEED_DEFAULT;
Cycle.color_mode = MODE_COLORS_NONE;
Cycle.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Cycle.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Cycle.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
modes.push_back(Cycle);
/*---------------------------------------------------------*\
| Gradient — single color, speed + brightness |
| Note: b4 = brightness on wire (special case) |
\*---------------------------------------------------------*/
mode Gradient;
Gradient.name = "Gradient";
Gradient.value = CASTOR3_STYLE_GRADIENT;
Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Gradient.speed_min = CASTOR3_SPEED_MIN;
Gradient.speed_max = CASTOR3_SPEED_MAX;
Gradient.speed = CASTOR3_SPEED_DEFAULT;
Gradient.colors_min = 1;
Gradient.colors_max = 1;
Gradient.color_mode = MODE_COLORS_MODE_SPECIFIC;
Gradient.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Gradient.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Gradient.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
Gradient.colors.resize(1);
modes.push_back(Gradient);
/*---------------------------------------------------------*\
| Color Shift — 8-color palette, speed + brightness |
\*---------------------------------------------------------*/
mode ColorShift;
ColorShift.name = "Color Shift";
ColorShift.value = CASTOR3_STYLE_COLORSHIFT;
ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
ColorShift.speed_min = CASTOR3_SPEED_MIN;
ColorShift.speed_max = CASTOR3_SPEED_MAX;
ColorShift.speed = CASTOR3_SPEED_DEFAULT;
ColorShift.colors_min = 1;
ColorShift.colors_max = 8;
ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC;
ColorShift.brightness_min = CASTOR3_BRIGHTNESS_MIN;
ColorShift.brightness_max = CASTOR3_BRIGHTNESS_MAX;
ColorShift.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
ColorShift.colors.resize(8);
ColorShift.colors[0] = ToRGBColor(0xFF, 0x00, 0x00);
ColorShift.colors[1] = ToRGBColor(0xFF, 0x72, 0x00);
ColorShift.colors[2] = ToRGBColor(0xFF, 0xFF, 0x00);
ColorShift.colors[3] = ToRGBColor(0x00, 0xFF, 0x00);
ColorShift.colors[4] = ToRGBColor(0x00, 0xFF, 0xFF);
ColorShift.colors[5] = ToRGBColor(0x00, 0x00, 0xFF);
ColorShift.colors[6] = ToRGBColor(0xFF, 0x00, 0xFF);
ColorShift.colors[7] = ToRGBColor(0xFF, 0x80, 0x80);
modes.push_back(ColorShift);
/*---------------------------------------------------------*\
| Wave — firmware colors, speed only |
\*---------------------------------------------------------*/
mode Wave;
Wave.name = "Wave";
Wave.value = CASTOR3_STYLE_WAVE;
Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Wave.speed_min = CASTOR3_SPEED_MIN;
Wave.speed_max = CASTOR3_SPEED_MAX;
Wave.speed = CASTOR3_SPEED_DEFAULT;
Wave.color_mode = MODE_COLORS_NONE;
Wave.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Wave.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Wave.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
modes.push_back(Wave);
/*---------------------------------------------------------*\
| Rainbow — firmware colors, speed only |
\*---------------------------------------------------------*/
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = CASTOR3_STYLE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
Rainbow.speed_min = CASTOR3_SPEED_MIN;
Rainbow.speed_max = CASTOR3_SPEED_MAX;
Rainbow.speed = CASTOR3_SPEED_DEFAULT;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Rainbow.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Rainbow.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
modes.push_back(Rainbow);
/*---------------------------------------------------------*\
| Tri-Color — 3-color palette, speed + brightness |
\*---------------------------------------------------------*/
mode TriColor;
TriColor.name = "Tri-Color";
TriColor.value = CASTOR3_STYLE_TRICOLOR;
TriColor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
TriColor.speed_min = CASTOR3_SPEED_MIN;
TriColor.speed_max = CASTOR3_SPEED_MAX;
TriColor.speed = CASTOR3_SPEED_DEFAULT;
TriColor.colors_min = 1;
TriColor.colors_max = 3;
TriColor.color_mode = MODE_COLORS_MODE_SPECIFIC;
TriColor.brightness_min = CASTOR3_BRIGHTNESS_MIN;
TriColor.brightness_max = CASTOR3_BRIGHTNESS_MAX;
TriColor.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
TriColor.colors.resize(3);
TriColor.colors[0] = ToRGBColor(0x00, 0x00, 0xFF);
TriColor.colors[1] = ToRGBColor(0x7D, 0x00, 0xFF);
TriColor.colors[2] = ToRGBColor(0xFF, 0x00, 0xFF);
modes.push_back(TriColor);
/*---------------------------------------------------------*\
| Spin — 3-color palette, speed + brightness |
\*---------------------------------------------------------*/
mode Spin;
Spin.name = "Spin";
Spin.value = CASTOR3_STYLE_SPIN;
Spin.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Spin.speed_min = CASTOR3_SPEED_MIN;
Spin.speed_max = CASTOR3_SPEED_MAX;
Spin.speed = CASTOR3_SPEED_DEFAULT;
Spin.colors_min = 1;
Spin.colors_max = 3;
Spin.color_mode = MODE_COLORS_MODE_SPECIFIC;
Spin.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Spin.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Spin.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
Spin.colors.resize(3);
Spin.colors[0] = ToRGBColor(0xFF, 0x00, 0xFE);
Spin.colors[1] = ToRGBColor(0x00, 0xFF, 0xFB);
Spin.colors[2] = ToRGBColor(0xFF, 0xFF, 0x00);
modes.push_back(Spin);
/*---------------------------------------------------------*\
| Switch — 2-color palette, speed + brightness |
\*---------------------------------------------------------*/
mode Switch;
Switch.name = "Switch";
Switch.value = CASTOR3_STYLE_SWITCH;
Switch.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Switch.speed_min = CASTOR3_SPEED_MIN;
Switch.speed_max = CASTOR3_SPEED_MAX;
Switch.speed = CASTOR3_SPEED_DEFAULT;
Switch.colors_min = 1;
Switch.colors_max = 2;
Switch.color_mode = MODE_COLORS_MODE_SPECIFIC;
Switch.brightness_min = CASTOR3_BRIGHTNESS_MIN;
Switch.brightness_max = CASTOR3_BRIGHTNESS_MAX;
Switch.brightness = CASTOR3_BRIGHTNESS_DEFAULT;
Switch.colors.resize(2);
Switch.colors[0] = ToRGBColor(0xFF, 0x00, 0xFE);
Switch.colors[1] = ToRGBColor(0x00, 0xFF, 0xFB);
modes.push_back(Switch);
SetupZones();
}
RGBController_GigabyteCastor3::~RGBController_GigabyteCastor3()
{
Shutdown();
delete controller;
}
void RGBController_GigabyteCastor3::SetupZones()
{
/*---------------------------------------------------------*\
| Single zone: LED ring + fans (not independently |
| addressable — fans follow the pump ring effect) |
| |
| This is a SINGLE zone because the protocol does not |
| expose per-LED addressing. All LEDs display the same |
| hardware effect simultaneously. |
\*---------------------------------------------------------*/
zone led_ring;
led_ring.name = "LED Ring";
led_ring.type = ZONE_TYPE_SINGLE;
led_ring.leds_min = 1;
led_ring.leds_max = 1;
led_ring.leds_count = 1;
zones.push_back(led_ring);
led new_led;
new_led.name = "LED Ring";
leds.push_back(new_led);
SetupColors();
}
void RGBController_GigabyteCastor3::DeviceUpdateLEDs()
{
DeviceUpdateMode();
}
void RGBController_GigabyteCastor3::DeviceUpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_GigabyteCastor3::DeviceUpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_GigabyteCastor3::DeviceUpdateMode()
{
unsigned char style = (unsigned char)modes[active_mode].value;
/*---------------------------------------------------------*\
| Handle Off mode (sentinel value 0xFF) |
\*---------------------------------------------------------*/
if(style == 0xFF)
{
controller->SetOff();
return;
}
/*---------------------------------------------------------*\
| Determine speed, brightness, b4, b5, and color type |
| from the effect lookup table matching castor3.py |
\*---------------------------------------------------------*/
unsigned char speed = CASTOR3_SPEED_DEFAULT;
unsigned char brightness = CASTOR3_BRIGHTNESS_DEFAULT;
if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED)
{
speed = (unsigned char)modes[active_mode].speed;
}
if(modes[active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS)
{
brightness = (unsigned char)modes[active_mode].brightness;
}
/*---------------------------------------------------------*\
| Look up b4, b5, and color_type per effect |
| These match the LED_EFFECTS dict in castor3.py |
\*---------------------------------------------------------*/
unsigned char b4 = 0x02;
unsigned char b5 = 0x01;
castor3_color_type color_type = CASTOR3_COLORS_NONE;
switch(style)
{
case CASTOR3_STYLE_STATIC:
case CASTOR3_STYLE_PULSE:
case CASTOR3_STYLE_FLASH:
case CASTOR3_STYLE_DFLASH:
b4 = 0x02;
b5 = 0x01;
color_type = CASTOR3_COLORS_SINGLE;
break;
case CASTOR3_STYLE_GRADIENT:
/*-------------------------------------------------*\
| Gradient: b4 = brightness on wire (special case) |
\*-------------------------------------------------*/
b4 = brightness;
b5 = 0x01;
color_type = CASTOR3_COLORS_SINGLE;
break;
case CASTOR3_STYLE_CYCLE:
case CASTOR3_STYLE_WAVE:
case CASTOR3_STYLE_RAINBOW:
b4 = 0x02;
b5 = 0x01;
color_type = CASTOR3_COLORS_NONE;
break;
case CASTOR3_STYLE_COLORSHIFT:
b4 = 0x08; /* ClrCount=8 */
b5 = 0x02; /* CmbIndex+1=2 */
color_type = CASTOR3_COLORS_PALETTE;
break;
case CASTOR3_STYLE_TRICOLOR:
case CASTOR3_STYLE_SPIN:
b4 = 0x02;
b5 = 0x01;
color_type = CASTOR3_COLORS_PALETTE;
break;
case CASTOR3_STYLE_SWITCH:
b4 = 0x02;
b5 = 0x01;
color_type = CASTOR3_COLORS_PALETTE;
break;
}
controller->SetEffect(style, speed, brightness, b4, b5,
color_type, modes[active_mode].colors);
}
@@ -1,32 +0,0 @@
/*---------------------------------------------------------*\
| RGBController_GigabyteCastor3.h |
| |
| RGBController for Gigabyte Aorus Waterforce X II 360 |
| AIO Cooler (Castor3 controller) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "GigabyteCastor3Controller.h"
class RGBController_GigabyteCastor3 : public RGBController
{
public:
RGBController_GigabyteCastor3(GigabyteCastor3Controller* controller_ptr);
~RGBController_GigabyteCastor3();
void SetupZones();
void DeviceUpdateLEDs();
void DeviceUpdateZoneLEDs(int zone);
void DeviceUpdateSingleLED(int led);
void DeviceUpdateMode();
private:
GigabyteCastor3Controller* controller;
};
@@ -68,14 +68,9 @@ void RGBFusion2BlackwellGPUController::SetMode(uint8_t type, uint8_t zone, uint8
if(zone_config.numberOfColors > 0)
{
int currentPos = 12;
switch(gpu_layout)
if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT)
{
case RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT:
case RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT:
currentPos = 11;
break;
default:
break;
currentPos = 11;
}
for(uint8_t i = 0; i < zone_config.numberOfColors; i++)
@@ -95,16 +90,6 @@ void RGBFusion2BlackwellGPUController::SetZone(uint8_t zone, uint8_t mode, fusio
if(mode == RGB_FUSION2_BLACKWELL_GPU_MODE_BREATHING)
zone_config.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX;
switch(gpu_layout)
{
case RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT:
if(mode == RGB_FUSION2_BLACKWELL_GPU_MODE_DIRECT)
mode = RGB_FUSION2_BLACKWELL_GPU_MODE_STATIC;
break;
default:
break;
}
uint8_t type = RGB_FUSION2_BLACKWELL_GPU_REG_COLOR;
if(mode != RGB_FUSION2_BLACKWELL_GPU_MODE_DIRECT)
type = RGB_FUSION2_BLACKWELL_GPU_REG_MODE;
@@ -62,12 +62,11 @@ enum
enum
{
RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE = 0,
RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT = 1,
RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT = 2,
RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT = 3,
RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT = 4,
RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT = 5,
RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE = 0,
RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT = 1,
RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT = 2,
RGB_FUSION2_BLACKWELL_GPU_AORUS_WATERFORCE_LAYOUT = 3,
RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT = 4,
};
class RGBFusion2BlackwellGPUController
@@ -1,4 +1,4 @@
/*---------------------------------------------------------*\
/*---------------------------------------------------------*\
| GigabyteRGBFusion2BlackwellGPUControllerDetect.cpp |
| |
| Detector for Gigabyte RGB Fusion 2 Blackwell GPU |
@@ -44,9 +44,8 @@ bool TestForGigabyteRGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, u
//GeForce RTX 5070 Ti Gaming OC 16G 0x01 0x01 0x01 0x00
//GeForce RTX 5070 Gaming OC 12G 0x01 0x01 0x01 0x00
//GeForce RTX 5080 AORUS MASTER 16G 0x01 0x01 0x01 0x10
//Radeon RX 9070 XT GAMING OC 16G 0x01 0x02 0x01 0x00
if(res < 0 || data_readpkt[0] != 0x01 || (data_readpkt[1] != 0x01 && data_readpkt[1] != 0x02) || data_readpkt[2] != 0x01)
if(res < 0 || data_readpkt[0] != 0x01 || data_readpkt[1] != 0x01 || data_readpkt[2] != 0x01)
{
// Assemble C-string with respons for debugging
std::string text = "";
@@ -58,7 +57,7 @@ bool TestForGigabyteRGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, u
text.append(str);
}
LOG_DEBUG("[%s] at address 0x%02X invalid. Expected 0x01 0x01/0x02 0x01 [0x*] but received:%s", GIGABYTEGPU_CONTROLLER_NAME3, address, text.c_str());
LOG_DEBUG("[%s] at address 0x%02X invalid. Expected 0x01 0x01 0x01 [0x*] but received:%s", GIGABYTEGPU_CONTROLLER_NAME3, address, text.c_str());
pass = false;
}
@@ -106,42 +105,34 @@ DetectedControllers DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUCon
return(DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT));
}
DetectedControllers DetectGigabyteRGBFusion2BlackwellAorusMaster5090DV2IceLayoutGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
{
return(DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT));
}
/*---------------------------------------------------------*\
| Nvidia GPUs |
\*---------------------------------------------------------*/
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5060 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5060TI_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_AERO_OC_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Eagle OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_EAGLE_OC_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Eagle OC ICE", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_EAGLE_OC_ICE_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_GAMING_OC_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Eagle OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_EAGLE_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Eagle OC ICE", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_EAGLE_OC_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_AERO_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_AERO_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellAorusWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER ICE", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV1, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV2, 0x75);
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);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5060 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5060TI_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_AERO_OC_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Eagle OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_EAGLE_OC_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_GAMING_OC_12G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Eagle OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_EAGLE_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Eagle OC ICE", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_EAGLE_OC_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_AERO_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_AERO_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 MASTER", DetectGigabyteRGBFusion2BlackwellAorusMaster5080LayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_MASTER_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellAorusWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte 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 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);
/*---------------------------------------------------------*\
| AMD GPUs |
\*---------------------------------------------------------*/
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);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC ICE", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_16G_SUB_DEV, 0x75);
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);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC ICE", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_ICE_16G_SUB_DEV, 0x75);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_16G_SUB_DEV, 0x75);
@@ -395,49 +395,6 @@ void RGBController_RGBFusion2BlackwellGPU::SetupZones()
leds.push_back(top_led);
}
else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT)
{
const char * fan_names[] = { "Right Fan", "Left Fan", "Middle Fan" };
for(int i = 0; i < 3; i++)
{
zone fan_zone;
fan_zone.name = fan_names[i];
fan_zone.type = ZONE_TYPE_SINGLE;
fan_zone.leds_min = 1;
fan_zone.leds_max = 1;
fan_zone.leds_count = 1;
zones.push_back(fan_zone);
led new_led;
new_led.name = fan_names[i];
leds.push_back(new_led);
}
zone backplate;
backplate.name = "Backplate";
backplate.type = ZONE_TYPE_SINGLE;
backplate.leds_min = 1;
backplate.leds_max = 1;
backplate.leds_count = 1;
zones.push_back(backplate);
led bp_led;
bp_led.name = "Backplate";
leds.push_back(bp_led);
zone side_logo;
side_logo.name = "Side Logo";
side_logo.type = ZONE_TYPE_SINGLE;
side_logo.leds_min = 1;
side_logo.leds_max = 1;
side_logo.leds_count = 1;
zones.push_back(side_logo);
led sl_led;
sl_led.name = "Side Logo";
leds.push_back(sl_led);
}
SetupColors();
}
@@ -477,10 +434,6 @@ void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateLEDs()
gpu_zones = 6; // Zones 4 and 5 refer to ui zone 4
break;
case RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT:
gpu_zones = 6;
break;
default:
LOG_TRACE("[%s] Invalid GPU layout (%d) when updating LEDs.", name.c_str(), gpu_layout);
return; // should not happen
@@ -507,8 +460,7 @@ void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateLEDs()
}
ui_zone_idx = zone_idx - 1; // Map: HW zone 1->UI zone 0, HW zone 2->UI zone 1, HW zone 3->UI zone 2, HW zone 4->UI zone 3
}
else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT ||
gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5090D_V2_ICE_LAYOUT)
else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_AORUS_MASTER_5080_LAYOUT)
{
if(zone_idx == 5)
{
@@ -135,7 +135,6 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3090 XTREME WATERFORCE",
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3090 XTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_XTREME_WATERFORCE_WB_SUB_DEV, 0x64);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_GAMING_OC_12G, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_GAMING_OC_12G_V2, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_AD103_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_GAMING_OC_12G_V2, 0x71);
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);
@@ -170,16 +169,13 @@ REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER ICE",
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7600 GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7600_GAMING_OC_8G_SUB_DEV, 0x55);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7600 GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7600_GAMING_OC_8G_SUB_DEV2, 0x55);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7600 XT GAMING OC 16G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7600XT_GAMING_OC_16G_SUB_DEV, 0x55);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6700 XT EAGLE 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX6700XT_EAGLE_12G_SUB_DEV, 0x63);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6700 XT GAMING OC 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX6700XT_GAMING_OC_12G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6800 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, GIGABYTE_SUB_VEN, GIGABYTE_RX6800XT_GAMING_OC_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 6900 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, GIGABYTE_SUB_VEN, GIGABYTE_RX6900XT_GAMING_OC_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7700 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7700XT_GAMING_OC_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7800 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7800XT_GAMING_OC_16G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 GRE GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900GRE_GAMING_OC_16G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XT_GAMING_OC_20G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XTX GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XTX_GAMING_OC_24G_SUB_DEV, 0x62);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 7900 XTX ELITE 24G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX7900XTX_ELITE_24G_SUB_DEV, 0x71);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6750 XT ELITE 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX_6750_XT_ELITE_12G_SUB_DEV, 0x70);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6900 XT EXTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, GIGABYTE_SUB_VEN, GIGABYTE_RX6900XT_XTREME_WATERFORCE_WB_SUB_DEV, 0x70);
REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 9070 XT Elite", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX9070XT_ELITE_16G_SUB_DEV, 0x73);
File diff suppressed because it is too large Load Diff

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