Publish LumaOps source

This commit is contained in:
LumaOps release export
2026-09-03 01:18:36 +02:00
commit 7f1c0e5f71
2363 changed files with 501543 additions and 0 deletions
@@ -0,0 +1,128 @@
/*---------------------------------------------------------*\
| SteelSeriesAerox3Controller.cpp |
| |
| Driver for SteelSeries Aerox 3 |
| |
| Chris M (Dr_No) 09 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "SteelSeriesAerox3Controller.h"
#include "LogManager.h"
SteelSeriesAerox3Controller::SteelSeriesAerox3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name)
{
SendInit();
}
SteelSeriesAerox3Controller::~SteelSeriesAerox3Controller()
{
hid_close(dev);
}
void SteelSeriesAerox3Controller::SendInit()
{
/*-----------------------------------------------------------------*\
| This sets sensitivity and allows software mode?? max 5 uint8 |
| buffer[2] = Count eg. 0 thru 5 |
| buffer[4] to [8] = dpi / 50 range = 0x04 - 0xC7 eg. 400 = 0x08 |
\*-----------------------------------------------------------------*/
uint8_t buffer[STEELSERIES_AEORX3_PACKET_SIZE] = { 0x00, 0x2D };
hid_send_feature_report(dev, buffer, STEELSERIES_AEORX3_PACKET_SIZE);
}
std::string SteelSeriesAerox3Controller::GetFirmwareVersion()
{
uint8_t result = 0;
const uint8_t CMD = 0x90;
const uint8_t sz = 16;
char version[sz + 1];
uint8_t buffer[STEELSERIES_AEORX3_PACKET_SIZE] = { 0x00, CMD, 0x00 };
hid_send_feature_report(dev, buffer, STEELSERIES_AEORX3_PACKET_SIZE);
do
{
result = hid_read_timeout(dev, buffer, STEELSERIES_AEORX3_PACKET_SIZE, STEELSERIES_AEORX3_TIMEOUT);
LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", STEELSERIES_AEORX3_NAME, result,
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]);
} while(result > 0 && buffer[0] != CMD);
if(buffer[0] == CMD)
{
/*-----------------------------------------------------------------*\
| Read the version from the second character |
\*-----------------------------------------------------------------*/
memcpy(version, &buffer[1], sz);
version[sz] = 0;
std::string tmp = std::string(version);
LOG_DEBUG("[%s] Version: %s as string %s", STEELSERIES_AEORX3_NAME, version, tmp.c_str());
return tmp;
}
else
{
LOG_DEBUG("[%s] Unable to get version: giving up!", STEELSERIES_AEORX3_NAME);
return "";
}
}
steelseries_mouse SteelSeriesAerox3Controller::GetMouse()
{
return aerox_3;
}
void SteelSeriesAerox3Controller::SetLightEffectAll(uint8_t /*effect*/)
{
/*-----------------------------------------------------------------*\
| Not used by this device |
\*-----------------------------------------------------------------*/
}
void SteelSeriesAerox3Controller::SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
)
{
uint8_t buffer[STEELSERIES_AEORX3_PACKET_SIZE] = { 0x00, 0x21 };
buffer[0x02] = 1 << zone_id;
uint8_t offset = 3 + zone_id * 3;
buffer[offset] = red;
buffer[offset + 1] = green;
buffer[offset + 2] = blue;
hid_write(dev, buffer, STEELSERIES_AEORX3_PACKET_SIZE);
if(brightness != current_brightness)
{
SetBrightness(brightness);
current_brightness = brightness;
}
}
void SteelSeriesAerox3Controller::SetBrightness(uint8_t brightness)
{
uint8_t buffer[STEELSERIES_AEORX3_PACKET_SIZE] = { 0x00, 0x23, brightness };
hid_write(dev, buffer, STEELSERIES_AEORX3_PACKET_SIZE);
}
void SteelSeriesAerox3Controller::Save()
{
/*---------------------------------------------------------------------------------*\
| Save packet was not confirmed as working but packet is verified as correct. |
| https://github.com/flozz/rivalcfg/blob/master/rivalcfg/devices/aerox3.py#L141 |
\*---------------------------------------------------------------------------------*/
uint8_t buffer2[STEELSERIES_AEORX3_PACKET_SIZE] = { 0x00, 0x11, 0x00 };
hid_write(dev, buffer2, STEELSERIES_AEORX3_PACKET_SIZE);
}
@@ -0,0 +1,58 @@
/*---------------------------------------------------------*\
| SteelSeriesAerox3Controller.h |
| |
| Driver for SteelSeries Aerox 3 |
| |
| Chris M (Dr_No) 09 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesMouseController.h"
#define STEELSERIES_AEORX3_NAME "SteelSeries Aerox 3"
#define STEELSERIES_AEORX3_PACKET_SIZE 65
#define STEELSERIES_AEORX3_TIMEOUT 250
static const steelseries_mouse aerox_3 =
{
{ 0x04 },
{
{"Front", 0 },
{"Middle", 1 },
{"Rear", 2 },
}
};
class SteelSeriesAerox3Controller: public SteelSeriesMouseController
{
public:
SteelSeriesAerox3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name);
~SteelSeriesAerox3Controller();
std::string GetFirmwareVersion() override;
steelseries_mouse GetMouse() override;
void Save() override;
void SetLightEffectAll(uint8_t effect) override;
void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
) override;
private:
void SendInit();
void SetBrightness(uint8_t brightness);
uint8_t current_brightness;
};
@@ -0,0 +1,147 @@
/*---------------------------------------------------------*\
| SteelSeriesAerox5Controller.cpp |
| |
| Driver for the Steelseries Aerox 5 |
| |
| Bobby Quantum (BobbyQuantum) 19 May 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "SteelSeriesAerox5Controller.h"
#include "LogManager.h"
SteelSeriesAerox5Controller::SteelSeriesAerox5Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name)
{
SendInit();
}
SteelSeriesAerox5Controller::~SteelSeriesAerox5Controller()
{
hid_close(dev);
}
void SteelSeriesAerox5Controller::SendInit()
{
/*-----------------------------------------------------------------*\
| This sets sensitivity and allows software mode?? max 5 uint8 |
| buffer[2] = Count eg. 0 thru 5 |
| buffer[4] to [8] = dpi / 50 range = 0x04 - 0xC7 eg. 400 = 0x08 |
\*-----------------------------------------------------------------*/
uint8_t buffer[STEELSERIES_AEROX5_PACKET_SIZE] = { 0x00, 0x2D };
hid_send_feature_report(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE);
}
std::string SteelSeriesAerox5Controller::GetFirmwareVersion()
{
uint8_t result = 0;
const uint8_t CMD = 0x90;
const uint8_t sz = 16;
char version[sz + 1];
uint8_t buffer[STEELSERIES_AEROX5_PACKET_SIZE] = { 0x00, CMD, 0x00 };
hid_send_feature_report(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE);
do
{
result = hid_read_timeout(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE, STEELSERIES_AEROX5_TIMEOUT);
LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", STEELSERIES_AEROX5_NAME, result,
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]);
} while(result > 0 && buffer[0] != CMD);
if(buffer[0] == CMD)
{
/*-----------------------------------------------------------------*\
| Read the version from the second character |
\*-----------------------------------------------------------------*/
memcpy(version, &buffer[1], sz);
version[sz] = 0;
std::string tmp = std::string(version);
LOG_DEBUG("[%s] Version: %s as string %s", STEELSERIES_AEROX5_NAME, version, tmp.c_str());
return tmp;
}
else
{
LOG_DEBUG("[%s] Unable to get version: giving up!", STEELSERIES_AEROX5_NAME);
return "";
}
}
steelseries_mouse SteelSeriesAerox5Controller::GetMouse()
{
return aerox_5;
}
void SteelSeriesAerox5Controller::SetLightEffectAll(uint8_t /*effect*/)
{
/*-----------------------------------------------------------------*\
| Not used by this device |
\*-----------------------------------------------------------------*/
}
void SteelSeriesAerox5Controller::SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
)
{
uint8_t buffer[STEELSERIES_AEROX5_PACKET_SIZE] = { 0x00, 0x21, 0x01 };
uint8_t offset = 0x03;
switch (zone_id)
{
case 0:
offset = 0x03;
break;
case 1:
buffer[2] = 0x02;
offset = 0x06;
break;
case 2:
buffer[2] = 0x04;
offset = 0x09;
break;
case 3:
buffer[1] = 0x26;
offset = 0x04;
break;
default:
return;
}
buffer[offset] = red;
buffer[offset + 1] = green;
buffer[offset + 2] = blue;
hid_write(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE);
std::this_thread::sleep_for(std::chrono::milliseconds(2));
if (brightness != current_brightness)
{
SetBrightness(brightness);
current_brightness = brightness;
}
}
void SteelSeriesAerox5Controller::SetBrightness(uint8_t brightness)
{
uint8_t buffer[3] = { 0x00, 0x23, brightness };
hid_write(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE);
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
void SteelSeriesAerox5Controller::Save()
{
uint8_t buffer2[3] = { 0x00, 0x11, 0x00 };
hid_write(dev, buffer2, STEELSERIES_AEROX5_PACKET_SIZE);
}
@@ -0,0 +1,61 @@
/*---------------------------------------------------------*\
| SteelSeriesAerox5Controller.h |
| |
| Driver for the Steelseries Aerox 5 |
| |
| Bobby Quantum (BobbyQuantum) 19 May 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesMouseController.h"
#define STEELSERIES_AEROX5_NAME "SteelSeries Aerox 5"
#define STEELSERIES_AEROX5_PACKET_SIZE 65
#define STEELSERIES_AEROX5_TIMEOUT 250
static const steelseries_mouse aerox_5 =
{
{ 0x04 },
{
{"Front", 0 },
{"Middle", 1 },
{"Rear", 2 },
{"Reactive", 3 },
}
};
class SteelSeriesAerox5Controller : public SteelSeriesMouseController
{
public:
SteelSeriesAerox5Controller(hid_device *dev_handle, steelseries_type proto_type, const char *path, std::string dev_name);
~SteelSeriesAerox5Controller();
std::string GetFirmwareVersion() override;
steelseries_mouse GetMouse() override;
void Save() override;
void SetLightEffectAll(uint8_t effect) override;
void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
) override;
private:
void SendInit();
void SetBrightness(uint8_t brightness);
uint8_t current_brightness;
};
@@ -0,0 +1,225 @@
/*---------------------------------------------------------*\
| SteelSeriesAeroxWirelessController.cpp |
| |
| Driver for SteelSeries Aerox 3, 5 and 9 Wireless |
| |
| Ensar S (esensar) 09 Sep 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "SteelSeriesAeroxWirelessController.h"
#include "LogManager.h"
#include "SteelSeriesGeneric.h"
SteelSeriesAeroxWirelessController::SteelSeriesAeroxWirelessController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name)
{
switch(proto_type)
{
case AEROX_3_WIRELESS:
name = STEELSERIES_AEROX3_WIRELESS_NAME;
break;
case AEROX_3_WIRELESS_WIRED:
name = STEELSERIES_AEROX3_WIRELESS_WIRED_NAME;
break;
case AEROX_5_WIRELESS:
name = STEELSERIES_AEROX5_WIRELESS_NAME;
break;
case AEROX_5_WIRELESS_WIRED:
name = STEELSERIES_AEROX5_WIRELESS_WIRED_NAME;
break;
case AEROX_5_DESTINY_WIRELESS:
name = STEELSERIES_AEROX5_DESTINY_WIRELESS_NAME;
break;
case AEROX_5_DESTINY_WIRELESS_WIRED:
name = STEELSERIES_AEROX5_DESTINY_WIRELESS_WIRED_NAME;
break;
case AEROX_5_DIABLO_WIRELESS:
name = STEELSERIES_AEROX5_DIABLO_WIRELESS_NAME;
break;
case AEROX_5_DIABLO_WIRELESS_WIRED:
name = STEELSERIES_AEROX5_DIABLO_WIRELESS_WIRED_NAME;
break;
case AEROX_9_WIRELESS:
name = STEELSERIES_AEROX9_WIRELESS_NAME;
break;
case AEROX_9_WIRELESS_WIRED:
name = STEELSERIES_AEROX9_WIRELESS_WIRED_NAME;
break;
default:
name = STEELSERIES_AEROX3_WIRELESS_NAME;
break;
}
SendInit();
}
SteelSeriesAeroxWirelessController::~SteelSeriesAeroxWirelessController()
{
hid_close(dev);
}
void SteelSeriesAeroxWirelessController::SendInit()
{
/*-----------------------------------------------------------------*\
| This sets sensitivity and allows software mode?? max 5 uint8 |
| buffer[2] = Count eg. 0 thru 5 |
| buffer[4] to [8] = dpi / 50 range = 0x04 - 0xC7 eg. 400 = 0x08 |
\*-----------------------------------------------------------------*/
uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x2D };
hid_send_feature_report(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE);
}
bool SteelSeriesAeroxWirelessController::IsWireless()
{
switch(proto)
{
case AEROX_3_WIRELESS:
case AEROX_5_WIRELESS:
case AEROX_5_DESTINY_WIRELESS:
case AEROX_5_DIABLO_WIRELESS:
case AEROX_9_WIRELESS:
return true;
break;
case AEROX_3_WIRELESS_WIRED:
case AEROX_5_WIRELESS_WIRED:
case AEROX_5_DESTINY_WIRELESS_WIRED:
case AEROX_5_DIABLO_WIRELESS_WIRED:
case AEROX_9_WIRELESS_WIRED:
default:
return false;
break;
}
}
std::string SteelSeriesAeroxWirelessController::GetFirmwareVersion()
{
uint8_t result = 0;
const uint8_t CMD = 0x90;
const uint8_t sz = 16;
char version[sz + 1];
uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, CMD, 0x00 };
hid_send_feature_report(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE);
do
{
result = hid_read_timeout(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE, STEELSERIES_AEROX_WIRELESS_TIMEOUT);
LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", name, result,
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]);
} while(result > 0 && buffer[0] != CMD);
if(buffer[0] == CMD)
{
/*-----------------------------------------------------------------*\
| Read the version from the second character |
\*-----------------------------------------------------------------*/
memcpy(version, &buffer[1], sz);
version[sz] = 0;
std::string tmp = std::string(version);
LOG_DEBUG("[%s] Version: %s as string %s", name, version, tmp.c_str());
return tmp;
}
else
{
LOG_DEBUG("[%s] Unable to get version: giving up!", name);
return "";
}
}
steelseries_mouse SteelSeriesAeroxWirelessController::GetMouse()
{
switch(proto)
{
case AEROX_9_WIRELESS:
case AEROX_9_WIRELESS_WIRED:
return aerox_9;
break;
default:
return aerox_3_wireless;
break;
}
}
void SteelSeriesAeroxWirelessController::SetLightEffectAll(uint8_t effect)
{
if(effect == 0x05)
{
uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x22, 0xFF };
WriteBuffer(buffer);
}
}
void SteelSeriesAeroxWirelessController::SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
)
{
uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x21, 0x01 };
uint8_t offset = 0x04;
if (zone_id == 3 && (proto == AEROX_9_WIRELESS_WIRED || proto == AEROX_9_WIRELESS))
{
buffer[0x03] = 0x00;
buffer[0x01] = 0x26;
}
else
{
buffer[0x03] = zone_id;
}
buffer[offset] = red;
buffer[offset + 1] = green;
buffer[offset + 2] = blue;
WriteBuffer(buffer);
// Supports only 10 steps of brightness
brightness = (uint8_t)(brightness / 10);
if(brightness != current_brightness)
{
SetBrightness(brightness);
current_brightness = brightness;
}
}
void SteelSeriesAeroxWirelessController::SetBrightness(uint8_t brightness)
{
uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x23, brightness };
WriteBuffer(buffer);
}
void SteelSeriesAeroxWirelessController::Save()
{
/*---------------------------------------------------------------------------------*\
| Save packet was not confirmed as working but packet is verified as correct. |
| https://github.com/flozz/rivalcfg/blob/master/rivalcfg/devices/aerox3.py#L141 |
\*---------------------------------------------------------------------------------*/
uint8_t buffer2[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x11, 0x00 };
WriteBuffer(buffer2);
}
void SteelSeriesAeroxWirelessController::WriteBuffer(uint8_t* buffer)
{
if(IsWireless())
{
buffer[1] |= STEELSERIES_AEROX_WIRELESS_FLAG;
}
hid_write(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE);
if(IsWireless())
{
// Readback required in wireless mode
hid_read_timeout(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE, STEELSERIES_AEROX_WIRELESS_TIMEOUT);
}
}
@@ -0,0 +1,82 @@
/*---------------------------------------------------------*\
| SteelSeriesAeroxWirelessController.h |
| |
| Driver for SteelSeries Aerox 3, 5 and 9 Wireless |
| |
| Ensar S (esensar) 09 Sep 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesMouseController.h"
#define STEELSERIES_AEROX3_WIRELESS_NAME "SteelSeries Aerox 3 Wireless (2.4 GHz wireless mode)"
#define STEELSERIES_AEROX3_WIRELESS_WIRED_NAME "SteelSeries Aerox 3 Wireless (wired mode)"
#define STEELSERIES_AEROX5_WIRELESS_NAME "SteelSeries Aerox 5 Wireless (2.4 GHz wireless mode)"
#define STEELSERIES_AEROX5_WIRELESS_WIRED_NAME "SteelSeries Aerox 5 Wireless (wired mode)"
#define STEELSERIES_AEROX5_DESTINY_WIRELESS_NAME "SteelSeries Aerox 5 Wireless Destiny 2 Edition (2.4 GHz wireless mode)"
#define STEELSERIES_AEROX5_DESTINY_WIRELESS_WIRED_NAME "SteelSeries Aerox 5 Wireless Destiny 2 Edition (wired mode)"
#define STEELSERIES_AEROX5_DIABLO_WIRELESS_NAME "SteelSeries Aerox 5 Wireless Diablo IV Edition (2.4 GHz wireless mode)"
#define STEELSERIES_AEROX5_DIABLO_WIRELESS_WIRED_NAME "SteelSeries Aerox 5 Wireless Diablo IV Edition (wired mode)"
#define STEELSERIES_AEROX9_WIRELESS_NAME "SteelSeries Aerox 9 Wireless (2.4 GHz wireless mode)"
#define STEELSERIES_AEROX9_WIRELESS_WIRED_NAME "SteelSeries Aerox 9 Wireless (wired mode)"
#define STEELSERIES_AEROX_WIRELESS_PACKET_SIZE 64
#define STEELSERIES_AEROX_WIRELESS_TIMEOUT 250
#define STEELSERIES_AEROX_WIRELESS_FLAG 0b01000000
static const steelseries_mouse aerox_3_wireless =
{
{ 0x04, 0x05 },
{
{"Front", 0 },
{"Middle", 1 },
{"Rear", 2 },
}
};
static const steelseries_mouse aerox_9 =
{
{ 0x04, 0x05 },
{
{"Front", 0 },
{"Middle", 1 },
{"Rear", 2 },
{"Reactive", 3 },
}
};
class SteelSeriesAeroxWirelessController: public SteelSeriesMouseController
{
public:
SteelSeriesAeroxWirelessController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name);
~SteelSeriesAeroxWirelessController();
std::string GetFirmwareVersion() override;
steelseries_mouse GetMouse() override;
void Save() override;
void SetLightEffectAll(uint8_t effect) override;
void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
) override;
private:
bool IsWireless();
void SendInit();
void WriteBuffer(uint8_t* buffer);
void SetBrightness(uint8_t brightness);
uint8_t current_brightness;
const char* name;
};
@@ -0,0 +1,131 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesApex3.cpp |
| |
| RGBController for SteelSeries Apex 3 |
| |
| Chris M (Dr_No) 23 Feb 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesApex3.h"
/**------------------------------------------------------------------*\
@name Steel Series Apex Tri Zone Keyboards
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectSteelSeriesApexTZone
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesApex3::RGBController_SteelSeriesApex3(SteelSeriesApex3Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "SteelSeries";
type = DEVICE_TYPE_KEYBOARD;
description = "SteelSeries Apex 3 Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode direct;
direct.name = "Direct";
direct.value = static_cast<int>(APEX3_MODES::DIRECT);
direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
if(controller->SupportsSave())
{
direct.flags |= MODE_FLAG_MANUAL_SAVE;
}
direct.color_mode = MODE_COLORS_PER_LED;
direct.brightness_min = STEELSERIES_APEX3_BRIGHTNESS_MIN;
direct.brightness_max = controller->GetMaxBrightness();
direct.brightness = direct.brightness_max;
modes.push_back(direct);
if(controller->SupportsRainbowWave())
{
mode rainbow;
rainbow.name = "Rainbow Wave";
rainbow.value = static_cast<int>(APEX3_MODES::RAINBOW_WAVE);
rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS;
rainbow.color_mode = MODE_COLORS_NONE;
rainbow.brightness_min = STEELSERIES_APEX3_BRIGHTNESS_MIN;
rainbow.brightness_max = controller->GetMaxBrightness();
rainbow.brightness = rainbow.brightness_max;
modes.push_back(rainbow);
}
SetupZones();
}
RGBController_SteelSeriesApex3::~RGBController_SteelSeriesApex3()
{
delete controller;
}
void RGBController_SteelSeriesApex3::DeviceSaveMode()
{
controller->Save();
}
void RGBController_SteelSeriesApex3::SetupZones()
{
uint8_t led_count = controller->GetLedCount();
zone curr_zone;
curr_zone.name = "Keyboard";
curr_zone.type = ZONE_TYPE_LINEAR;
curr_zone.leds_min = led_count;
curr_zone.leds_max = led_count;
curr_zone.leds_count = led_count;
curr_zone.matrix_map = NULL;
zones.push_back(curr_zone);
for(size_t i = 0; i < curr_zone.leds_count; i++)
{
led zone_led;
zone_led.name = "LED " + std::to_string(i);
leds.push_back(zone_led);
}
SetupColors();
}
void RGBController_SteelSeriesApex3::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesApex3::DeviceUpdateLEDs()
{
controller->SetColor(colors, modes[active_mode].value, modes[active_mode].brightness);
}
void RGBController_SteelSeriesApex3::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesApex3::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesApex3::DeviceUpdateMode()
{
if(modes[active_mode].color_mode == MODE_FLAG_HAS_PER_LED_COLOR)
{
DeviceUpdateLEDs();
}
else
{
controller->SetColor(modes[active_mode].colors, modes[active_mode].value, modes[active_mode].brightness);
}
}
@@ -0,0 +1,41 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesApex3.h |
| |
| RGBController for SteelSeries Apex 3 |
| |
| Chris M (Dr_No) 23 Feb 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesApex3Controller.h"
enum class APEX3_MODES
{
DIRECT = 0,
RAINBOW_WAVE = 1
};
class RGBController_SteelSeriesApex3 : public RGBController
{
public:
RGBController_SteelSeriesApex3(SteelSeriesApex3Controller* controller_ptr);
~RGBController_SteelSeriesApex3();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void DeviceSaveMode();
private:
SteelSeriesApex3Controller* controller;
};
@@ -0,0 +1,49 @@
/*---------------------------------------------------------*\
| SteelSeriesApex3Controller.cpp |
| |
| Driver for SteelSeries Apex 3 |
| |
| Chris M (Dr_No) 23 Feb 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesApex3Controller.h"
#include "StringUtils.h"
SteelSeriesApex3Controller::SteelSeriesApex3Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
SteelSeriesApex3Controller::~SteelSeriesApex3Controller()
{
hid_close(dev);
}
std::string SteelSeriesApex3Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesApex3Controller::GetNameString()
{
return(name);
}
std::string SteelSeriesApex3Controller::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));
}
@@ -0,0 +1,45 @@
/*---------------------------------------------------------*\
| SteelSeriesApex3Controller.h |
| |
| Driver for SteelSeries Apex 3 |
| |
| Chris M (Dr_No) 23 Feb 2022 |
| |
| 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"
#include "SteelSeriesGeneric.h"
#define STEELSERIES_APEX3_BRIGHTNESS_MIN 0x00
#define STEELSERIES_APEX3_HID_TIMEOUT 100
class SteelSeriesApex3Controller
{
public:
SteelSeriesApex3Controller(hid_device* dev_handle, const char* path, std::string dev_name);
virtual ~SteelSeriesApex3Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
steelseries_type GetKeyboardType();
virtual void SetColor(std::vector<RGBColor> colors, uint8_t mode, uint8_t brightness) = 0;
virtual void Save() = 0;
virtual uint8_t GetLedCount() = 0;
virtual uint8_t GetMaxBrightness() = 0;
virtual bool SupportsRainbowWave() = 0;
virtual bool SupportsSave() = 0;
hid_device* dev;
private:
std::string location;
std::string name;
};
@@ -0,0 +1,99 @@
/*---------------------------------------------------------*\
| SteelSeriesApex8ZoneController.cpp |
| |
| Driver for SteelSeries Apex 8 Zone |
| |
| Chris M (Dr_No) 23 Feb 2022 |
| Paul K. Gerke 27 Oct 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <string>
#include "SteelSeriesApex8ZoneController.h"
#include "LogManager.h"
SteelSeriesApex8ZoneController::SteelSeriesApex8ZoneController(hid_device* dev_handle, const char* path, std::string dev_name) : SteelSeriesApex3Controller(dev_handle, path, dev_name)
{
}
SteelSeriesApex8ZoneController::~SteelSeriesApex8ZoneController()
{
}
uint8_t SteelSeriesApex8ZoneController::GetLedCount()
{
return STEELSERIES_8Z_LED_COUNT;
}
uint8_t SteelSeriesApex8ZoneController::GetMaxBrightness()
{
return STEELSERIES_8Z_BRIGHTNESS_MAX;
}
bool SteelSeriesApex8ZoneController::SupportsRainbowWave()
{
return true;
}
bool SteelSeriesApex8ZoneController::SupportsSave()
{
return false;
}
void SteelSeriesApex8ZoneController::Save()
{
/*---------------------------------------------------------*\
| This device does not yet support saving |
\*---------------------------------------------------------*/
}
void SteelSeriesApex8ZoneController::SetBrightness(uint8_t brightness)
{
uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0x23, brightness };
hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE);
current_brightness = brightness;
}
uint8_t SteelSeriesApex8ZoneController::GetBrightness()
{
uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0xA3 };
hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE);
int result = hid_read_timeout(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE, STEELSERIES_APEX3_HID_TIMEOUT);
if (result > 1 && buffer[0x00] == 0xA3)
{
return(buffer[0x01]);
}
return(STEELSERIES_8Z_BRIGHTNESS_MAX);
}
void SteelSeriesApex8ZoneController::SetColor(std::vector<RGBColor> colors, uint8_t mode, uint8_t brightness)
{
uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0x21, 0xFF };
buffer[1] += mode;
for(unsigned int i = 0; i < colors.size(); i++)
{
uint8_t index = i * 3;
buffer[index + 3] = RGBGetRValue(colors[i]);;
buffer[index + 4] = RGBGetGValue(colors[i]);;
buffer[index + 5] = RGBGetBValue(colors[i]);;
}
hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE);
if(current_brightness != brightness)
{
SetBrightness(brightness);
}
}
@@ -0,0 +1,107 @@
/*---------------------------------------------------------*\
| SteelSeriesApex8ZoneController.h |
| |
| Driver for SteelSeries Apex 8 Zone |
| |
| Chris M (Dr_No) 23 Feb 2022 |
| Paul K. Gerke 27 Oct 2022 |
| |
| 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"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesApex3Controller.h"
#define STEELSERIES_8Z_LED_COUNT 8
#define STEELSERIES_8Z_WRITE_PACKET_SIZE 65
#define STEELSERIES_8Z_BRIGHTNESS_MAX 0x10
class SteelSeriesApex8ZoneController : public SteelSeriesApex3Controller
{
public:
SteelSeriesApex8ZoneController(hid_device *dev_handle, const char *path, std::string dev_name);
~SteelSeriesApex8ZoneController();
void SetColor(std::vector<RGBColor> colors, uint8_t mode, uint8_t brightness);
void Save();
uint8_t GetLedCount();
uint8_t GetMaxBrightness();
bool SupportsRainbowWave();
bool SupportsSave();
private:
uint8_t current_brightness;
void SetBrightness(uint8_t brightness);
uint8_t GetBrightness();
};
/*-----------------------------------------------------------------------------------------------*\
# General keyboard behavior overview
- The keyboard does not appear to have persistent memory: Cycling the USB
connection resets the keyboard to a `Rainbow Wave` mode. SteelSeries GG
has to be running to set color patterns, indicating `Direct` mode.
- The brightness settings of the keyboard can be read back by the
SteelSeries GG Software from the keyboard. Changing the brightness with
Mod+F11/F12 moves the slider in the SteelSeries GG software. Also, when
changing the brightness and opening the configuration dialog, the slider
is updated to the value set via Mod+F11/F12.
# Message protocol
The HID-Messages contain a data-packet that is sent with HID-Requests to the
keyboard to change the keyboard's mode. The first byte seems to be a command-ID.
The full message-length is 64 bytes.
Values not explicitly mentioned below are zero-bytes.
## 0x21: Set LED color
0x21 BM R1 G1 B1 R2 G2 B2 ... [up to rgb values for zone 8]
- Bit Mask<br/>A bit mask of LEDs to set where 0xFF sets all LEDs. Setting 2<sup>N</sup>
as 0 will ***not*** set LED N.
- The next sequence of bytes are RGB triplets for each of the 8 LEDs.
Value range from 0 up to 255 for each color value.
## 0x22: Set the keyboard to `Rainbow Wave` mode. Message
0x22 0xFF
- As for 0x21, 0xFF seems to be constant.
## 0x23: Set Brightness
Sets the overall brightness of all color channels. Seems to act as a factor
for the individual RGB values, but can be individually adjusted by the user
through the Mod+F11/F12 key combinations.
0x23 [brightness]
- Brightness values are in the range from 0x00 (dark) to 0x10 (full
brightness)
# Other observed commands/messages of unknown purpose were:
## 0x6C 0x00 0x01 0x01
This triggers some sort of URB_INTERRUPT from USB endpoint .2
reporting back some data however unsure what the data is. It seems
to be 0x6C followed by only zeroes.
## 0xA3
Query brightness?
## 0x90
Best guess "get firmware version" or similar... or some other settings. Again
a complex answer is echoed from endpoint .2 starting with 0x90 and a
few bytes (~8-10) of data.
\*-----------------------------------------------------------------------------------------------*/
@@ -0,0 +1,160 @@
/*---------------------------------------------------------*\
| SteelSeriesApex9Controller.cpp |
| |
| Driver for SteelSeries Apex 9 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesApex9Controller.h"
using namespace std::chrono_literals;
static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //40
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, //60
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x64, 0xE0, //80
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xF0, 0x31, 0x87,
0x88, 0x89, 0x8A, 0x8B, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, //100
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
0x63 };
SteelSeriesApex9Controller::SteelSeriesApex9Controller(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController (dev_handle, path, dev_name)
{
proto_type = type;
}
SteelSeriesApex9Controller::~SteelSeriesApex9Controller()
{
hid_close(dev);
}
void SteelSeriesApex9Controller::SetMode(unsigned char mode /*mode*/, std::vector<RGBColor> /*colors*/ )
{
unsigned char mode_colors[9];
active_mode = mode;
memset(mode_colors, 0x00, sizeof(mode_colors));
}
void SteelSeriesApex9Controller::SetLEDsDirect(std::vector<RGBColor> colors)
{
unsigned char buf[APEX_9_PACKET_LENGTH];
int num_keys = 0;
num_keys = sizeof(keys) / sizeof(*keys);
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0;
buf[0x01] = APEX_9_PACKET_ID_DIRECT;
buf[0x02] = num_keys;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0; i < num_keys; i++)
{
buf[(i*4)+3] = keys[i];
buf[(i*4)+4] = RGBGetRValue(colors[i]);
buf[(i*4)+5] = RGBGetGValue(colors[i]);
buf[(i*4)+6] = RGBGetBValue(colors[i]);
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, APEX_9_PACKET_LENGTH);
}
std::string SteelSeriesApex9Controller::GetSerial()
{
std::string return_string = "";
switch(proto_type)
{
case APEX_9_TKL:
return_string = "64847";
break;
case APEX_9_MINI:
return_string = "64837";
break;
default:
return_string = "Apex 9 GetSerial() error";
}
return(return_string);
}
std::string SteelSeriesApex9Controller::GetVersion()
{
std::string return_string = "Unsupported protocol";
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
int result;
memset(obuf, 0x00, sizeof(obuf));
obuf[0x00] = 0;
obuf[0x01] = 0x90;
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
if(result > 0)
{
std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE);
fwver = fwver.substr(2, fwver.size());
fwver = fwver.c_str();
/*---------------------------------------------*\
| Find 2 periods in string, if found we can |
| form a X.Y.Z revision. |
\*---------------------------------------------*/
std::size_t majorp = fwver.find('.');
if(majorp != std::string::npos)
{
std::size_t minorp = fwver.find('.', majorp+1);
if(minorp != std::string::npos)
{
std::string major = fwver.substr(0, majorp);
std::string minor = fwver.substr(majorp+1, (minorp-majorp-1));
std::string build = fwver.substr(minorp+1);
return_string = "KBD: " + major + "." + minor + "." + build;
}
}
}
return(return_string);
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void SteelSeriesApex9Controller::SelectProfile(unsigned char profile)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer, set up packet and send |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0;
buf[0x01] = 0x89;
buf[0x02] = profile;
hid_send_feature_report(dev, buf, 65);
}
@@ -0,0 +1,38 @@
/*---------------------------------------------------------*\
| SteelSeriesApex9Controller.h |
| |
| Driver for SteelSeries Apex 9 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesApexBaseController.h"
enum
{
APEX_9_PACKET_ID_DIRECT = 0x40, /* Direct mode */
APEX_9_PACKET_LENGTH = 513,
};
class SteelSeriesApex9Controller : public SteelSeriesApexBaseController
{
public:
SteelSeriesApex9Controller(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name);
~SteelSeriesApex9Controller();
void SetMode(unsigned char mode, std::vector<RGBColor> colors);
void SetLEDsDirect(std::vector<RGBColor> colors);
std::string GetSerial() override;
std::string GetVersion() override;
private:
void SelectProfile(unsigned char profile);
};
@@ -0,0 +1,152 @@
/*---------------------------------------------------------*\
| SteelSeriesApexBaseController.cpp |
| |
| Driver base for SteelSeries Apex |
| |
| Florian Heilmann (FHeilmann) 19 Oct 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "SteelSeriesApexBaseController.h"
#include <algorithm>
SteelSeriesApexBaseController::SteelSeriesApexBaseController(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
SteelSeriesApexBaseController::~SteelSeriesApexBaseController()
{
}
std::string SteelSeriesApexBaseController::GetLocation()
{
return("HID: " + location);
};
std::string SteelSeriesApexBaseController::GetName()
{
return(name);
}
/*---------------------------------------------------------*\
| Gen 1 Apex Pro stores the unit serial number in firmware. |
| The first 5 digits determine the region of the keyboard. |
| This is not the case for Gen 3, call to this function |
| will be ignored. |
\*---------------------------------------------------------*/
std::string SteelSeriesApexBaseController::GetSerial()
{
std::string return_string = "";
if(proto_type == APEX && kbd_quirk == APEX_GEN1)
{
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
int result;
memset(obuf, 0x00, sizeof(obuf));
obuf[0x00] = 0;
obuf[0x01] = 0xFF;
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
/*-------------------------------------------------*\
| Only the first 19 bytes are of value |
\*-------------------------------------------------*/
if(result > 0)
{
std::string serialnum(ibuf, ibuf+19);
return_string = serialnum;
}
}
return(return_string);
}
std::string ExtractVersion(std::string version_string)
{
/*---------------------------------------------*\
| Find 2 periods in string, if found we can |
| form a X.Y.Z revision. |
\*---------------------------------------------*/
std::size_t majorp = version_string.find('.');
if(majorp != std::string::npos)
{
std::size_t minorp = version_string.find('.', majorp+1);
if(minorp != std::string::npos)
{
std::string major = version_string.substr(0, majorp);
std::string minor = version_string.substr(majorp+1, (minorp-majorp-1));
std::string build = version_string.substr(minorp+1);
return major + "." + minor + "." + build;
}
}
return "";
}
std::string SteelSeriesApexBaseController::GetVersion()
{
std::string return_string = "Unsupported protocol";
if(proto_type == APEX)
{
/*-------------------------------------------------*\
| Gen 1 & 2 Apex Pro report KBD and LED firmware |
| Gen 3 only reports the KBD firmware, ignoring |
| requests to read the LED version |
\*-------------------------------------------------*/
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
int result;
memset(obuf, 0x00, sizeof(obuf));
obuf[0x00] = 0;
obuf[0x01] = 0x90;
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
if(result > 0)
{
std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE);
fwver.erase(std::remove(fwver.begin(), fwver.end(), '\0'), fwver.end());
/*---------------------------------------------*\
| Apex Pro Gen 3 needs the first char dropped |
\*---------------------------------------------*/
if(kbd_quirk == APEX_GEN3)
{
fwver.erase(0,1);
}
return_string = "KBD: " + ExtractVersion(fwver);
}
/*-------------------------------------------------*\
| Clear and reuse buffer |
\*-------------------------------------------------*/
if(kbd_quirk != APEX_GEN3)
{
memset(ibuf, 0x00, sizeof(ibuf));
obuf[0x02] = 0x01;
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 10);
if(result > 0)
{
std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE);
fwver.erase(std::remove(fwver.begin(), fwver.end(), '\0'), fwver.end());
fwver = fwver.c_str();
return_string = return_string + " / LED: " + ExtractVersion(fwver);
}
}
}
return(return_string);
}
@@ -0,0 +1,59 @@
/*---------------------------------------------------------*\
| SteelSeriesApexBaseController.h |
| |
| Driver base for SteelSeries Apex |
| |
| Florian Heilmann (FHeilmann) 19 Oct 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <string>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#define STEELSERIES_PACKET_IN_SIZE 64
#define STEELSERIES_PACKET_OUT_SIZE STEELSERIES_PACKET_IN_SIZE + 1
/*-------------------------------------------------*\
| Gen 1: 2019-22 models (all FW) & 2023 FW < 1.19.7 |
| Gen 2: 2023 models with FW >= 1.19.7 |
| Gen 3: 2025+ and may feature Gen 3 in the name |
\*-------------------------------------------------*/
typedef enum
{
APEX_GEN1 = 0x00,
APEX_GEN2 = 0x01,
APEX_GEN3 = 0x02,
} protocol_quirk;
class SteelSeriesApexBaseController
{
public:
SteelSeriesApexBaseController(hid_device* dev_handle, const char* path, std::string dev_name);
virtual ~SteelSeriesApexBaseController();
std::string GetLocation();
std::string GetName();
virtual std::string GetSerial();
virtual std::string GetVersion();
virtual void SetMode(unsigned char mode, std::vector<RGBColor> colors) = 0;
virtual void SetLEDsDirect(std::vector<RGBColor> colors) = 0;
steelseries_type proto_type;
protected:
hid_device* dev;
unsigned char active_mode;
std::string location;
std::string name;
protocol_quirk kbd_quirk;
};
@@ -0,0 +1,160 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesApex.cpp |
| |
| RGBController for SteelSeries Apex 7 |
| |
| Eric Samuelson (edbgon) 05 Jul 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_SteelSeriesApex.h"
#include "SteelSeriesApexRegions.h"
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX
};
static const unsigned int zone_sizes[] =
{
sizeof(led_names)/sizeof(char*),
};
/**------------------------------------------------------------------*\
@name Steel Series APEX
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectSteelSeriesApex,DetectSteelSeriesApexM
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesApex::RGBController_SteelSeriesApex(SteelSeriesApexBaseController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetName();
vendor = "SteelSeries";
type = DEVICE_TYPE_KEYBOARD;
description = "SteelSeries Apex RGB Device";
location = controller->GetLocation();
serial = controller->GetSerial();
version = controller->GetVersion();
proto_type = controller->proto_type;
mode Direct;
Direct.name = "Direct";
Direct.value = 0x00;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_SteelSeriesApex::~RGBController_SteelSeriesApex()
{
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
free(zones[zone_index].matrix_map->map);
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_SteelSeriesApex::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
/*---------------------------------------------------------*\
| The first 5 chars are the SKU which we need to determine |
| the region. |
\*---------------------------------------------------------*/
std::string sku = serial.substr(0, 5);
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->map = (unsigned int *) malloc(matrix_mapsize*sizeof(unsigned int));
if((proto_type == APEX) || (proto_type == APEX_M) || (proto_type == APEX_9_TKL) || (proto_type == APEX_9_MINI))
{
SetSkuRegion(*new_zone.matrix_map, sku);
}
}
else
{
new_zone.matrix_map = NULL;
}
if((proto_type == APEX) || (proto_type == APEX_M) || (proto_type == APEX_9_TKL) || (proto_type == APEX_9_MINI))
{
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
total_led_count += zone_sizes[zone_idx];
}
zones.push_back(new_zone);
};
SetSkuLedNames(leds, sku, total_led_count);
SetupColors();
}
void RGBController_SteelSeriesApex::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesApex::DeviceUpdateLEDs()
{
last_update_time = std::chrono::steady_clock::now();
controller->SetLEDsDirect(colors);
}
void RGBController_SteelSeriesApex::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesApex::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesApex::DeviceUpdateMode()
{
std::vector<RGBColor> temp_colors;
controller->SetMode(modes[active_mode].value, temp_colors);
}
@@ -0,0 +1,39 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesApex.h |
| |
| RGBController for SteelSeries Apex 7 |
| |
| Eric Samuelson (edbgon) 05 Jul 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "SteelSeriesApexBaseController.h"
#include "SteelSeriesGeneric.h"
class RGBController_SteelSeriesApex : public RGBController
{
public:
RGBController_SteelSeriesApex(SteelSeriesApexBaseController* controller_ptr);
~RGBController_SteelSeriesApex();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
SteelSeriesApexBaseController* controller;
steelseries_type proto_type;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,318 @@
/*---------------------------------------------------------*\
| SteelSeriesApexController.cpp |
| |
| Driver for SteelSeries Apex Keyboards |
| |
| New driver based on SignalRGB Plugins |
| https://gitlab.com/signalrgb/signal-plugins/ |
| |
| Eric Samuelson (edbgon) 05 Jul 2020 |
| Filipe S. (filipesn) 5 Jan 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <cstdio>
#include "SteelSeriesApexController.h"
#include "LogManager.h"
using namespace std::chrono_literals;
#define FIRMWARE_REQ_LEN 645
static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //40
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, //60
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x64, 0xE0, //80
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xF0, 0x31, 0x87,
0x88, 0x89, 0x8A, 0x8B, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, //100
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
0x63, 0xFB };
SteelSeriesApexController::SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name)
{
proto_type = type;
kbd_quirk = APEX_GEN1;
SendInitialization();
}
SteelSeriesApexController::~SteelSeriesApexController()
{
/*-----------------------------------------------------*\
| Gen 3 models must be explicitly cleared for on-board |
| config selection to apply without power cycling after |
| OpenRGB shuts down. |
\*-----------------------------------------------------*/
if(kbd_quirk == APEX_GEN3)
{
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
memset(obuf, 0x00, sizeof(obuf));
obuf[0x00] = 0;
obuf[0x01] = APEX_GEN3_PACKET_CLEAR_LIGHTING;
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
}
hid_close(dev);
}
void SteelSeriesApexController::SetMode
(
unsigned char mode,
std::vector<RGBColor> /*colors*/
)
{
unsigned char mode_colors[9];
active_mode = mode;
memset(mode_colors, 0x00, sizeof(mode_colors));
}
void SteelSeriesApexController::SetLEDsDirect(std::vector<RGBColor> colors)
{
unsigned char buf[643];
int num_keys = 0;
unsigned char packet_id = APEX_PACKET_ID_DIRECT;
num_keys = sizeof(keys) / sizeof(*keys);
if(kbd_quirk >= APEX_GEN2)
{
struct hid_device_info* info = hid_get_device_info(dev);
/*-------------------------------------------------*\
| Apparently Gen 3 wireless models reuse this |
| protocol, make sure to place their PID here and |
| further below when developing. |
\*-------------------------------------------------*/
if(info && (info->product_id == 0x1630 || info->product_id == 0x1632
|| info->product_id == 0x162C || info->product_id == 0x162D
|| info->product_id == 0x1644 || info->product_id == 0x1646))
{
packet_id = APEX_2023_PACKET_ID_DIRECT_WIRELESS;
}
else
{
packet_id = APEX_2023_PACKET_ID_DIRECT;
}
}
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0;
buf[0x01] = packet_id;
buf[0x02] = kbd_quirk ? (unsigned char)colors.size() : num_keys;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0; i < num_keys; i++)
{
buf[(i*4)+3] = keys[i];
buf[(i*4)+4] = RGBGetRValue(colors[i]);
buf[(i*4)+5] = RGBGetGValue(colors[i]);
buf[(i*4)+6] = RGBGetBValue(colors[i]);
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 643);
}
/*---------------------------------------------------------*\
| Private packet sending functions. |
\*---------------------------------------------------------*/
void SteelSeriesApexController::SelectProfile
(
unsigned char profile
)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer, set up packet and send |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0;
buf[0x01] = 0x89;
buf[0x02] = profile;
hid_send_feature_report(dev, buf, 65);
}
void SteelSeriesApexController::SendInitialization()
{
unsigned char buf[FIRMWARE_REQ_LEN];
unsigned char read_buf[65];
int res = 0;
char version_str[65] = "Unknown";
struct hid_device_info* info = hid_get_device_info(dev);
unsigned short pid = (info) ? info->product_id : 0;
/*-----------------------------------------------------*\
| Firmware check for TKL 2023 |
\*-----------------------------------------------------*/
if(pid == 0x1628)
{
/*-------------------------------------------------*\
| Zero out buffer |
\*-------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x00;
buf[0x01] = 0x90;
/*-------------------------------------------------*\
| Send packet |
\*-------------------------------------------------*/
hid_write(dev, buf, 65);
/*-------------------------------------------------*\
| Read Response |
\*-------------------------------------------------*/
memset(read_buf, 0x00, sizeof(read_buf));
res = hid_read_timeout(dev, read_buf, sizeof(read_buf), 200);
/*-------------------------------------------------*\
| Firmware Check |
\*-------------------------------------------------*/
if(res > 2 && read_buf[0] == 0x90)
{
int major = 0, minor = 0, patch = 0;
char* fw_ptr = (char*)&read_buf[2];
snprintf(version_str, sizeof(version_str), "%s", fw_ptr);
int count = sscanf(version_str, "%d.%d.%d", &major, &minor, &patch);
if(count == 3)
{
/*-----------------------------------------*\
| Currently set to 1.19.7 or newer. |
\*-----------------------------------------*/
if(major > 1)
{
kbd_quirk = APEX_GEN2;
}
else if(major == 1)
{
if(minor > 19)
{
kbd_quirk = APEX_GEN2;
}
else if(minor == 19 && patch >= 7)
{
kbd_quirk = APEX_GEN2;
}
}
}
}
}
/*-----------------------------------------------------*\
| Apparently Gen 3 models reuse this protocol, make |
| sure to place their PID here and further above for |
| wireless when developing. |
\*-----------------------------------------------------*/
else if(pid == 0x1630 || pid == 0x1632
|| pid == 0x162C || pid == 0x162D
|| pid == 0x1642 || pid == 0x1644 || pid == 0x1646)
{
kbd_quirk = APEX_GEN3;
}
/*-----------------------------------------------------*\
| Send Initialization packet on new protocol. |
\*-----------------------------------------------------*/
if(kbd_quirk >= APEX_GEN2)
{
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x00;
buf[0x01] = APEX_2023_PACKET_ID_INIT;
hid_send_feature_report(dev, buf, APEX_2023_PACKET_LENGTH);
LOG_DEBUG("[%s] Using Apex 2023 protocol. FW: %s", name.c_str(), version_str);
}
else
{
LOG_DEBUG("[%s] Using Apex Legacy protocol. FW: %s", name.c_str(), version_str);
}
}
std::string SteelSeriesApexController::GetSerial()
{
/*-------------------------------------------------*\
| Gen 3 doesn't expose the serial number in |
| firmware. A region code is instead set by the |
| user and subsequently read back. This region code |
| is used by all 5 on-board configs. |
| For consistency with other Apex keyboards, this |
| region code in combination with the PID is mapped |
| to an approximate product number as the region |
| patch logic from that point is identical. |
| The product number used may not be an exact match |
| for the keyboard but should reflect the form |
| factor, region and RGB layout |
\*-------------------------------------------------*/
if(kbd_quirk >= APEX_GEN2)
{
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
int result;
struct hid_device_info* info = hid_get_device_info(dev);
unsigned short pid = (info) ? info->product_id : 0;
memset(obuf, 0x00, sizeof(obuf));
if(pid == 0x1642)
{
obuf[0x00] = 0;
obuf[0x01] = 0xF5;
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
if(result > 3 && ibuf[0] == 0xF5)
{
switch(ibuf[2])
{
case 0x1:
return "64740";
break;
case 0x3:
return "64741";
break;
case 0x4:
return "64743";
break;
case 0x6:
return "64744";
break;
case 0xA:
return "64742";
break;
case 0xD:
return "64745";
break;
default:
break;
}
}
}
return "64865";
}
return SteelSeriesApexBaseController::GetSerial();
}
@@ -0,0 +1,59 @@
/*---------------------------------------------------------*\
| SteelSeriesApexController.cpp |
| |
| Driver for SteelSeries Apex Keyboards |
| |
| New driver based on SignalRGB Plugins |
| https://gitlab.com/signalrgb/signal-plugins/ |
| |
| Eric Samuelson (edbgon) 05 Jul 2020 |
| Filipe S. (filipesn) 5 Jan 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesApexBaseController.h"
enum
{
APEX_PACKET_ID_DIRECT = 0x3a, /* Direct mode */
APEX_2023_PACKET_ID_DIRECT = 0x40, /* New Wired Direct mode */
APEX_2023_PACKET_ID_DIRECT_WIRELESS = 0x61, /* New Wireless Direct mode */
APEX_2023_PACKET_ID_INIT = 0x4B, /* New Initialization */
APEX_2023_PACKET_LENGTH = 643,
APEX_GEN3_PACKET_CLEAR_LIGHTING = 0x41,
};
class SteelSeriesApexController : public SteelSeriesApexBaseController
{
public:
SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name);
~SteelSeriesApexController();
void SetMode
(
unsigned char mode,
std::vector<RGBColor> colors
);
void SetLEDsDirect(std::vector<RGBColor> colors);
std::string GetSerial() override;
private:
void SelectProfile
(
unsigned char profile
);
void SendInitialization();
};
@@ -0,0 +1,128 @@
/*---------------------------------------------------------*\
| SteelSeriesApexMController.cpp |
| |
| Driver for SteelSeries Apex M750 |
| |
| Florian Heilmann (FHeilmann) 12 Oct 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesApexMController.h"
#define SS_APEX_M_PACKET_SIZE 513
#define NA 0xFF
static unsigned int keys_m[] =
{
/* LCTRL LWIN LALT XXX SPACE XXX XXX XXX XXX RALT RWIN FNC RCTRL XXX XXX LEFT DOWN RIGHT XXX #0 XXX #. */
79, 82, 81, NA, 40, NA, NA, NA, NA, 85, 86, 87, 83, NA, NA, 75, 76, 74, NA, 104, NA, 105,
/* LSHFT Z X C V B N M , . / XXX RSHFT XXX XXX XXX UP XXX #1 #2 #3 #ENTR */
80, 25, 23, 2, 21, 1, 13, 12, 49, 50, 51, NA, 84, NA, NA, NA, 77, NA, 95, 96, 97, 94,
/* CAPLK A S D F G H J K L ; ' XXX ENTER XXX XXX XXX XXX #4 #5 #6 XXX */
52, 0, 18, 3, 5, 6, 7, 9, 10, 11, 46, 47, NA, 36, NA, NA, NA, NA, 98, 99, 100, NA,
/* TAB Q W E R T Y U I O P [ ] XXX \ DELTE END PGDN #7 #8 #9 #+ */
39, 16, 22, 4, 17, 19, 24, 20, 8, 14, 15, 43, 44, NA, 88, 71, 72, 73, 101, 102, 103, 93,
/* ` 1 2 3 4 5 6 7 8 9 0 - = XXX BKSPC INSRT HOME PGUP NUMLK #/ #* #- */
48, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 41, 42, NA, 38, 68, 69, 70, 89, 90, 91, 92,
/* ESC F1 F2 F3 F4 XXX F5 F6 F7 F8 XXX F9 F10 F11 F12 PRTSC SCRLK PAUSE XXX XXX XXX XXX */
37, 53, 54, 55, 56, NA, 57, 58, 59, 60, NA, 61, 62, 63, 64, 65, 66, 67, NA, NA, NA, NA
};
SteelSeriesApexMController::SteelSeriesApexMController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name)
{
proto_type = type;
EnableLEDControl();
}
SteelSeriesApexMController::~SteelSeriesApexMController()
{
hid_close(dev);
}
void SteelSeriesApexMController::EnableLEDControl()
{
unsigned char buf[SS_APEX_M_PACKET_SIZE] = { 0x00 };
buf[0x00] = 0x00;
buf[0x01] = 0x00;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
buf[0x04] = 0x01;
buf[0x05] = 0x00;
buf[0x06] = 0x85;
hid_send_feature_report(dev, buf, SS_APEX_M_PACKET_SIZE);
buf[0x00] = 0x00;
buf[0x01] = 0x00;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
buf[0x04] = 0x03;
buf[0x05] = 0x01;
buf[0x06] = 0x00;
buf[0x07] = 0xff;
hid_send_feature_report(dev, buf, SS_APEX_M_PACKET_SIZE);
buf[0x00] = 0x00;
buf[0x01] = 0x00;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
buf[0x04] = 0x01;
buf[0x05] = 0x00;
buf[0x06] = 0x85;
hid_send_feature_report(dev, buf, SS_APEX_M_PACKET_SIZE);
}
void SteelSeriesApexMController::SetMode(unsigned char /*mode*/, std::vector<RGBColor> /*colors*/)
{
}
void SteelSeriesApexMController::SetLEDsDirect(std::vector<RGBColor> colors)
{
unsigned char buf[SS_APEX_M_PACKET_SIZE] = { 0x00 };
int num_keys = sizeof(keys_m) / sizeof(*keys_m);
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
buf[0x01] = 0x00;
buf[0x02] = 0x00;
buf[0x03] = 0x01;
buf[0x04] = 0x8e;
buf[0x05] = 0x01;
buf[0x06] = 0x03;
buf[0x07] = 0x06;
buf[0x08] = 0x16;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for (int i = 0; i < num_keys; i++)
{
if (keys_m[i] == NA)
{
buf[i * 3 + 9] = 0xFF;
buf[i * 3 + 10] = 0x32;
buf[i * 3 + 11] = 0x00;
}
else
{
buf[(i * 3) + 9] = RGBGetRValue(colors[keys_m[i]]);
buf[(i * 3) + 10] = RGBGetGValue(colors[keys_m[i]]);
buf[(i * 3) + 11] = RGBGetBValue(colors[keys_m[i]]);
}
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, SS_APEX_M_PACKET_SIZE);
}
@@ -0,0 +1,40 @@
/*---------------------------------------------------------*\
| SteelSeriesApexMController.cpp |
| |
| Driver for SteelSeries Apex M750 |
| |
| Florian Heilmann (FHeilmann) 12 Oct 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesApexBaseController.h"
class SteelSeriesApexMController : public SteelSeriesApexBaseController
{
public:
SteelSeriesApexMController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name);
~SteelSeriesApexMController();
void SetMode
(
unsigned char mode,
std::vector<RGBColor> colors
);
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
void EnableLEDControl();
void SelectProfile
(
unsigned char profile
);
};
@@ -0,0 +1,650 @@
/*---------------------------------------------------------*\
| SteelSeriesApexRegions.h |
| |
| Region settings for SteelSeries Apex 5/7/Pro and TKL |
| |
| Joseph East (dripsnek) 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <map>
#include <string>
#include <vector>
#include "RGBController_SteelSeriesApex.h"
#include "RGBControllerKeyNames.h"
#define NA 0xFFFFFFFF
/*----------------------------------------------------------------------*\
| Steelseries keyboards share a library of 111 standard keys plus extra |
| ambients across all physical form factors. No keyboard has every key |
| fitted but the same format packet can be sent regardless of model and |
| the firmware will pick the keys applicable to it, ignoring the rest. |
| The complication comes in commuicating this to the OpenRGB GUI as |
| different key layouts change the LED positions, additionally some |
| labels / scancodes are overloaded based on the language which clashes |
| with the OpenRGB defaults. In order to account for this a base SKU |
| (ANSI) is assumed which is transformed into a regional SKU when device |
| detection returns a known product number acquired from the keyboard |
\*----------------------------------------------------------------------*/
#define MATRIX_HEIGHT 6
#define MATRIX_WIDTH 22
/*-------------------------------------------------------*\
| Default keymap where values are indicies into led_names |
| or NA for no key. |
\*-------------------------------------------------------*/
#define MATRIX_MAP_ANSI\
{ { 37, NA, 53, 54, 55, 56, NA, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, NA, NA, NA, NA },\
{ 48, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 41, 42, 38, NA, 68, 69, 70, 94, 95, 96, 97 },\
{ 39, NA, 16, 22, 4 , 17, 19, 24, 20, 8 , 14, 15, 43, 44, 88, 71, 72, 73, 106, 107, 108, 98 },\
{ 52, NA, 0 , 18, 3 , 5 , 6 , 7 , 9 , 10, 11, 46, 47, 36, NA, NA, NA, NA, 103, 104, 105, NA },\
{ 80, NA, 25, 23, 2 , 21, 1 , 13, 12, 49, 50, 51, 84, NA, NA, NA, 77, NA, 100, 101, 102, 99 },\
{ 79, 82, 81, NA, NA, NA, NA, 40, NA, NA, NA, 85, 86, 87, 83, 75, 76, 74, 109, NA, 110, NA } };
static const int matrix_mapsize = MATRIX_HEIGHT * MATRIX_WIDTH;
/*-------------------------------------------------------*\
| These map to the values defined in the keys array at |
| SteelSeriesApexController |
\*-------------------------------------------------------*/
static const char* led_names[] =
{
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_POUND,
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_ISO_BACK_SLASH,
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_RIGHT_WINDOWS,
KEY_EN_RIGHT_FUNCTION,
KEY_EN_ANSI_BACK_SLASH,
KEY_JP_RO,
KEY_JP_KANA,
KEY_JP_YEN,
KEY_JP_HENKAN,
KEY_JP_MUHENKAN,
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_MEDIA_PLAY_PAUSE
};
struct matrix_region_patch
{
int row;
int column;
unsigned int value;
};
struct sku_patch
{
std::vector<matrix_region_patch> base_patch;
std::vector<matrix_region_patch> region_patch;
std::map<int, std::string> key_patch;
};
/*-----------------------------------------------*\
| There are two types of patches, a SKU may |
| use one, both or none. The first type are |
| region patches which modify the location of |
| a logical key (in terms of RGB) based on the |
| scancode emitted by the physical key on the |
| keyboard. This is the most important as it |
| impacts what keys are lit in terms of RGB. |
| |
| The second type are keyname lookups |
| where the face of the key may be different |
| between SKUs but the scancode is the same, this |
| is for convenience of the LED view in the GUI. |
| |
| Each SKU has up to 3 operations performed on |
| it. A generic TKL region patch (where req'd) |
| the SKU region patch then a keyname lookup in |
| that order. |
\*-----------------------------------------------*/
/*-----------------------------------------------*\
| Region patches are structs consisting of |
| {row, column, value} where row and column are |
| 0 indexed into the logical key layout defined |
| by MATRIX_MAP_ANSI. This array closely matches |
| the physical layout of the keyboard. Value is |
| an index into the led_names array and refers |
| to the replacement character which should exist |
| at that location, or NA for no character. When |
| the SetSkuRegion function is called, the |
| contents of MATRIX_MAP_ANSI populate a local |
| array, then based on the SKU argument the |
| specific patches are applied to the local copy |
| before being passed to the controller. |
\*-----------------------------------------------*/
static const std::vector<matrix_region_patch> apex_jp_region_patch =
{
{1, 13, 91},
{1, 14, 38},
{2, 14, 36},
{3, 13, 45},
{4, 12, 89},
{4, 13, 84},
{5, 3, 93},
{5, 10, 92},
{5, 11, 90},
{5, 12, 85},
};
static const std::vector<matrix_region_patch> apex_iso_region_patch =
{
{2, 14, 36},
{3, 13, 45},
{4, 1, 78},
};
/*-----------------------------------------------*\
| The TKL region patch is common for all TKL SKUs |
\*-----------------------------------------------*/
static const std::vector<matrix_region_patch> apex_tkl_us_region_patch =
{
{0, 15, NA},
{0, 16, NA},
{0, 17, 111},
{1, 18, NA},
{1, 19, NA},
{1, 20, NA},
{1, 21, NA},
{2, 18, NA},
{2, 19, NA},
{2, 20, NA},
{2, 21, NA},
{3, 18, NA},
{3, 19, NA},
{3, 20, NA},
{4, 18, NA},
{4, 19, NA},
{4, 20, NA},
{4, 21, NA},
{5, 18, NA},
{5, 20, NA},
};
/*-------------------------------------------------*\
| The Mini region patch is common for all Mini SKUs |
\*-------------------------------------------------*/
static const std::vector<matrix_region_patch> apex_mini_us_region_patch =
{
{0, 0, NA},
{0, 2, NA},
{0, 3, NA},
{0, 4, NA},
{0, 5, NA},
{0, 7, NA},
{0, 8, NA},
{0, 9, NA},
{0, 10, NA},
{0, 11, NA},
{0, 12, NA},
{0, 13, NA},
{0, 14, NA},
{0, 15, NA},
{0, 16, NA},
{0, 17, NA},
{1, 0, 37},
{1, 15, NA},
{1, 16, NA},
{1, 17, NA},
{1, 18, NA},
{1, 19, NA},
{1, 20, NA},
{1, 21, NA},
{2, 15, NA},
{2, 16, NA},
{2, 17, NA},
{2, 18, NA},
{2, 19, NA},
{2, 20, NA},
{2, 21, NA},
{3, 18, NA},
{3, 19, NA},
{3, 20, NA},
{4, 16, NA},
{4, 18, NA},
{4, 19, NA},
{4, 20, NA},
{4, 21, NA},
{5, 15, NA},
{5, 16, NA},
{5, 17, NA},
{5, 18, NA},
{5, 20, NA},
};
/*-----------------------------------------------*\
| Keyname lookups change the character displayed |
| on the LED view GUI by overriding the value |
| associated with the index in led_names. |
\*-----------------------------------------------*/
static const std::map<int, std::string> apex_jp_keyname_lookup =
{
{42, KEY_JP_CHEVRON},
{43, KEY_JP_AT},
{44, KEY_EN_LEFT_BRACKET},
{45, KEY_EN_RIGHT_BRACKET},
{47, KEY_JP_COLON},
{48, KEY_JP_EJ},
{84, KEY_EN_RIGHT_SHIFT},
{36, KEY_EN_ISO_ENTER},
};
static const std::map<int, std::string> apex_uk_keyname_lookup =
{
{36, KEY_EN_ISO_ENTER},
};
static const std::map<int, std::string> apex_nor_keyname_lookup =
{
{36, KEY_EN_ISO_ENTER},
{41, KEY_NORD_PLUS_QUESTION},
{42, KEY_NORD_ACUTE_GRAVE},
{43, KEY_NORD_AAL},
{44, KEY_NORD_DOTS_CARET},
{45, KEY_NORD_QUOTE},
{46, KEY_NORD_A_OE},
{47, KEY_NORD_O_AE},
{48, KEY_NORD_HALF},
{51, KEY_NORD_HYPHEN},
{78, KEY_NORD_ANGLE_BRACKET},
};
static const std::map<std::string, sku_patch> patch_lookup =
{
/*----------------------------------------------------------*\
| All TKL keyboards must use apex_tkl_us_region_patch as the |
| base patch, then apply the regional patch on top (if any). |
\*----------------------------------------------------------*/
/*---------------------*\
| APEX Pro Gen 3 |
\*---------------------*/
{ "64660", { {}, {}, {} }},
{ "64740", { apex_tkl_us_region_patch, {}, {} }},
{ "64742", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64743", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64745", { apex_tkl_us_region_patch, apex_jp_region_patch, apex_jp_keyname_lookup }},
{ "64871", { apex_tkl_us_region_patch, {}, {} }},
{ "64913", { apex_mini_us_region_patch, {}, {} }},
/*---------------------*\
| APEX Pro Gen 2 / 2023 |
\*---------------------*/
{ "64856", { apex_tkl_us_region_patch, {}, {} }},
{ "64865", { apex_tkl_us_region_patch, {}, {} }},
{ "64820", { apex_mini_us_region_patch, {}, {} }},
{ "64842", { apex_mini_us_region_patch, {}, {} }},
/*--------*\
| APEX Pro |
\*--------*/
{ "64739", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64738", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64737", { apex_tkl_us_region_patch, apex_jp_region_patch, apex_jp_keyname_lookup }},
{ "64856", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64734", { apex_tkl_us_region_patch, {}, {} }},
{ "64631", { {}, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64634", { {}, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64629", { {}, apex_jp_region_patch, apex_jp_keyname_lookup }},
/*--------*\
| APEX 9 |
\*--------*/
{ "64847", { apex_tkl_us_region_patch, {}, {} }},
{ "64848", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64849", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_nor_keyname_lookup }},
// { "64850", { apex_tkl_us_region_patch, apex_iso_region_patch, {} }},
// { "64851", { apex_tkl_us_region_patch, apex_iso_region_patch, {} }},
{ "64837", { apex_mini_us_region_patch, {}, {} }},
/*--------*\
| APEX 7 |
\*--------*/
{ "64646", { apex_tkl_us_region_patch, {}, {} }},
{ "64758", { apex_tkl_us_region_patch, {}, {} }},
{ "64747", { apex_tkl_us_region_patch, {}, {} }},
{ "64652", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64760", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64749", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64651", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64649", { apex_tkl_us_region_patch, apex_jp_region_patch, apex_jp_keyname_lookup }},
{ "64756", { apex_tkl_us_region_patch, apex_jp_region_patch, apex_jp_keyname_lookup }},
{ "64635", { {}, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64778", { {}, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64788", { {}, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64641", { {}, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64775", { {}, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64787", { {}, apex_iso_region_patch, apex_nor_keyname_lookup }},
{ "64639", { {}, apex_jp_region_patch, apex_jp_keyname_lookup }},
{ "64772", { {}, apex_jp_region_patch, apex_jp_keyname_lookup }},
/*--------*\
| APEX 5 |
\*--------*/
{ "64534", { {}, apex_iso_region_patch, apex_uk_keyname_lookup }},
{ "64537", { {}, apex_jp_region_patch, apex_jp_keyname_lookup }},
{ "64533", { {}, apex_iso_region_patch, apex_nor_keyname_lookup }},
};
static void SetSkuRegion (matrix_map_type& input, std::string& sku)
{
std::map<std::string, sku_patch>::const_iterator it = patch_lookup.find(sku);
unsigned int local_matrix [MATRIX_HEIGHT][MATRIX_WIDTH] = MATRIX_MAP_ANSI;
input.height = MATRIX_HEIGHT;
input.width = MATRIX_WIDTH;
if(it != patch_lookup.end())
{
for(std::size_t i = 0; i < it->second.base_patch.size(); i++)
{
local_matrix[it->second.base_patch[i].row][it->second.base_patch[i].column] = it->second.base_patch[i].value;
}
for(std::size_t i = 0; i < it->second.region_patch.size(); i++)
{
local_matrix[it->second.region_patch[i].row][it->second.region_patch[i].column] = it->second.region_patch[i].value;
}
}
memcpy(input.map, (unsigned int *)local_matrix, sizeof(unsigned int)*MATRIX_HEIGHT*MATRIX_WIDTH);
}
static void SetSkuLedNames (std::vector<led>& input, std::string& sku, unsigned int led_count)
{
std::map<std::string, sku_patch>::const_iterator it = patch_lookup.find(sku);
for(unsigned int led_idx = 0; led_idx < led_count; led_idx++)
{
led new_led;
if(it != patch_lookup.end())
{
std::map<int, std::string>::const_iterator jt = it->second.key_patch.find(led_idx);
if(jt == it->second.key_patch.end())
{
new_led.name = led_names[led_idx];
}
else if(jt != it->second.key_patch.end())
{
new_led.name = jt->second;
}
}
else
{
new_led.name = led_names[led_idx];
}
input.push_back(new_led);
}
}
/*-----------------------------------------------------------*\
| SKU codes for all known Apex Pro / 7 / 5 & TKL variant |
| keyboards as at Janauary 2022. Generated by cross-checking |
| store listings aginst Steelseries website. |
| Updated 2026 for Apex 9 and Pro Gen 2 & Gen 3 |
| The product Pro Mini seem to belong to Gen 2 |
| |
| -- APEX PRO Gen 3 -- |
| |
| "64660", // US |
| |
| >> APEX PRO TKL Gen 3 |
| |
| "64740", // US TKL Black |
| "64741", // UK TKL Black |
| "64742", // Nordic TKL Black |
| "64743", // German TKL Black |
| "64744", // French TKL Black |
| "64745", // Japanese TKL Black |
| |
| >> APEX PRO TKL Wireless Gen 3 |
| |
| "64871", // US TKL Black Wireless |
| "64876", // Japanese TKL Black Wireless |
| |
| >> APEX PRO Mini Gen 3 |
| |
| "64913", // US Mini |
| |
| -- APEX PRO Gen2 / 2023 -- |
| |
| >> APEX PRO TKL Gen 2 / 2023 |
| |
| "64856", // US TKL |
| "64861", // Japanese TKL |
| |
| >> APEX PRO TKL Wireless Gen 2 / 2023 |
| |
| "64865", // US TKL Wireless |
| |
| >> APEX PRO Mini Gen 2 / 2023 |
| |
| "64820", // US Mini |
| |
| >> APEX PRO Mini Wireless Gen 2 / 2023 |
| |
| "64842", // US Mini Wireless |
| |
| -- APEX PRO -- |
| |
| "64626", // US |
| "64627", // German |
| "64628", // French |
| "64629", // Japanese |
| "64630", // Korean |
| "64631", // Nordic |
| "64632", // Taiwanese |
| "64633", // Thai |
| "64634" // UK |
| |
| >> APEX PRO TKL |
| |
| "64734", // US TKL |
| "64735", // German TKL |
| "64736", // French TKL |
| "64737", // Japanese TKL |
| "64738", // Nordic TKL |
| "64739", // UK TKL |
| |
| -- APEX 9 -- |
| |
| >> APEX 9 TKL |
| |
| "64847", // US TKL |
| "64848", // UK TKL |
| "64849", // Nordic TKL |
| "64850", // German TKL |
| "64851", // French TKL |
| |
| >> APEX 9 Mini |
| |
| "64837", // US Mini |
| "64838", // UK Mini |
| "64839", // German Mini |
| "64840", // French Mini |
| "64841", // Nordic Mini |
| |
| -- APEX 7 -- |
| |
| >> RED switches |
| |
| "64635", // UK Red |
| "64636", // US Red |
| "64637", // German Red |
| "64638", // French Red |
| "64639", // Japanese Red |
| "64640", // Korean Red |
| "64641", // Nordic Red |
| "64642", // Russian Red |
| "64643", // Thai Red |
| "64644", // Turkish Red |
| "64645", // Taiwanese Red |
| |
| >> RED TKL |
| |
| "64646" // US Red TKL |
| "64647", // German Red TKL |
| "64648", // French Red TKL |
| "64649", // Japanese Red TKL |
| "64650", // Korean Red TKL |
| "64651", // Nordic Red TKL |
| "64652", // UK Red TKL |
| |
| >> BLUE switches |
| |
| "64770" // German Blue |
| "64771" // French Blue |
| "64772" // Japanese Blue |
| "64773" // Korean Blue |
| "64774" // US Blue |
| "64775" // Nordic Blue |
| "64776" // Thai Blue |
| "64777" // Taiwanese Blue |
| "64778" // UK Blue |
| |
| >> BLUE TKL |
| |
| "64756" // Japanese Blue TKL |
| "64757" // Korean Blue TKL |
| "64758" // US Blue TKL |
| "64760" // UK Blue TKL |
| |
| >> BROWN switches |
| |
| "64784" // German Brown |
| "64785" // French Brown |
| "64786" // US Brown |
| "64787" // Nordic Brown |
| "64788" // UK Brown |
| |
| >> BROWN TKL |
| |
| "64746" // French Brown TKL |
| "64747" // US Brown TKL |
| "64749" // UK Brown TKL |
| |
| -- APEX 5 -- |
| |
| "64533", // Nordic |
| "64534", // UK |
| "64535", // German |
| "64536", // French |
| "64537", // Japanese |
| "64538", // Turkish |
| "64539", // US |
| |
\*-----------------------------------------------------------*/
@@ -0,0 +1,80 @@
/*---------------------------------------------------------*\
| SteelSeriesApexTZoneController.cpp |
| |
| Driver for SteelSeries Apex T Zone |
| |
| Edbgon 06 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesApexTZoneController.h"
SteelSeriesApexTZoneController::SteelSeriesApexTZoneController(hid_device* dev_handle, const char* path, std::string dev_name) : SteelSeriesApex3Controller(dev_handle, path, dev_name)
{
}
SteelSeriesApexTZoneController::~SteelSeriesApexTZoneController()
{
}
uint8_t SteelSeriesApexTZoneController::GetLedCount()
{
return STEELSERIES_TZ_LED_COUNT;
}
uint8_t SteelSeriesApexTZoneController::GetMaxBrightness()
{
return STEELSERIES_TZ_BRIGHTNESS_MAX;
}
bool SteelSeriesApexTZoneController::SupportsRainbowWave()
{
return false;
}
bool SteelSeriesApexTZoneController::SupportsSave()
{
return true;
}
void SteelSeriesApexTZoneController::Save()
{
unsigned char buf[STEELSERIES_TZ_WRITE_PACKET_SIZE] = { 0x00, 0x06, 0x00, 0x08 };
hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE);
buf[0x01] = 0x09;
buf[0x03] = 0x00;
hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE);
}
void SteelSeriesApexTZoneController::SetColor(std::vector<RGBColor> colors, uint8_t /*mode*/, uint8_t brightness)
{
unsigned char buf[STEELSERIES_TZ_WRITE_PACKET_SIZE] = { 0x00 };
/*-----------------------------------------------------*\
| Zero out buffer, set up packet and send |
\*-----------------------------------------------------*/
memset(buf, 0x00, STEELSERIES_TZ_WRITE_PACKET_SIZE);
buf[0x01] = 0x0A;
buf[0x03] = brightness;
hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE);
buf[0x01] = 0x0B;
for(size_t i = 0; i < colors.size(); i++)
{
uint8_t index = (uint8_t)(i * 3);
buf[index + 3] = RGBGetRValue(colors[i]);;
buf[index + 4] = RGBGetGValue(colors[i]);;
buf[index + 5] = RGBGetBValue(colors[i]);;
}
hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE);
}
@@ -0,0 +1,39 @@
/*---------------------------------------------------------*\
| SteelSeriesApexTZoneController.h |
| |
| Driver for SteelSeries Apex T Zone |
| |
| Edbgon 06 Oct 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesApex3Controller.h"
#define STEELSERIES_TZ_LED_COUNT 10
#define STEELSERIES_TZ_WRITE_PACKET_SIZE 33
#define STEELSERIES_TZ_BRIGHTNESS_MAX 0x64
class SteelSeriesApexTZoneController : public SteelSeriesApex3Controller
{
public:
SteelSeriesApexTZoneController(hid_device *dev_handle, const char *path, std::string dev_name);
~SteelSeriesApexTZoneController();
void SetColor(std::vector<RGBColor> colors, uint8_t mode, uint8_t brightness);
void Save();
uint8_t GetLedCount();
uint8_t GetMaxBrightness();
bool SupportsRainbowWave();
bool SupportsSave();
private:
};
@@ -0,0 +1,106 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesArctis5.cpp |
| |
| RGBController for SteelSeries Arctis 5 |
| |
| Morgan Guimard 04 Mar 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesArctis5.h"
/**------------------------------------------------------------------*\
@name Steelseries Arctis 5
@category Headset
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectSteelSeriesArctis5
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesArctis5::RGBController_SteelSeriesArctis5(SteelSeriesArctis5Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "SteelSeries";
type = DEVICE_TYPE_HEADSET;
description = "SteelSeries Arctis 5 Headset Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0x00;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_SteelSeriesArctis5::~RGBController_SteelSeriesArctis5()
{
delete controller;
}
void RGBController_SteelSeriesArctis5::SetupZones()
{
const std::string zone_names[2] =
{
"Left" , "Right"
};
for(const std::string& zone_name : zone_names)
{
zone zone;
zone.name = zone_name;
zone.type = ZONE_TYPE_SINGLE;
zone.leds_min = 1;
zone.leds_max = 1;
zone.leds_count = 1;
zone.matrix_map = NULL;
zones.push_back(zone);
led mouse_led;
mouse_led.name = zone_name;
leds.push_back(mouse_led);
}
SetupColors();
}
void RGBController_SteelSeriesArctis5::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesArctis5::DeviceUpdateLEDs()
{
for(unsigned int i = 0; i < zones.size(); i++)
{
UpdateZoneLEDs(i);
}
}
void RGBController_SteelSeriesArctis5::UpdateZoneLEDs(int zone)
{
controller->SetColor(zone, colors[zone]);
}
void RGBController_SteelSeriesArctis5::UpdateSingleLED(int led)
{
UpdateZoneLEDs(led);
}
void RGBController_SteelSeriesArctis5::DeviceUpdateMode()
{
}
@@ -0,0 +1,34 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesArctis5.h |
| |
| RGBController for SteelSeries Arctis 5 |
| |
| Morgan Guimard 04 Mar 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesArctis5Controller.h"
class RGBController_SteelSeriesArctis5 : public RGBController
{
public:
RGBController_SteelSeriesArctis5(SteelSeriesArctis5Controller* controller_ptr);
~RGBController_SteelSeriesArctis5();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
SteelSeriesArctis5Controller* controller;
};
@@ -0,0 +1,140 @@
/*---------------------------------------------------------*\
| SteelSeriesArctis5Controller.cpp |
| |
| Driver for SteelSeries Arctis 5 |
| |
| Morgan Guimard 04 Mar 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <string.h>
#include "SteelSeriesArctis5Controller.h"
#include "StringUtils.h"
SteelSeriesArctis5Controller::SteelSeriesArctis5Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
{
dev = dev_handle;
location = info.path;
name = dev_name;
}
SteelSeriesArctis5Controller::~SteelSeriesArctis5Controller()
{
hid_close(dev);
}
std::string SteelSeriesArctis5Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesArctis5Controller::GetNameString()
{
return(name);
}
std::string SteelSeriesArctis5Controller::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 SteelSeriesArctis5Controller::SetColor(unsigned char zone_id, RGBColor color)
{
unsigned char usb_buf[ARCTIS_5_REPORT_SIZE];
/*----------------------------------------------*\
| Two packets are sent before a color change |
\*----------------------------------------------*/
memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE);
usb_buf[0x00] = ARCTIS_5_REPORT_ID;
usb_buf[0x01] = 0x81;
usb_buf[0x02] = 0x43;
usb_buf[0x03] = 0x01;
usb_buf[0x04] = 0x22;
hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE);
usb_buf[0x04] = 0x23;
hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE);
/*----------------------------------------------*\
| First packet: send color |
\*----------------------------------------------*/
memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE);
usb_buf[0x00] = ARCTIS_5_REPORT_ID;
usb_buf[0x01] = 0x8A;
usb_buf[0x02] = 0x42;
usb_buf[0x04] = 0x20;
usb_buf[0x05] = 0x41;
usb_buf[0x07] = RGBGetRValue(color);
usb_buf[0x08] = RGBGetGValue(color);
usb_buf[0x09] = RGBGetBValue(color);
usb_buf[0x0A] = 0xFF;
usb_buf[0x0B] = 0x32;
usb_buf[0x0C] = 0xC8;
usb_buf[0x0D] = 0xC8;
hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE);
/*-----------------------------------------*\
| Second packet: apply to zone |
\*-----------------------------------------*/
memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE);
usb_buf[0x00] = ARCTIS_5_REPORT_ID;
usb_buf[0x01] = 0x8A;
usb_buf[0x02] = 0x42;
usb_buf[0x04] = 0x20;
usb_buf[0x05] = 0x41;
usb_buf[0x06] = 0x08;
usb_buf[0x07] = zone_id;
usb_buf[0x08] = 0x01;
hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE);
/*-----------------------------------------*\
| Thrid packet: apply to zone |
\*-----------------------------------------*/
memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE);
usb_buf[0x00] = ARCTIS_5_REPORT_ID;
usb_buf[0x01] = 0x8A;
usb_buf[0x02] = 0x42;
usb_buf[0x04] = 0x20;
usb_buf[0x05] = 0x60;
usb_buf[0x06] = zone_id;
hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE);
/*-----------------------------------------*\
| Last packet: apply |
\*-----------------------------------------*/
memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE);
usb_buf[0x00] = ARCTIS_5_REPORT_ID;
usb_buf[0x01] = 0x8A;
usb_buf[0x02] = 0x42;
usb_buf[0x04] = 0x20;
usb_buf[0x05] = 0x05;
hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE);
}
@@ -0,0 +1,37 @@
/*---------------------------------------------------------*\
| SteelSeriesArctis5Controller.h |
| |
| Driver for SteelSeries Arctis 5 |
| |
| Morgan Guimard 04 Mar 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#define ARCTIS_5_REPORT_SIZE 37
#define ARCTIS_5_REPORT_ID 0x06
class SteelSeriesArctis5Controller
{
public:
SteelSeriesArctis5Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
~SteelSeriesArctis5Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetColor(unsigned char zone_id, RGBColor color);
private:
hid_device* dev;
std::string location;
std::string name;
};
@@ -0,0 +1,525 @@
/*---------------------------------------------------------*\
| SteelSeriesControllerDetect.cpp |
| |
| Detector for SteelSeries devices |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "Detector.h"
#include "SteelSeriesGeneric.h"
#include "SteelSeriesAeroxWirelessController.h"
#include "SteelSeriesAerox5Controller.h"
#include "SteelSeriesArctis5Controller.h"
#include "SteelSeriesApex8ZoneController.h"
#include "SteelSeriesApex9Controller.h"
#include "SteelSeriesApexController.h"
#include "SteelSeriesApexMController.h"
#include "SteelSeriesApexTZoneController.h"
#include "SteelSeriesOldApexController.h"
#include "SteelSeriesQCKMatController.h"
#include "SteelSeriesRivalController.h"
#include "SteelSeriesRival3Controller.h"
#include "SteelSeriesSenseiController.h"
#include "SteelSeriesSiberiaController.h"
#include "RGBController_SteelSeriesArctis5.h"
#include "RGBController_SteelSeriesApex.h"
#include "RGBController_SteelSeriesApex3.h"
#include "RGBController_SteelSeriesOldApex.h"
#include "RGBController_SteelSeriesQCKMat.h"
#include "RGBController_SteelSeriesRival.h"
#include "RGBController_SteelSeriesRival3.h"
#include "RGBController_SteelSeriesSensei.h"
#include "RGBController_SteelSeriesSiberia.h"
/*-----------------------------------------------------*\
| Vendor ID |
\*-----------------------------------------------------*/
#define STEELSERIES_VID 0x1038
/*-----------------------------------------------------*\
| Mouse product IDs |
\*-----------------------------------------------------*/
#define STEELSERIES_AEROX_3_PID 0x1836
#define STEELSERIES_AEROX_3_WIRELESS_PID 0x1838
#define STEELSERIES_AEROX_3_WIRELESS_WIRED_PID 0x183A
#define STEELSERIES_AEROX_3_CS2_WIRELESS_PID 0x1878
#define STEELSERIES_AEROX_3_CS2_WIRELESS_WIRED_PID 0x187A
#define STEELSERIES_AEROX_5_WIRELESS_PID 0x1852
#define STEELSERIES_AEROX_5_WIRELESS_WIRED_PID 0x1854
#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_PID 0x185C
#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_WIRED_PID 0x185E
#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_PID 0x1860
#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_WIRED_PID 0x1862
#define STEELSERIES_AEROX_9_WIRELESS_PID 0x1858
#define STEELSERIES_AEROX_9_WIRELESS_WIRED_PID 0x185A
#define STEELSERIES_AEROX_5_PID 0x1850
#define STEELSERIES_AEROX_9_PID 0x185A
#define STEELSERIES_RIVAL_100_PID 0x1702
#define STEELSERIES_RIVAL_100_DOTA_PID 0x170C
#define STEELSERIES_RIVAL_105_PID 0x1814
#define STEELSERIES_RIVAL_106_PID 0x1816
#define STEELSERIES_RIVAL_110_PID 0x1729
#define STEELSERIES_RIVAL_300_PID 0x1710
#define ACER_PREDATOR_RIVAL_300_PID 0x1714
#define STEELSERIES_RIVAL_300_CSGO_PID 0x1394
#define STEELSERIES_RIVAL_300_CSGO_STM32_PID 0x1716
#define STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID 0x171A
#define STEELSERIES_RIVAL_300_DOTA_PID 0x1392
#define STEELSERIES_RIVAL_300_HP_PID 0x1718
#define STEELSERIES_RIVAL_300_BLACKOPS_PID 0x1710
#define STEELSERIES_RIVAL_310_PID 0x1720
#define STEELSERIES_RIVAL_310_CSGO_HOWL_PID 0x171E
#define STEELSERIES_RIVAL_310_PUBG_PID 0x1736
#define STEELSERIES_RIVAL_600_PID 0x1724
#define STEELSERIES_RIVAL_600_DOTA_2_PID 0x172E
#define STEELSERIES_RIVAL_650_PID 0x172B
#define STEELSERIES_RIVAL_650_WIRELESS_PID 0x1726
#define STEELSERIES_RIVAL_700_PID 0x1700
#define STEELSERIES_RIVAL_710_PID 0x1730
#define STEELSERIES_RIVAL_3_OLD_PID 0x1824
#define STEELSERIES_RIVAL_3_PID 0x184C
#define STEELSERIES_SENSEI_TEN_PID 0x1832
#define STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID 0x1834
#define STEELSERIES_SENSEI_310_PID 0x1722
/*-----------------------------------------------------*\
| Headset product IDs |
\*-----------------------------------------------------*/
#define STEELSERIES_SIBERIA_350_PID 0x1229
#define STEELSERIES_ARCTIS_5_PID 0x1250
#define STEELSERIES_ARCTIS_5_V2_PID 0x12AA
/*--------------------------------------------------------------------*\
| Mousemat product IDs |
\*--------------------------------------------------------------------*/
#define STEELSERIES_QCK_PRISM_CLOTH_MED_PID 0x150A
#define STEELSERIES_QCK_PRISM_CLOTH_XL_PID 0x150D
#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID 0x151E
#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID 0x1514
#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEO_NOIR_PID 0x151C
#define STEELSERIES_QCK_PRISM_CLOTH_3XL_PID 0x1516
#define STEELSERIES_QCK_PRISM_CLOTH_4XL_PID 0x1518
#define STEELSERIES_QCK_PRISM_CLOTH_5XL_PID 0x151A
#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_2_LIGHTFALL_ED_PID 0x1520
/*-----------------------------------------------------*\
| Keyboard product IDs |
\*-----------------------------------------------------*/
#define STEELSERIES_APEX_3_PID 0x161A
#define STEELSERIES_APEX_3_TKL_PID 0x1622
#define STEELSERIES_APEX_5_PID 0x161C
#define STEELSERIES_APEX_7_PID 0x1612
#define STEELSERIES_APEX_7_TKL_PID 0x1618
#define STEELSERIES_APEX_9_TKL_PID 0x1634
#define STEELSERIES_APEX_9_MINI_PID 0x1620
#define STEELSERIES_APEX_PRO_PID 0x1610
#define STEELSERIES_APEX_PRO_TKL_PID 0x1614
#define STEELSERIES_APEX_PRO_TKL_2023_PID 0x1628
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1 0x1630
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2 0x1632
#define STEELSERIES_APEX_PRO_TKL_GEN3_PID 0x1642
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1 0x1644
#define STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2 0x1646
#define STEELSERIES_APEX_M750_PID 0x0616
#define STEELSERIES_APEX_OG_PID 0x1202
#define STEELSERIES_APEX_350_PID 0x1206
#define STEELSERIES_APEX_PRO3_PID 0x1640
void DetectSteelSeriesAerox3(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesAerox3Controller* controller = new SteelSeriesAerox3Controller(dev, AEROX_3, info->path, name);
RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesAeroxWireless(hid_device_info* info, const std::string& name, steelseries_type proto_type)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesAeroxWirelessController* controller = new SteelSeriesAeroxWirelessController(dev, proto_type, info->path, name);
RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesAerox3Wireless(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_3_WIRELESS);
}
void DetectSteelSeriesAerox3WirelessWired(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_3_WIRELESS_WIRED);
}
void DetectSteelSeriesAerox5(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesAerox5Controller* controller = new SteelSeriesAerox5Controller(dev, AEROX_3, info->path, name);
RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesAerox5Wireless(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_5_WIRELESS);
}
void DetectSteelSeriesAerox5WirelessWired(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_5_WIRELESS_WIRED);
}
void DetectSteelSeriesAerox5DestinyWireless(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DESTINY_WIRELESS);
}
void DetectSteelSeriesAerox5DestinyWirelessWired(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DESTINY_WIRELESS_WIRED);
}
void DetectSteelSeriesAerox5DiabloWireless(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DIABLO_WIRELESS);
}
void DetectSteelSeriesAerox5DiabloWirelessWired(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DIABLO_WIRELESS_WIRED);
}
void DetectSteelSeriesAerox9Wireless(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_9_WIRELESS);
}
void DetectSteelSeriesAerox9WirelessWired(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesAeroxWireless(info, name, AEROX_9_WIRELESS_WIRED);
}
void DetectSteelSeriesApex3Full(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesApexTZoneController* controller = new SteelSeriesApexTZoneController(dev, info->path, name);
RGBController_SteelSeriesApex3* rgb_controller = new RGBController_SteelSeriesApex3(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesApex3TKL(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesApex8ZoneController* controller = new SteelSeriesApex8ZoneController(dev, info->path, name);
RGBController_SteelSeriesApex3* rgb_controller = new RGBController_SteelSeriesApex3(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesApex(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesApexController* controller = new SteelSeriesApexController(dev, APEX, info->path, name);
RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesApex9(hid_device_info* info, const std::string& name, steelseries_type proto_type)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesApex9Controller* controller = new SteelSeriesApex9Controller(dev, proto_type, info->path, name);
RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesApex9TKL(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesApex9(info, name, APEX_9_TKL);
}
void DetectSteelSeriesApex9Mini(hid_device_info* info, const std::string& name)
{
DetectSteelSeriesApex9(info, name, APEX_9_MINI);
}
void DetectSteelSeriesApexM(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesApexMController* controller = new SteelSeriesApexMController(dev, APEX_M, info->path, name);
RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesApexOld(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesOldApexController* controller = new SteelSeriesOldApexController(dev, APEX_OLD, info->path, name);
RGBController_SteelSeriesOldApex* rgb_controller = new RGBController_SteelSeriesOldApex(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesHeadset(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesSiberiaController* controller = new SteelSeriesSiberiaController(dev, info->path, name);
RGBController_SteelSeriesSiberia* rgb_controller = new RGBController_SteelSeriesSiberia(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesMousemat(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesQCKMatController* controller = new SteelSeriesQCKMatController(dev, info->path, name);
RGBController_SteelSeriesQCKMat* rgb_controller = new RGBController_SteelSeriesQCKMat(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesRival100(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_100, info->path, name);
RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesRival300(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_300, info->path, name);
RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesRival600(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_600, info->path, name);
RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesRival650(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_650, info->path, name);
RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesRival700(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_700, info->path, name);
RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesRival3(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesRival3Controller* controller = new SteelSeriesRival3Controller(dev, RIVAL_3, info->path, name);
RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesSensei(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesSenseiController* controller = new SteelSeriesSenseiController(dev, SENSEI, info->path, name);
RGBController_SteelSeriesSensei* rgb_controller = new RGBController_SteelSeriesSensei(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectSteelSeriesArctis5(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SteelSeriesArctis5Controller* controller = new SteelSeriesArctis5Controller(dev, *info, name);
RGBController_SteelSeriesArctis5* rgb_controller = new RGBController_SteelSeriesArctis5(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\
| Mice |
\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wireless", DetectSteelSeriesAerox3Wireless, STEELSERIES_VID, STEELSERIES_AEROX_3_WIRELESS_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wireless Wired", DetectSteelSeriesAerox3WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_3_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 CS2 Dragon Lore Edition Wireless", DetectSteelSeriesAerox3Wireless, STEELSERIES_VID, STEELSERIES_AEROX_3_CS2_WIRELESS_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 CS2 Dragon Lore Edition Wireless Wired", DetectSteelSeriesAerox3WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_3_CS2_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wired", DetectSteelSeriesAerox3, STEELSERIES_VID, STEELSERIES_AEROX_3_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Wireless", DetectSteelSeriesAerox5Wireless, STEELSERIES_VID, STEELSERIES_AEROX_5_WIRELESS_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Wireless Wired", DetectSteelSeriesAerox5WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_5_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Destiny 2 Edition Wireless", DetectSteelSeriesAerox5DestinyWireless, STEELSERIES_VID, STEELSERIES_AEROX_5_DESTINY_WIRELESS_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Destiny 2 Edition Wireless Wired", DetectSteelSeriesAerox5DestinyWirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_5_DESTINY_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Diablo IV Edition Wireless", DetectSteelSeriesAerox5DiabloWireless, STEELSERIES_VID, STEELSERIES_AEROX_5_DIABLO_WIRELESS_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Diablo IV Edition Wireless Wired", DetectSteelSeriesAerox5DiabloWirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_5_DIABLO_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Wired", DetectSteelSeriesAerox5, STEELSERIES_VID, STEELSERIES_AEROX_5_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 9 Wireless", DetectSteelSeriesAerox9Wireless, STEELSERIES_VID, STEELSERIES_AEROX_9_WIRELESS_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 9 Wireless Wired", DetectSteelSeriesAerox9WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_9_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_I("SteelSeries Rival 100", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_100_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 100 DotA 2 Edition", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_100_DOTA_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 105", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_105_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 106", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_106_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 110", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_110_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_PID, 0);
REGISTER_HID_DETECTOR_I("Acer Predator Gaming Mouse (Rival 300)", DetectSteelSeriesRival300, STEELSERIES_VID, ACER_PREDATOR_RIVAL_300_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Fade Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Fade Edition (stm32)", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_STM32_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Hyperbeast Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 Dota 2 Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_DOTA_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 HP Omen Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_HP_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 Black Ops Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_BLACKOPS_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 310", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 310 CS:GO Howl Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_CSGO_HOWL_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 310 PUBG Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_PUBG_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 600", DetectSteelSeriesRival600, STEELSERIES_VID, STEELSERIES_RIVAL_600_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 600 Dota 2 Edition", DetectSteelSeriesRival600, STEELSERIES_VID, STEELSERIES_RIVAL_600_DOTA_2_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 650", DetectSteelSeriesRival650, STEELSERIES_VID, STEELSERIES_RIVAL_650_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 650 Wireless", DetectSteelSeriesRival650, STEELSERIES_VID, STEELSERIES_RIVAL_650_WIRELESS_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 700", DetectSteelSeriesRival700, STEELSERIES_VID, STEELSERIES_RIVAL_700_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 710", DetectSteelSeriesRival700, STEELSERIES_VID, STEELSERIES_RIVAL_710_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 3 (Old Firmware)", DetectSteelSeriesRival3, STEELSERIES_VID, STEELSERIES_RIVAL_3_OLD_PID, 3);
REGISTER_HID_DETECTOR_I("SteelSeries Rival 3", DetectSteelSeriesRival3, STEELSERIES_VID, STEELSERIES_RIVAL_3_PID, 3);
REGISTER_HID_DETECTOR_I("SteelSeries Sensei TEN", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_TEN_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Sensei TEN CS:GO Neon Rider Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID, 0);
REGISTER_HID_DETECTOR_I("SteelSeries Sensei 310", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_310_PID, 0);
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\
| Headsets |
\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_I("SteelSeries Siberia 350", DetectSteelSeriesHeadset, STEELSERIES_VID, STEELSERIES_SIBERIA_350_PID, 3 );
REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_PID, 5 );
REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_V2_PID, 5 );
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\
| Mousemats |
\*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth Medium", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_MED_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL Destiny Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL Destiny 2 Lightfall Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_2_LIGHTFALL_ED_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL CS:GO Neon Rider Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL CS:GO Neo Noir Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEO_NOIR_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 3XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_3XL_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 4XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_4XL_PID, 0 );
REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 5XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_5XL_PID, 0 );
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\
| Keyboards |
\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 3", DetectSteelSeriesApex3Full, STEELSERIES_VID, STEELSERIES_APEX_3_PID, 3 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex 3 TKL", DetectSteelSeriesApex3TKL, STEELSERIES_VID, STEELSERIES_APEX_3_TKL_PID, 1, 0xFFC0, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 5", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_5_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7 TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_TKL_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 TKL", DetectSteelSeriesApex9TKL, STEELSERIES_VID, STEELSERIES_APEX_9_TKL_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 Mini", DetectSteelSeriesApex9Mini, STEELSERIES_VID, STEELSERIES_APEX_9_MINI_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_PID, 1 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL 2023 Wired", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_PID, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL 2023 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1, 3, 0xFFC0, 1);
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL 2023 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2, 3, 0xFFC0, 1);
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL Gen 3 Wired", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_PID, 1 );
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL Gen 3 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_1, 3, 0xFFC0, 1);
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL Gen 3 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_GEN3_WL_PID_2, 3, 0xFFC0, 1);
REGISTER_HID_DETECTOR_I ("SteelSeries Apex M750", DetectSteelSeriesApexM, STEELSERIES_VID, STEELSERIES_APEX_M750_PID, 2 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex (OG)/Apex Fnatic", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_OG_PID, 0 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 350", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_350_PID, 0 );
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro 3", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO3_PID, 1 );
@@ -0,0 +1,48 @@
/*---------------------------------------------------------*\
| SteelSeriesGeneric.h |
| |
| Generic file for SteelSeries devices |
| |
| B Horn (bahorn) 17 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
/* Allows us to handle variation in the protocol.
* Defined in a single enum so we can keep the device_list struct the same
* for every possible device. */
typedef enum
{
RIVAL_100 = 0x00,
RIVAL_300 = 0x01,
RIVAL_650 = 0x02,
SIBERIA_350 = 0x03,
APEX = 0x04,
APEX_M = 0x05,
APEX_OLD = 0x06,
SENSEI = 0x07,
RIVAL_600 = 0x08,
RIVAL_3 = 0x09,
APEX_TZONE = 0x0A,
RIVAL_700 = 0x0B,
AEROX_3 = 0x0C,
APEX_8ZONE = 0x0D,
AEROX_3_WIRELESS = 0x0E,
AEROX_3_WIRELESS_WIRED = 0x0F,
AEROX_5_WIRELESS = 0x10,
AEROX_5_WIRELESS_WIRED = 0x11,
AEROX_5_DESTINY_WIRELESS = 0x12,
AEROX_5_DESTINY_WIRELESS_WIRED = 0x13,
AEROX_5_DIABLO_WIRELESS = 0x14,
AEROX_5_DIABLO_WIRELESS_WIRED = 0x15,
AEROX_9_WIRELESS = 0x16,
AEROX_9_WIRELESS_WIRED = 0x17,
APEX_9_TKL = 0x18,
APEX_9_MINI = 0x19,
} steelseries_type;
@@ -0,0 +1,63 @@
/*---------------------------------------------------------*\
| SteelSeriesMouseController.cpp |
| |
| Driver for SteelSeries Mouse |
| |
| Chris M (Dr_No) 09 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesMouseController.h"
#include "StringUtils.h"
SteelSeriesMouseController::SteelSeriesMouseController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
proto = proto_type;
}
SteelSeriesMouseController::~SteelSeriesMouseController()
{
}
std::string SteelSeriesMouseController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesMouseController::GetNameString()
{
return(name);
}
std::string SteelSeriesMouseController::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));
}
steelseries_type SteelSeriesMouseController::GetMouseType()
{
return proto;
}
void SteelSeriesMouseController::Save()
{
const uint8_t SAVE_BUFFER_SIZE = 10;
uint8_t usb_buf[SAVE_BUFFER_SIZE] = { 0x00, 0x09 };
hid_write(dev, usb_buf, SAVE_BUFFER_SIZE);
}
@@ -0,0 +1,84 @@
/*---------------------------------------------------------*\
| SteelSeriesMouseController.h |
| |
| Driver for SteelSeries Mouse |
| |
| Chris M (Dr_No) 09 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <hidapi.h>
#include "SteelSeriesGeneric.h"
#define STEELSERIES_MOUSE_BRIGHTNESS_MAX 0x64
/*-----------------------------------------------------------*\
| Theses are the specific values that get sent to set a mode |
\*-----------------------------------------------------------*/
enum
{
STEELSERIES_MOUSE_EFFECT_SPECTRUM_CYCLE = 0x00,
STEELSERIES_MOUSE_EFFECT_BREATHING_MAX = 0x01,
STEELSERIES_MOUSE_EFFECT_BREATHING_MID = 0x02,
STEELSERIES_MOUSE_EFFECT_BREATHING_MIN = 0x03,
STEELSERIES_MOUSE_EFFECT_DIRECT = 0x04,
STEELSERIES_MOUSE_EFFECT_RAINBOW_BREATHING = 0x05,
STEELSERIES_MOUSE_EFFECT_DISCO = 0x06
};
typedef struct
{
const char* name;
const int value;
} led_info;
typedef struct
{
std::vector<uint8_t> modes;
std::vector<led_info> leds;
} steelseries_mouse;
class SteelSeriesMouseController
{
public:
SteelSeriesMouseController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name);
virtual ~SteelSeriesMouseController();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
steelseries_type GetMouseType();
/*-----------------------------------------------------------------*\
| Save has a common function but can be overridden |
\*-----------------------------------------------------------------*/
virtual void Save();
virtual steelseries_mouse GetMouse() = 0;
virtual std::string GetFirmwareVersion() = 0;
virtual void SetLightEffectAll(uint8_t effect) = 0;
virtual void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
) = 0;
protected:
hid_device* dev;
std::string location;
std::string name;
steelseries_type proto;
private:
};
@@ -0,0 +1,200 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesOldApex.cpp |
| |
| RGBController for older SteelSeries Apex keyboards |
| (Apex/Apex Fnatic/Apex 350) |
| |
| Based on findings in ApexCtl by Audrius/tuxmark5, et. |
| al, https://github.com/tuxmark5/ApexCtl |
| |
| David Lee (RAMChYLD) 15 Nov 2020 |
| Based on work by B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesOldApex.h"
/**------------------------------------------------------------------*\
@name Steel Series Apex (Old)
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectSteelSeriesApexOld
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesOldApex::RGBController_SteelSeriesOldApex(SteelSeriesOldApexController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "SteelSeries";
type = DEVICE_TYPE_KEYBOARD;
description = "SteelSeries Old Apex Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode direct;
direct.name = "Direct";
direct.value = STEELSERIES_OLDAPEX_DIRECT;
direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(direct);
SetupZones();
}
RGBController_SteelSeriesOldApex::~RGBController_SteelSeriesOldApex()
{
delete controller;
}
void RGBController_SteelSeriesOldApex::SetupZones()
{
/* We have 5 zones to work with. Here goes... */
zone qwerty_zone;
qwerty_zone.name = "QWERTY";
qwerty_zone.type = ZONE_TYPE_LINEAR;
qwerty_zone.leds_min = 1;
qwerty_zone.leds_max = 1;
qwerty_zone.leds_count = 1;
qwerty_zone.matrix_map = NULL;
zones.push_back(qwerty_zone);
led qwerty_led;
qwerty_led.name = "QWERTY";
leds.push_back(qwerty_led);
zone tenkey_zone;
tenkey_zone.name = "TenKey";
tenkey_zone.type = ZONE_TYPE_LINEAR;
tenkey_zone.leds_min = 1;
tenkey_zone.leds_max = 1;
tenkey_zone.leds_count = 1;
tenkey_zone.matrix_map = NULL;
zones.push_back(tenkey_zone);
led tenkey_led;
tenkey_led.name = "TenKey";
leds.push_back(tenkey_led);
zone function_zone;
function_zone.name = "FunctionKeys";
function_zone.type = ZONE_TYPE_LINEAR;
function_zone.leds_min = 1;
function_zone.leds_max = 1;
function_zone.leds_count = 1;
function_zone.matrix_map = NULL;
zones.push_back(function_zone);
led function_led;
function_led.name = "FunctionKeys";
leds.push_back(function_led);
zone mx_zone;
mx_zone.name = "MXKeys";
mx_zone.type = ZONE_TYPE_LINEAR;
mx_zone.leds_min = 1;
mx_zone.leds_max = 1;
mx_zone.leds_count = 1;
mx_zone.matrix_map = NULL;
zones.push_back(mx_zone);
led mx_led;
mx_led.name = "MXKeys";
leds.push_back(mx_led);
zone logo_zone;
logo_zone.name = "Logo";
logo_zone.type = ZONE_TYPE_LINEAR;
logo_zone.leds_min = 1;
logo_zone.leds_max = 1;
logo_zone.leds_count = 1;
logo_zone.matrix_map = NULL;
zones.push_back(logo_zone);
led logo_led;
logo_led.name = "Logo";
leds.push_back(logo_led);
SetupColors();
}
void RGBController_SteelSeriesOldApex::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesOldApex::DeviceUpdateLEDs()
{
// Due to the inefficient packet design of the OG Apex
// All colors must be blasted with each update
color32 qwerty;
qwerty.red = RGBGetRValue(colors[0]);
qwerty.green = RGBGetGValue(colors[0]);
qwerty.blue = RGBGetBValue(colors[0]);
qwerty.alpha = modes[active_mode].value;
color32 tenkey;
tenkey.red = RGBGetRValue(colors[1]);
tenkey.green = RGBGetGValue(colors[1]);
tenkey.blue = RGBGetBValue(colors[1]);
tenkey.alpha = modes[active_mode].value;
color32 functionkey;
functionkey.red = RGBGetRValue(colors[2]);
functionkey.green = RGBGetGValue(colors[2]);
functionkey.blue = RGBGetBValue(colors[2]);
functionkey.alpha = modes[active_mode].value;
color32 mxkey;
mxkey.red = RGBGetRValue(colors[3]);
mxkey.green = RGBGetGValue(colors[3]);
mxkey.blue = RGBGetBValue(colors[3]);
mxkey.alpha = modes[active_mode].value;
color32 logo;
logo.red = RGBGetRValue(colors[4]);
logo.green = RGBGetGValue(colors[4]);
logo.blue = RGBGetBValue(colors[4]);
logo.alpha = modes[active_mode].value;
controller->SetColorDetailed(qwerty, tenkey, functionkey, mxkey, logo);
}
void RGBController_SteelSeriesOldApex::UpdateZoneLEDs(int /*zone*/)
{
// updating for one zone is pointless,
// all zones have to be blasted anyway
// so just do a full update
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesOldApex::UpdateSingleLED(int /*led*/)
{
// Each zone is one LED, however
// updating for one zone is pointless,
// all zones have to be blasted anyway
// so just do a full update
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesOldApex::DeviceUpdateMode()
{
// We are using SetLightingEffect to control the brightness of
// LEDs. Per-zone brightness is actually possible but we are not
// doing that for now. Brightness affects whole keyboard.
// Because at the moment all this code does is change brightness,
// We just let the new value set in and do a device LED update
// and blast the brightness value along with the RGB values
DeviceUpdateLEDs();
}
@@ -0,0 +1,40 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesOldApex.h |
| |
| RGBController for older SteelSeries Apex keyboards |
| (Apex/Apex Fnatic/Apex 350) |
| |
| Based on findings in ApexCtl by Audrius/tuxmark5, et. |
| al, https://github.com/tuxmark5/ApexCtl |
| |
| David Lee (RAMChYLD) 15 Nov 2020 |
| Based on work by B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesOldApexController.h"
#include "color32.h"
class RGBController_SteelSeriesOldApex : public RGBController
{
public:
RGBController_SteelSeriesOldApex(SteelSeriesOldApexController* controller_ptr);
~RGBController_SteelSeriesOldApex();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
SteelSeriesOldApexController* controller;
};
@@ -0,0 +1,124 @@
/*---------------------------------------------------------*\
| SteelSeriesOldApexController.cpp |
| |
| Driver for older SteelSeries Apex keyboards |
| (Apex/Apex Fnatic/Apex 350) |
| |
| Based on findings in ApexCtl by Audrius/tuxmark5, et. |
| al, https://github.com/tuxmark5/ApexCtl |
| |
| David Lee (RAMChYLD) 15 Nov 2020 |
| Based on work by B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include "SteelSeriesOldApexController.h"
#include "StringUtils.h"
static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size)
{
char* usb_pkt = new char[size + 1];
usb_pkt[0] = 0x00;
for(unsigned int i = 1; i < size + 1; i++)
{
usb_pkt[i] = data_pkt[i-1];
}
hid_write(dev, (unsigned char *)usb_pkt, size + 1);
delete[] usb_pkt;
}
SteelSeriesOldApexController::SteelSeriesOldApexController
(
hid_device* dev_handle,
steelseries_type proto_type,
const char* path,
std::string dev_name
)
{
dev = dev_handle;
location = path;
name = dev_name;
proto = proto_type;
}
SteelSeriesOldApexController::~SteelSeriesOldApexController()
{
hid_close(dev);
}
std::string SteelSeriesOldApexController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesOldApexController::GetDeviceName()
{
return(name);
}
std::string SteelSeriesOldApexController::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));
}
steelseries_type SteelSeriesOldApexController::GetKeyboardType()
{
return proto;
}
void SteelSeriesOldApexController::SetColorDetailed(color32 qwerty, color32 tenkey, color32 functionkey, color32 mxkey, color32 logo)
{
char usb_buf[32];
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x07;
usb_buf[0x01] = 0x00; // All zones
// QWERTY Zone
usb_buf[0x02] = qwerty.red;
usb_buf[0x03] = qwerty.green;
usb_buf[0x04] = qwerty.blue;
usb_buf[0x05] = qwerty.alpha;
// Tenkey Zone
usb_buf[0x06] = tenkey.red;
usb_buf[0x07] = tenkey.green;
usb_buf[0x08] = tenkey.blue;
usb_buf[0x09] = tenkey.alpha;
// FunctionKey Zone
usb_buf[0x0A] = functionkey.red;
usb_buf[0x0B] = functionkey.green;
usb_buf[0x0C] = functionkey.blue;
usb_buf[0x0D] = functionkey.alpha;
// MXKey Zone
usb_buf[0x0E] = mxkey.red;
usb_buf[0x0F] = mxkey.green;
usb_buf[0x10] = mxkey.blue;
usb_buf[0x11] = mxkey.alpha;
//Logo Zone
usb_buf[0x12] = logo.red;
usb_buf[0x13] = logo.green;
usb_buf[0x14] = logo.blue;
usb_buf[0x15] = logo.alpha;
send_usb_msg(dev, usb_buf, 32);
}
@@ -0,0 +1,71 @@
/*---------------------------------------------------------*\
| SteelSeriesOldApexController.h |
| |
| Driver for older SteelSeries Apex keyboards |
| (Apex/Apex Fnatic/Apex 350) |
| |
| Based on findings in ApexCtl by Audrius/tuxmark5, et. |
| al, https://github.com/tuxmark5/ApexCtl |
| |
| David Lee (RAMChYLD) 15 Nov 2020 |
| Based on work by B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "color32.h"
#include "SteelSeriesGeneric.h"
/* Mode, we then use these to set actual effect based on speed. */
enum
{
STEELSERIES_OLDAPEX_DIRECT = 0x08,
};
/* Effects */
enum
{
STEELSERIES_OLDAPEX_EFFECT_DIRECT = 0x08,
};
class SteelSeriesOldApexController
{
public:
SteelSeriesOldApexController
(
hid_device* dev_handle,
steelseries_type proto_type,
const char* path,
std::string dev_name
);
~SteelSeriesOldApexController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetSerialString();
steelseries_type GetKeyboardType();
void SetColorDetailed
(
color32 qwerty,
color32 tenkey,
color32 functionkey,
color32 mxkey,
color32 logo
);
void DoUpdateLEDs();
private:
hid_device* dev;
std::string location;
std::string name;
steelseries_type proto;
};
@@ -0,0 +1,106 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesQCKMat.cpp |
| |
| RGBController for SteelSeries Mouse |
| |
| Edbgon 22 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesQCKMat.h"
/**------------------------------------------------------------------*\
@name Steel Series QCK Mat
@category Mousemat
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectSteelSeriesMousemat
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesQCKMat::RGBController_SteelSeriesQCKMat(SteelSeriesQCKMatController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "SteelSeries";
type = DEVICE_TYPE_MOUSEMAT;
description = "SteelSeries QCK Mat Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_SteelSeriesQCKMat::~RGBController_SteelSeriesQCKMat()
{
delete controller;
}
void RGBController_SteelSeriesQCKMat::SetupZones()
{
/*---------------------------------------------------------*\
| QCK has two zones |
\*---------------------------------------------------------*/
zone mousemat_zone;
mousemat_zone.name = "Mousemat";
mousemat_zone.type = ZONE_TYPE_SINGLE;
mousemat_zone.leds_min = 2;
mousemat_zone.leds_max = 2;
mousemat_zone.leds_count = 2;
mousemat_zone.matrix_map = NULL;
zones.push_back(mousemat_zone);
led bot_led;
bot_led.name = "Mat Bottom LED";
leds.push_back(bot_led);
led top_led;
top_led.name = "Mat Top LED";
leds.push_back(top_led);
SetupColors();
}
void RGBController_SteelSeriesQCKMat::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesQCKMat::DeviceUpdateLEDs()
{
controller->SetColors(colors);
}
void RGBController_SteelSeriesQCKMat::UpdateZoneLEDs(int /*zone*/)
{
/*---------------------------------------------------------*\
| Packet expects both LEDs |
\*---------------------------------------------------------*/
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesQCKMat::UpdateSingleLED(int /*led*/)
{
/*---------------------------------------------------------*\
| Packet expects both LEDs |
\*---------------------------------------------------------*/
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesQCKMat::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -0,0 +1,34 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesQCKMat.h |
| |
| RGBController for SteelSeries Mouse |
| |
| Edbgon 22 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesQCKMatController.h"
class RGBController_SteelSeriesQCKMat : public RGBController
{
public:
RGBController_SteelSeriesQCKMat(SteelSeriesQCKMatController* controller_ptr);
~RGBController_SteelSeriesQCKMat();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
SteelSeriesQCKMatController* controller;
};
@@ -0,0 +1,100 @@
/*---------------------------------------------------------*\
| SteelSeriesQCKControllerMat.cpp |
| |
| Driver for SteelSeries Mouse |
| |
| Edbgon 22 May 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesQCKMatController.h"
#include "StringUtils.h"
SteelSeriesQCKMatController::SteelSeriesQCKMatController(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
SteelSeriesQCKMatController::~SteelSeriesQCKMatController()
{
hid_close(dev);
}
std::string SteelSeriesQCKMatController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesQCKMatController::GetDeviceName()
{
return(name);
}
std::string SteelSeriesQCKMatController::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 SteelSeriesQCKMatController::SetColors(std::vector<RGBColor> colors)
{
unsigned char buf[525];
unsigned char cbuf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
memset(cbuf, 0x00, sizeof(cbuf));
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
buf[0x01] = 0x0E;
buf[0x03] = 0x02;
buf[0x08] = 0xFF;
buf[0x09] = 0x32;
buf[0x0A] = 0xC8;
buf[0x0E] = 0x01;
buf[0x14] = 0xFF;
buf[0x15] = 0x32;
buf[0x16] = 0xC8;
buf[0x19] = 0x01;
buf[0x1A] = 0x01;
buf[0x1C] = 0x01;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
buf[0x05] = RGBGetRValue(colors[0]);
buf[0x06] = RGBGetGValue(colors[0]);
buf[0x07] = RGBGetBValue(colors[0]);
buf[0x11] = RGBGetRValue(colors[1]);
buf[0x12] = RGBGetGValue(colors[1]);
buf[0x13] = RGBGetBValue(colors[1]);
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 525);
cbuf[0x01] = 0x0D;
hid_write(dev, cbuf, 65);
}
@@ -0,0 +1,34 @@
/*---------------------------------------------------------*\
| SteelSeriesQCKControllerMat.h |
| |
| Driver for SteelSeries Mouse |
| |
| Edbgon 22 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 SteelSeriesQCKMatController
{
public:
SteelSeriesQCKMatController(hid_device* dev_handle, const char* path, std::string dev_name);
~SteelSeriesQCKMatController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetSerialString();
void SetColors(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
};
@@ -0,0 +1,174 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesRival3.cpp |
| |
| RGBController for SteelSeries Rival 3 |
| |
| B Horn (bahorn) 29 Aug 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesRival3.h"
/**------------------------------------------------------------------*\
@name Steel Series Rival 3
@category Mouse
@type USB
@save :white_check_mark:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectSteelSeriesRival3,DetectSteelSeriesAerox3,DetectSteelSeriesAerox5,DetectSteelSeriesAerox9
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesRival3::RGBController_SteelSeriesRival3(SteelSeriesMouseController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "SteelSeries";
type = DEVICE_TYPE_MOUSE;
description = "SteelSeries Mouse Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
version = controller->GetFirmwareVersion();
mode Direct;
Direct.name = "Direct";
Direct.value = STEELSERIES_MOUSE_EFFECT_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE;
Direct.color_mode = MODE_COLORS_PER_LED;
Direct.brightness_min = 0x00;
Direct.brightness_max = STEELSERIES_MOUSE_BRIGHTNESS_MAX;
Direct.brightness = STEELSERIES_MOUSE_BRIGHTNESS_MAX;
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = STEELSERIES_MOUSE_EFFECT_BREATHING_MIN;
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;
Breathing.color_mode = MODE_COLORS_PER_LED;
Breathing.speed_min = 0;
Breathing.speed_max = 2;
Breathing.speed = 1;
mode SpectrumCycle;
SpectrumCycle.name = "Spectrum Cycle";
SpectrumCycle.value = STEELSERIES_MOUSE_EFFECT_SPECTRUM_CYCLE;
SpectrumCycle.flags = MODE_FLAG_MANUAL_SAVE;
mode RainbowBreathing;
RainbowBreathing.name = "Rainbow Breathing";
RainbowBreathing.value = STEELSERIES_MOUSE_EFFECT_RAINBOW_BREATHING;
RainbowBreathing.flags = MODE_FLAG_MANUAL_SAVE;
/*------------------------------------------------------------------------*\
| This is a pretty cool mode where it flashes random colors. |
| |
| However, the flashes are in the frequency range where it probably needs |
| a proper warning for it to be compiled in by default. |
| |
| It is disabled in the vendor software, and is only known about as it is |
| documented in rivalcfg. |
| |
| If this does get re-enabled, worth noting it has an issue where this |
| mode is black if you come directly from one of the pulsating modes. |
\*------------------------------------------------------------------------*/
/*
mode Disco;
Disco.name = "Disco";
Disco.value = STEELSERIES_MOUSE_EFFECT_DISCO;
Disco.flags = MODE_FLAG_MANUAL_SAVE;
modes.push_back(Disco);
*/
steelseries_mouse mouse = controller->GetMouse();
for(const uint8_t i: mouse.modes)
{
switch(i)
{
case STEELSERIES_MOUSE_EFFECT_SPECTRUM_CYCLE:
modes.push_back(SpectrumCycle);
break;
case STEELSERIES_MOUSE_EFFECT_BREATHING_MIN:
modes.push_back(Breathing);
break;
case STEELSERIES_MOUSE_EFFECT_DIRECT:
modes.push_back(Direct);
break;
case STEELSERIES_MOUSE_EFFECT_RAINBOW_BREATHING:
modes.push_back(RainbowBreathing);
break;
}
}
SetupZones();
}
void RGBController_SteelSeriesRival3::DeviceSaveMode()
{
controller->Save();
}
RGBController_SteelSeriesRival3::~RGBController_SteelSeriesRival3()
{
delete controller;
}
void RGBController_SteelSeriesRival3::SetupZones()
{
steelseries_mouse mouse = controller->GetMouse();
for(const led_info info: mouse.leds)
{
zone zone;
zone.name = info.name;
zone.type = ZONE_TYPE_SINGLE;
zone.leds_min = 1;
zone.leds_max = 1;
zone.leds_count = 1;
zone.matrix_map = NULL;
zones.push_back(zone);
led mouse_led;
mouse_led.name = info.name;
mouse_led.value = info.value;
leds.push_back(mouse_led);
}
SetupColors();
}
void RGBController_SteelSeriesRival3::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesRival3::DeviceUpdateLEDs()
{
for(unsigned int i = 0; i < zones.size(); i++)
{
UpdateZoneLEDs(i);
}
DeviceUpdateMode();
}
void RGBController_SteelSeriesRival3::UpdateZoneLEDs(int zone)
{
UpdateSingleLED(zone);
}
void RGBController_SteelSeriesRival3::UpdateSingleLED(int led)
{
unsigned char red = RGBGetRValue(colors[led]);
unsigned char grn = RGBGetGValue(colors[led]);
unsigned char blu = RGBGetBValue(colors[led]);
controller->SetColor(leds[led].value, red, grn, blu, modes[active_mode].brightness);
}
void RGBController_SteelSeriesRival3::DeviceUpdateMode()
{
controller->SetLightEffectAll(modes[active_mode].value - modes[active_mode].speed);
}
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesRival3.h |
| |
| RGBController for SteelSeries Rival 3 |
| |
| B Horn (bahorn) 29 Aug 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesAerox3Controller.h"
#include "SteelSeriesRival3Controller.h"
class RGBController_SteelSeriesRival3 : public RGBController
{
public:
RGBController_SteelSeriesRival3(SteelSeriesMouseController* controller_ptr);
~RGBController_SteelSeriesRival3();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void DeviceSaveMode();
private:
SteelSeriesMouseController* controller;
};
@@ -0,0 +1,77 @@
/*---------------------------------------------------------*\
| SteelSeriesRival3Controller.cpp |
| |
| Driver for SteelSeries Rival 3 |
| |
| B Horn (bahorn) 29 Aug 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include "SteelSeriesRival3Controller.h"
SteelSeriesRival3Controller::SteelSeriesRival3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name)
{
}
SteelSeriesRival3Controller::~SteelSeriesRival3Controller()
{
hid_close(dev);
}
std::string SteelSeriesRival3Controller::GetFirmwareVersion()
{
const uint8_t FW_BUFFER_SIZE = 3;
uint8_t usb_buf[FW_BUFFER_SIZE] = { 0x00, 0x10, 0x00 };
uint16_t version;
std::string return_string;
hid_write(dev, usb_buf, FW_BUFFER_SIZE);
hid_read(dev, (unsigned char *)&version, 2);
return_string = std::to_string(version);
return return_string;
}
steelseries_mouse SteelSeriesRival3Controller::GetMouse()
{
return rival_3;
}
void SteelSeriesRival3Controller::SetLightEffectAll(uint8_t effect)
{
const uint8_t EFFECT_BUFFER_SIZE = 4;
uint8_t usb_buf[EFFECT_BUFFER_SIZE] = { 0x00, 0x06, 0x00, effect };
hid_write(dev, usb_buf, EFFECT_BUFFER_SIZE);
}
void SteelSeriesRival3Controller::SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
)
{
const uint8_t COLOR_BUFFER_SIZE = 8;
uint8_t usb_buf[COLOR_BUFFER_SIZE];
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x05;
usb_buf[0x02] = 0x00;
usb_buf[0x03] = zone_id;
usb_buf[0x04] = red;
usb_buf[0x05] = green;
usb_buf[0x06] = blue;
usb_buf[0x07] = brightness;
hid_write(dev, usb_buf, COLOR_BUFFER_SIZE);
}
@@ -0,0 +1,49 @@
/*---------------------------------------------------------*\
| SteelSeriesRival3Controller.h |
| |
| Driver for SteelSeries Rival 3 |
| |
| B Horn (bahorn) 29 Aug 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 "SteelSeriesGeneric.h"
#include "SteelSeriesMouseController.h"
static const steelseries_mouse rival_3 =
{
{ 0x04, 0x03, 0x00, 0x05 },
{
{"Front", 0x01},
{"Middle", 0x02},
{"Rear", 0x03},
{"Logo", 0x04}
}
};
class SteelSeriesRival3Controller: public SteelSeriesMouseController
{
public:
SteelSeriesRival3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name);
~SteelSeriesRival3Controller();
std::string GetFirmwareVersion();
steelseries_mouse GetMouse();
void SetLightEffectAll(uint8_t effect);
void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char brightness
);
};
@@ -0,0 +1,259 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesRival.cpp |
| |
| RGBController for SteelSeries Rival |
| |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesRival.h"
typedef struct
{
const char* name;
const int value;
} steelseries_rival_led_info;
static const steelseries_rival_led_info rival_650_leds[]=
{
{"Left 1", 0x12},
{"Left 2", 0x14},
{"Left 3", 0x16},
{"Right 1", 0x13},
{"Right 2", 0x15},
{"Right 3", 0x17},
};
static const steelseries_rival_led_info rival_600_leds[]=
{
{"Left top", 0x02},
{"Left mid", 0x04},
{"Left bottom", 0x06},
{"Right top", 0x03},
{"Right mid", 0x05},
{"Right bottom", 0x07},
};
/**------------------------------------------------------------------*\
@name Steel Series Rival
@category Mouse
@type USB
@save :x:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectSteelSeriesRival100,DetectSteelSeriesRival300,DetectSteelSeriesRival600,DetectSteelSeriesRival650,DetectSteelSeriesRival700
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesRival::RGBController_SteelSeriesRival(SteelSeriesRivalController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "SteelSeries";
type = DEVICE_TYPE_MOUSE;
description = "SteelSeries Rival Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
version = controller->GetFirmwareVersion();
mode Direct;
Direct.name = "Direct";
Direct.value = STEELSERIES_RIVAL_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Pulsate;
Pulsate.name = "Pulsate";
Pulsate.value = STEELSERIES_RIVAL_PULSATE;
Pulsate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
Pulsate.color_mode = MODE_COLORS_PER_LED;
Pulsate.speed_min = STEELSERIES_RIVAL_EFFECT_PULSATE_MIN;
Pulsate.speed_max = STEELSERIES_RIVAL_EFFECT_PULSATE_MAX;
Pulsate.speed = STEELSERIES_RIVAL_EFFECT_PULSATE_MID;
modes.push_back(Pulsate);
SetupZones();
}
RGBController_SteelSeriesRival::~RGBController_SteelSeriesRival()
{
delete controller;
}
void RGBController_SteelSeriesRival::SetupZones()
{
/* Rival 100 Series only has one Zone */
zone logo_zone;
logo_zone.name = "Logo";
logo_zone.type = ZONE_TYPE_SINGLE;
logo_zone.leds_min = 1;
logo_zone.leds_max = 1;
logo_zone.leds_count = 1;
logo_zone.matrix_map = NULL;
zones.push_back(logo_zone);
led logo_led;
logo_led.name = "Logo";
logo_led.value = 0;
leds.push_back(logo_led);
/* Rival 300 and 700 extend this by adding Scroll Wheel LED + Zone */
if(controller->GetMouseType() == RIVAL_300 ||
controller->GetMouseType() == RIVAL_700)
{
zone wheel_zone;
wheel_zone.name = "Scroll Wheel";
wheel_zone.type = ZONE_TYPE_SINGLE;
wheel_zone.leds_min = 1;
wheel_zone.leds_max = 1;
wheel_zone.leds_count = 1;
wheel_zone.matrix_map = NULL;
zones.push_back(wheel_zone);
led wheel_led;
wheel_led.name = "Scroll Wheel";
wheel_led.value = 1;
leds.push_back(wheel_led);
}
/* Rival 650 extends this by Scroll Wheel LED + Zone and additional lights LEDs + Zone */
else if(controller->GetMouseType() == RIVAL_650)
{
leds[0].value = 0x11;
zone wheel_zone;
wheel_zone.name = "Scroll Wheel";
wheel_zone.type = ZONE_TYPE_SINGLE;
wheel_zone.leds_min = 1;
wheel_zone.leds_max = 1;
wheel_zone.leds_count = 1;
wheel_zone.matrix_map = NULL;
zones.push_back(wheel_zone);
led wheel_led;
wheel_led.name = "Scroll Wheel";
wheel_led.value = 0x10;
leds.push_back(wheel_led);
zone mouse_zone;
mouse_zone.name = "Mouse";
mouse_zone.type = ZONE_TYPE_LINEAR;
mouse_zone.leds_min = 6;
mouse_zone.leds_max = 6;
mouse_zone.leds_count = 6;
mouse_zone.matrix_map = NULL;
zones.push_back(mouse_zone);
for(const steelseries_rival_led_info led_info: rival_650_leds)
{
led mouse_led;
mouse_led.name = led_info.name;
mouse_led.value = led_info.value;
leds.push_back(mouse_led);
}
}
/* Rival 600 is simular to Rival 650 */
else if(controller->GetMouseType() == RIVAL_600)
{
leds[0].value = 0x01;
zone wheel_zone;
wheel_zone.name = "Scroll Wheel";
wheel_zone.type = ZONE_TYPE_SINGLE;
wheel_zone.leds_min = 1;
wheel_zone.leds_max = 1;
wheel_zone.leds_count = 1;
wheel_zone.matrix_map = NULL;
zones.push_back(wheel_zone);
led wheel_led;
wheel_led.name = "Scroll Wheel";
wheel_led.value = 0x00;
leds.push_back(wheel_led);
zone mouse_zone;
mouse_zone.name = "Mouse";
mouse_zone.type = ZONE_TYPE_LINEAR;
mouse_zone.leds_min = 6;
mouse_zone.leds_max = 6;
mouse_zone.leds_count = 6;
mouse_zone.matrix_map = NULL;
zones.push_back(mouse_zone);
for(const steelseries_rival_led_info led_info: rival_600_leds)
{
led mouse_led;
mouse_led.name = led_info.name;
mouse_led.value = led_info.value;
leds.push_back(mouse_led);
}
}
SetupColors();
}
void RGBController_SteelSeriesRival::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesRival::DeviceUpdateLEDs()
{
for(unsigned int i = 0; i < leds.size(); i++)
{
unsigned char red = RGBGetRValue(colors[i]);
unsigned char grn = RGBGetGValue(colors[i]);
unsigned char blu = RGBGetBValue(colors[i]);
controller->SetColor(leds[i].value, red, grn, blu);
}
}
void RGBController_SteelSeriesRival::UpdateZoneLEDs(int zone)
{
for(unsigned int i = 0; i < zones[zone].leds_count; i++)
{
unsigned char red = RGBGetRValue(zones[zone].colors[i]);
unsigned char grn = RGBGetGValue(zones[zone].colors[i]);
unsigned char blu = RGBGetBValue(zones[zone].colors[i]);
controller->SetColor(zones[zone].leds[i].value, red, grn, blu);
}
}
void RGBController_SteelSeriesRival::UpdateSingleLED(int led)
{
unsigned char red = RGBGetRValue(colors[led]);
unsigned char grn = RGBGetGValue(colors[led]);
unsigned char blu = RGBGetBValue(colors[led]);
controller->SetColor(leds[led].value, red, grn, blu);
}
void RGBController_SteelSeriesRival::DeviceUpdateMode()
{
/* Strictly, the device actually does support different modes for the
* different zones, but we don't support that. */
//steelseries_type mouse_type = rival->GetMouseType();
switch (modes[active_mode].value)
{
case STEELSERIES_RIVAL_DIRECT:
controller->SetLightEffectAll(STEELSERIES_RIVAL_EFFECT_DIRECT);
break;
case STEELSERIES_RIVAL_PULSATE:
controller->SetLightEffectAll(modes[active_mode].speed);
break;
}
DeviceUpdateLEDs();
}
void RGBController_SteelSeriesRival::DeviceSaveMode()
{
DeviceUpdateMode();
controller->SaveMode();
}
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesRival.h |
| |
| RGBController for SteelSeries Rival |
| |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesRivalController.h"
class RGBController_SteelSeriesRival : public RGBController
{
public:
RGBController_SteelSeriesRival(SteelSeriesRivalController* controller_ptr);
~RGBController_SteelSeriesRival();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void DeviceSaveMode();
private:
SteelSeriesRivalController* controller;
};
@@ -0,0 +1,353 @@
/*---------------------------------------------------------*\
| SteelSeriesRivalController.cpp |
| |
| Driver for SteelSeries Rival |
| |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstdint>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include "SteelSeriesRivalController.h"
#include "StringUtils.h"
static void send_usb_msg(hid_device* dev, unsigned char * data_pkt, unsigned int size)
{
unsigned char* usb_pkt = new unsigned char[size + 1];
usb_pkt[0] = 0x00;
for(unsigned int i = 1; i < size + 1; i++)
{
usb_pkt[i] = data_pkt[i-1];
}
hid_write(dev, usb_pkt, size + 1);
delete[] usb_pkt;
}
SteelSeriesRivalController::SteelSeriesRivalController
(
hid_device* dev_handle,
steelseries_type proto_type,
const char* path,
std::string dev_name
)
{
dev = dev_handle;
location = path;
name = dev_name;
proto = proto_type;
}
SteelSeriesRivalController::~SteelSeriesRivalController()
{
hid_close(dev);
}
std::string SteelSeriesRivalController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesRivalController::GetDeviceName()
{
return(name);
}
std::string SteelSeriesRivalController::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 SteelSeriesRivalController::GetFirmwareVersion()
{
if (proto != RIVAL_300 && proto != RIVAL_700) return "";
unsigned char usb_buf[2] = { 0x10, 0x00 };
uint16_t version;
std::string return_string;
send_usb_msg(dev, usb_buf, 2);
hid_read(dev, (unsigned char *)&version, 2);
return_string = std::to_string(version);
return return_string;
}
steelseries_type SteelSeriesRivalController::GetMouseType()
{
return proto;
}
/* Saves to the internal configuration */
void SteelSeriesRivalController::SaveMode()
{
unsigned char usb_buf[9];
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x09;
send_usb_msg(dev, usb_buf, 9);
}
void SteelSeriesRivalController::SetLightEffect
(
unsigned char zone_id,
unsigned char effect
)
{
unsigned char usb_buf[9];
memset(usb_buf, 0x00, sizeof(usb_buf));
switch(proto)
{
case RIVAL_100:
usb_buf[0x00] = 0x07;
usb_buf[0x01] = 0x00;
break;
case RIVAL_300:
usb_buf[0x00] = 0x07;
usb_buf[0x01] = zone_id + 1;
break;
case RIVAL_700:
return;
default:
break;
}
usb_buf[0x02] = effect;
send_usb_msg(dev, usb_buf, 9);
}
void SteelSeriesRivalController::SetLightEffectAll
(
unsigned char effect
)
{
switch(proto)
{
case RIVAL_100:
SetLightEffect(0, effect);
break;
case RIVAL_300:
SetLightEffect(0, effect);
SetLightEffect(1, effect);
break;
case RIVAL_650:
for(int i=0x10; i<0x18; i++)
{
SetLightEffect(i, effect);
}
break;
default:
break;
}
}
void SteelSeriesRivalController::SetRival650Color
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[60];
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x03;
usb_buf[0x04] = 0x30;
usb_buf[0x06] = 0x10;
usb_buf[0x07] = 0x27;
usb_buf[0x16] = 0x01;
usb_buf[0x1E] = 0x04;
usb_buf[0x1F] = red;
usb_buf[0x20] = green;
usb_buf[0x21] = blue;
usb_buf[0x22] = 0xFF;
usb_buf[0x27] = 0xFF;
usb_buf[0x29] = 0x54;
usb_buf[0x2C] = 0xFF;
usb_buf[0x2D] = 0x54;
usb_buf[0x2E] = red;
usb_buf[0x2F] = green;
usb_buf[0x30] = blue;
usb_buf[0x31] = 0x56;
send_usb_msg(dev, usb_buf, 60);
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x03;
usb_buf[0x02] = 0x30;
usb_buf[0x04] = 0x2C;
send_usb_msg(dev, usb_buf, 60);
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x05;
usb_buf[0x02] = zone_id;//mousekey 0x10-0x17
usb_buf[0x03] = 0xFF;
usb_buf[0x08] = 0x5C;
send_usb_msg(dev, usb_buf, 60);
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x1C;
usb_buf[0x02] = 0x55;
usb_buf[0x04] = 0x46;
send_usb_msg(dev, usb_buf, 60);
}
void SteelSeriesRivalController::SetRival600Color
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_pkt[0x07];
memset(usb_pkt, 0x00, sizeof(usb_pkt));
usb_pkt[0x00] = 0x1c;
usb_pkt[0x01] = 0x27;
usb_pkt[0x02] = 0x00;
usb_pkt[0x03] = 1 << zone_id;
usb_pkt[0x04] = red;
usb_pkt[0x05] = green;
usb_pkt[0x06] = blue;
hid_write(dev, usb_pkt, 0x07);
}
void SteelSeriesRivalController::SetRival700Color
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
const uint16_t REPORT_SIZE = 578;
unsigned char usb_buf[REPORT_SIZE];
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0x00] = 0x05;
usb_buf[0x02] = zone_id;
usb_buf[0x03] = red;
usb_buf[0x04] = green;
usb_buf[0x05] = blue;
usb_buf[0x0b] = zone_id;
usb_buf[0x0c] = 0x01;
unsigned char *usb_pkt = new unsigned char[REPORT_SIZE + 1];
usb_pkt[0] = 0x00;
for (unsigned int i = 1; i < REPORT_SIZE + 1; i++)
{
usb_pkt[i] = usb_buf[i - 1];
}
hid_send_feature_report(dev, usb_pkt, REPORT_SIZE + 1);
delete[] usb_pkt;
}
void SteelSeriesRivalController::SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[9];
memset(usb_buf, 0x00, sizeof(usb_buf));
switch(proto)
{
case RIVAL_100:
usb_buf[0x00] = 0x05;
usb_buf[0x01] = 0x00;
break;
case RIVAL_300:
usb_buf[0x00] = 0x08;
usb_buf[0x01] = zone_id + 1;
break;
case RIVAL_650:
SetRival650Color(zone_id, red, green, blue);
return;
case RIVAL_600:
SetRival600Color(zone_id, red, green, blue);
return;
case RIVAL_700:
SetRival700Color(zone_id, red, green, blue);
return;
default:
break;
}
usb_buf[0x02] = red;
usb_buf[0x03] = green;
usb_buf[0x04] = blue;
send_usb_msg(dev, usb_buf, 9);
}
void SteelSeriesRivalController::SetColorAll
(
unsigned char red,
unsigned char green,
unsigned char blue
)
{
switch(proto)
{
case RIVAL_100:
SetColor(0, red, green, blue);
break;
case RIVAL_300:
SetColor(0, red, green, blue);
SetColor(1, red, green, blue);
break;
case RIVAL_650:
for(int i = 0x10; i < 0x18; i++)
{
SetColor(i, red, green, blue);
}
break;
default:
break;
}
}
@@ -0,0 +1,110 @@
/*---------------------------------------------------------*\
| SteelSeriesRivalController.h |
| |
| Driver for SteelSeries Rival |
| |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "SteelSeriesGeneric.h"
/* Mode, we then use these to set actual effect based on speed. */
enum
{
STEELSERIES_RIVAL_DIRECT = 0x00,
STEELSERIES_RIVAL_PULSATE = 0x01
};
/* Effects */
enum
{
STEELSERIES_RIVAL_EFFECT_DIRECT = 0x01,
STEELSERIES_RIVAL_EFFECT_PULSATE_MIN = 0x02,
STEELSERIES_RIVAL_EFFECT_PULSATE_MID = 0x03,
STEELSERIES_RIVAL_EFFECT_PULSATE_MAX = 0x04
};
class SteelSeriesRivalController
{
public:
SteelSeriesRivalController
(
hid_device* dev_handle,
steelseries_type proto_type,
const char* path,
std::string dev_name
);
~SteelSeriesRivalController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetSerialString();
std::string GetFirmwareVersion();
steelseries_type GetMouseType();
void SaveMode();
void SetLightEffect
(
unsigned char zone_id,
unsigned char effect
);
void SetLightEffectAll
(
unsigned char effect
);
void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SetColorAll
(
unsigned char red,
unsigned char green,
unsigned char blue
);
private:
hid_device* dev;
std::string location;
std::string name;
steelseries_type proto;
void SetRival650Color
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SetRival600Color
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SetRival700Color
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
);
};
@@ -0,0 +1,152 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesSensei.cpp |
| |
| RGBController for SteelSeries Sensei |
| |
| Based on SteelSeries Rival controller |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesSensei.h"
/**------------------------------------------------------------------*\
@name Steel Series Sensei
@category Mouse
@type USB
@save :x:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectSteelSeriesSensei
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesSensei::RGBController_SteelSeriesSensei(SteelSeriesSenseiController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "SteelSeries";
type = DEVICE_TYPE_MOUSE;
description = "SteelSeries Sensei Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = STEELSERIES_SENSEI_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = STEELSERIES_SENSEI_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
Breathing.color_mode = MODE_COLORS_PER_LED;
Breathing.speed_min = STEELSERIES_SENSEI_EFFECT_BREATHING_MIN;
Breathing.speed_max = STEELSERIES_SENSEI_EFFECT_BREATHING_MAX;
Breathing.speed = STEELSERIES_SENSEI_EFFECT_BREATHING_MID;
modes.push_back(Breathing);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = STEELSERIES_SENSEI_MODE_RAINBOW;
Rainbow.flags = MODE_FLAG_HAS_SPEED;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.speed_min = STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN;
Rainbow.speed_max = STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX;
Rainbow.speed = STEELSERIES_SENSEI_EFFECT_RAINBOW_MID;
modes.push_back(Rainbow);
SetupZones();
}
RGBController_SteelSeriesSensei::~RGBController_SteelSeriesSensei()
{
delete controller;
}
void RGBController_SteelSeriesSensei::SetupZones()
{
zone logo_zone;
logo_zone.name = "Logo";
logo_zone.type = ZONE_TYPE_SINGLE;
logo_zone.leds_min = 1;
logo_zone.leds_max = 1;
logo_zone.leds_count = 1;
logo_zone.matrix_map = NULL;
zones.push_back(logo_zone);
led logo_led;
logo_led.name = "Logo";
leds.push_back(logo_led);
zone wheel_zone;
wheel_zone.name = "Scroll Wheel";
wheel_zone.type = ZONE_TYPE_SINGLE;
wheel_zone.leds_min = 1;
wheel_zone.leds_max = 1;
wheel_zone.leds_count = 1;
wheel_zone.matrix_map = NULL;
zones.push_back(wheel_zone);
led wheel_led;
wheel_led.name = "Scroll Wheel";
leds.push_back(wheel_led);
SetupColors();
}
void RGBController_SteelSeriesSensei::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesSensei::DeviceUpdateLEDs()
{
UpdateZoneLEDs(0);
UpdateZoneLEDs(1);
}
void RGBController_SteelSeriesSensei::UpdateZoneLEDs(int zone)
{
RGBColor color = colors[zone];
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
switch(modes[active_mode].value)
{
case STEELSERIES_SENSEI_MODE_DIRECT:
controller->SetColor(zone, red, grn, blu);
break;
case STEELSERIES_SENSEI_MODE_BREATHING:
case STEELSERIES_SENSEI_MODE_RAINBOW:
controller->SetLightEffect(zone, modes[active_mode].value, modes[active_mode].speed, red, grn, blu);
break;
}
}
void RGBController_SteelSeriesSensei::UpdateSingleLED(int led)
{
/*---------------------------------------------------------*\
| Each zone only has a single LED, so we can use the LED ID |
| to reference the existing zone code. |
\*---------------------------------------------------------*/
UpdateZoneLEDs(led);
}
void RGBController_SteelSeriesSensei::DeviceUpdateMode()
{
/*---------------------------------------------------------*\
| Strictly, the device actually does support different modes|
| for the different zones, but we don't support that. |
\*---------------------------------------------------------*/
DeviceUpdateLEDs();
}
@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesSensei.h |
| |
| RGBController for SteelSeries Sensei |
| |
| Based on SteelSeries Rival controller |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesSenseiController.h"
class RGBController_SteelSeriesSensei : public RGBController
{
public:
RGBController_SteelSeriesSensei(SteelSeriesSenseiController* controller_ptr);
~RGBController_SteelSeriesSensei();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
SteelSeriesSenseiController* controller;
};
@@ -0,0 +1,297 @@
/*---------------------------------------------------------*\
| SteelSeriesSenseiController.cpp |
| |
| Driver for SteelSeries Sensei |
| |
| Based on SteelSeries Rival controller |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include "SteelSeriesSenseiController.h"
#include "StringUtils.h"
static void send_usb_msg(hid_device* dev, unsigned char * data_pkt, unsigned int size)
{
unsigned char* usb_pkt = new unsigned char[size + 1];
usb_pkt[0] = 0x00;
for(unsigned int i = 1; i < size + 1; i++)
{
usb_pkt[i] = data_pkt[i-1];
}
hid_write(dev, usb_pkt, size + 1);
delete[] usb_pkt;
}
SteelSeriesSenseiController::SteelSeriesSenseiController
(
hid_device* dev_handle,
steelseries_type proto_type,
const char* path,
std::string dev_name
)
{
dev = dev_handle;
location = path;
name = dev_name;
proto = proto_type;
}
SteelSeriesSenseiController::~SteelSeriesSenseiController()
{
hid_close(dev);
}
std::string SteelSeriesSenseiController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesSenseiController::GetDeviceName()
{
return(name);
}
std::string SteelSeriesSenseiController::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));
}
steelseries_type SteelSeriesSenseiController::GetMouseType()
{
return proto;
}
/* Saves to the internal configuration */
void SteelSeriesSenseiController::Save()
{
/*-----------------------------------------------------*\
| Saves to the internal configuration |
\*-----------------------------------------------------*/
unsigned char usb_buf[9];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Save packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x59;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
send_usb_msg(dev, usb_buf, 9);
}
void SteelSeriesSenseiController::SetLightEffect
(
unsigned char zone_id,
unsigned char effect,
unsigned char speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Light Effect packet |
\*-----------------------------------------------------*/
unsigned char dur1 = 0x27;
unsigned char dur2 = 0x10; //10 sec cycle
switch(effect)
{
case STEELSERIES_SENSEI_MODE_BREATHING:
switch(speed)
{
case STEELSERIES_SENSEI_EFFECT_BREATHING_MIN:
dur1 = 0x27;
dur2 = 0x10; //10 sec cycle
break;
case STEELSERIES_SENSEI_EFFECT_BREATHING_MID:
dur1 = 0x13;
dur2 = 0x88; //5 sec cycle
break;
case STEELSERIES_SENSEI_EFFECT_BREATHING_MAX:
dur1 = 0x09;
dur2 = 0xc4; //2.5 sec cycle
break;
}
usb_buf[0x00] = 0x5B; //command byte
usb_buf[0x02] = zone_id;
usb_buf[0x04] = dur1; //duration in ms 1st byte
usb_buf[0x03] = dur2; //duration in ms 2nd byte
usb_buf[0x1B] = 0x03; //Number of colors
/*---------------------------------------------*\
| Original software duplicates these RGB bytes, |
| but seems unnecessary |
\*---------------------------------------------*/
usb_buf[0x1C] = red;
usb_buf[0x1D] = green;
usb_buf[0x1E] = blue;
usb_buf[0x1F] = red;
usb_buf[0x20] = green;
usb_buf[0x21] = blue;
usb_buf[0x26] = 0x7F; //percent of duration out of 0xFF
usb_buf[0x27] = red;
usb_buf[0x28] = green;
usb_buf[0x29] = blue;
usb_buf[0x2A] = 0x7F; //percent of duration out of 0xFF
break;
case STEELSERIES_SENSEI_MODE_RAINBOW:
switch(speed)
{
case STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN:
dur1 = 0x4E;
dur2 = 0x20; //20 sec cycle
break;
case STEELSERIES_SENSEI_EFFECT_RAINBOW_MID:
dur1 = 0x27;
dur2 = 0x10; //10 sec cycle
break;
case STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX:
dur1 = 0x13;
dur2 = 0x88; //5 sec cycle
break;
}
usb_buf[0x00] = 0x5B; //command byte
usb_buf[0x02] = zone_id;
usb_buf[0x04] = dur1; //duration in ms 1st byte
usb_buf[0x03] = dur2; //duration in ms 2nd byte
usb_buf[0x1B] = 0x07; //Number of colors
/*---------------------------------------------*\
| Original software duplicates these RGB bytes, |
| but seems unnecessary |
\*---------------------------------------------*/
usb_buf[0x1C] = red;
usb_buf[0x1D] = green;
usb_buf[0x1E] = blue;
usb_buf[0x1C] = 0xFF;
usb_buf[0x1F] = 0xFF;
usb_buf[0x22] = 0x14;
usb_buf[0x23] = 0xFF;
usb_buf[0x24] = 0xFF;
usb_buf[0x26] = 0x2B; //percent of duration out of 0xFF
usb_buf[0x28] = 0xFF;
usb_buf[0x2A] = 0x2B;
usb_buf[0x2C] = 0xFF;
usb_buf[0x2D] = 0xFF; //percent of duration out of 0xFF
usb_buf[0x2E] = 0x28;
usb_buf[0x31] = 0xFF;
usb_buf[0x32] = 0x2B;
usb_buf[0x33] = 0xFF;
usb_buf[0x35] = 0xFF;
usb_buf[0x36] = 0x2B;
usb_buf[0x37] = 0xFF;
usb_buf[0x3A] = 0x14;
break;
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
send_usb_msg(dev, usb_buf, sizeof(usb_buf));
}
void SteelSeriesSenseiController::SetLightEffectAll
(
unsigned char effect,
unsigned char speed,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
SetLightEffect(0, effect, speed, red, green, blue);
SetLightEffect(1, effect, speed, red, green, blue);
}
void SteelSeriesSenseiController::SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Set Color packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x5B; //command byte
usb_buf[0x02] = zone_id;
/*-----------------------------------------------------*\
| Original software duplicates these RGB bytes, |
| but seems unnecessary |
\*-----------------------------------------------------*/
usb_buf[0x1C] = red;
usb_buf[0x1D] = green;
usb_buf[0x1E] = blue;
usb_buf[0x1F] = red;
usb_buf[0x20] = green;
usb_buf[0x21] = blue;
usb_buf[0x13] = 0x01; //Static color flag
usb_buf[0x1B] = 0x01; //Number of colors
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
send_usb_msg(dev, usb_buf, sizeof(usb_buf));
}
void SteelSeriesSenseiController::SetColorAll
(
unsigned char red,
unsigned char green,
unsigned char blue
)
{
SetColor(0, red, green, blue);
SetColor(1, red, green, blue);
}
@@ -0,0 +1,103 @@
/*---------------------------------------------------------*\
| SteelSeriesSenseiController.h |
| |
| Driver for SteelSeries Sensei |
| |
| Based on SteelSeries Rival controller |
| B Horn (bahorn) 13 May 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "SteelSeriesGeneric.h"
/*-------------------------------------------------------------*\
| Mode, we then use these to set actual effect based on speed. |
\*-------------------------------------------------------------*/
enum
{
STEELSERIES_SENSEI_MODE_DIRECT = 0x00,
STEELSERIES_SENSEI_MODE_BREATHING = 0x01,
STEELSERIES_SENSEI_MODE_RAINBOW = 0x02
};
/*-------------------------------------------------------------*\
| Effects |
\*-------------------------------------------------------------*/
enum
{
STEELSERIES_SENSEI_EFFECT_DIRECT = 0x01,
STEELSERIES_SENSEI_EFFECT_BREATHING_MIN = 0x02,
STEELSERIES_SENSEI_EFFECT_BREATHING_MID = 0x03,
STEELSERIES_SENSEI_EFFECT_BREATHING_MAX = 0x04,
STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN = 0x05,
STEELSERIES_SENSEI_EFFECT_RAINBOW_MID = 0x06,
STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX = 0x07
};
class SteelSeriesSenseiController
{
public:
SteelSeriesSenseiController
(
hid_device* dev_handle,
steelseries_type proto_type,
const char* path,
std::string dev_name
);
~SteelSeriesSenseiController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetSerialString();
steelseries_type GetMouseType();
void Save();
void SetLightEffect
(
unsigned char zone_id,
unsigned char effect,
unsigned char speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SetLightEffectAll
(
unsigned char effect,
unsigned char speed,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SetColor
(
unsigned char zone_id,
unsigned char red,
unsigned char green,
unsigned char blue
);
void SetColorAll
(
unsigned char red,
unsigned char green,
unsigned char blue
);
private:
hid_device* dev;
std::string location;
std::string name;
steelseries_type proto;
};
@@ -0,0 +1,103 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesSiberia.cpp |
| |
| RGBController for SteelSeries Siberia |
| |
| E Karlsson (pilophae) 18 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_SteelSeriesSiberia.h"
/**------------------------------------------------------------------*\
@name Steel Series Siberia
@category Headset
@type USB
@save :x:
@direct :x:
@effects :white_check_mark:
@detectors DetectSteelSeriesHeadset
@comment
\*-------------------------------------------------------------------*/
RGBController_SteelSeriesSiberia::RGBController_SteelSeriesSiberia(SteelSeriesSiberiaController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "SteelSeries";
type = DEVICE_TYPE_HEADSET;
description = "SteelSeries Siberia Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Static;
Static.name = "Static";
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Static.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Static);
SetupZones();
}
RGBController_SteelSeriesSiberia::~RGBController_SteelSeriesSiberia()
{
delete controller;
}
void RGBController_SteelSeriesSiberia::SetupZones()
{
/* Siberia 350 only has one Zone */
zone earpiece_zone;
earpiece_zone.name = "Headset";
earpiece_zone.type = ZONE_TYPE_SINGLE;
earpiece_zone.leds_min = 1;
earpiece_zone.leds_max = 1;
earpiece_zone.leds_count = 1;
earpiece_zone.matrix_map = NULL;
zones.push_back(earpiece_zone);
led earpiece_led;
earpiece_led.name = "Headset LED";
leds.push_back(earpiece_led);
SetupColors();
}
void RGBController_SteelSeriesSiberia::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_SteelSeriesSiberia::DeviceUpdateLEDs()
{
unsigned char red = RGBGetRValue(colors[0]);
unsigned char grn = RGBGetGValue(colors[0]);
unsigned char blu = RGBGetBValue(colors[0]);
controller->SetColor(red, grn, blu);
}
void RGBController_SteelSeriesSiberia::UpdateZoneLEDs(int zone)
{
RGBColor color = colors[zone];
unsigned char red = RGBGetRValue(color);
unsigned char grn = RGBGetGValue(color);
unsigned char blu = RGBGetBValue(color);
controller->SetColor(red, grn, blu);
}
void RGBController_SteelSeriesSiberia::UpdateSingleLED(int led)
{
/* Each zone only has a single LED, so we can use the LED ID to reference
* the existing zone code. */
UpdateZoneLEDs(led);
}
void RGBController_SteelSeriesSiberia::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -0,0 +1,34 @@
/*---------------------------------------------------------*\
| RGBController_SteelSeriesSiberia.h |
| |
| RGBController for SteelSeries Siberia |
| |
| E Karlsson (pilophae) 18 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "SteelSeriesSiberiaController.h"
class RGBController_SteelSeriesSiberia : public RGBController
{
public:
RGBController_SteelSeriesSiberia(SteelSeriesSiberiaController* controller_ptr);
~RGBController_SteelSeriesSiberia();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
SteelSeriesSiberiaController* controller;
};
@@ -0,0 +1,105 @@
/*---------------------------------------------------------*\
| SteelSeriesSiberiaController.cpp |
| |
| Driver for SteelSeries Siberia |
| |
| E Karlsson (pilophae) 18 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "SteelSeriesSiberiaController.h"
#include "StringUtils.h"
static void send_usb_msg(hid_device* dev, unsigned char * data_pkt, unsigned int size)
{
unsigned char usb_pkt[16];
memset(usb_pkt, 0x00, sizeof(usb_pkt));
// Report number
usb_pkt[0] = 0x01;
// Magic
usb_pkt[1] = 0x00;
// Command
usb_pkt[2] = data_pkt[0];
// Payload length
usb_pkt[3] = size - 1;
for(unsigned int i = 0; i < (size - 1); i++)
{
usb_pkt[4 + i] = data_pkt[1 + i];
}
hid_write(dev, usb_pkt, 16);
}
SteelSeriesSiberiaController::SteelSeriesSiberiaController(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
SteelSeriesSiberiaController::~SteelSeriesSiberiaController()
{
hid_close(dev);
}
std::string SteelSeriesSiberiaController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string SteelSeriesSiberiaController::GetDeviceName()
{
return(name);
}
std::string SteelSeriesSiberiaController::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 SteelSeriesSiberiaController::SetColor(unsigned char red, unsigned char green, unsigned char blue)
{
unsigned char usb_buf[4];
memset(usb_buf, 0x00, sizeof(usb_buf));
// Command 1
usb_buf[0] = 0x95;
usb_buf[1] = 0x80;
usb_buf[2] = 0xbf;
send_usb_msg(dev, usb_buf, 3);
// Command 2
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0] = 0x80;
usb_buf[1] = 0x52;
usb_buf[2] = 0x20;
send_usb_msg(dev, usb_buf, 3);
// Command 3 (Set color)
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0] = 0x83;
usb_buf[1] = red;
usb_buf[2] = green;
usb_buf[3] = blue;
send_usb_msg(dev, usb_buf, 4);
// Command 4
memset(usb_buf, 0x00, sizeof(usb_buf));
usb_buf[0] = 0x93;
usb_buf[1] = 0x03;
usb_buf[2] = 0x80;
send_usb_msg(dev, usb_buf, 3);
}
@@ -0,0 +1,33 @@
/*---------------------------------------------------------*\
| SteelSeriesSiberiaController.h |
| |
| Driver for SteelSeries Siberia |
| |
| E Karlsson (pilophae) 18 Jun 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
class SteelSeriesSiberiaController
{
public:
SteelSeriesSiberiaController(hid_device* dev_handle, const char* path, std::string dev_name);
~SteelSeriesSiberiaController();
std::string GetDeviceLocation();
std::string GetDeviceName();
std::string GetSerialString();
void SetColor(unsigned char red, unsigned char green, unsigned char blue);
private:
hid_device* dev;
std::string location;
std::string name;
};
@@ -0,0 +1,20 @@
/*---------------------------------------------------------*\
| color32.h |
| |
| Class to hold 32-bit color data |
| |
| David Lee (RAMChYLD) 15 Nov 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
typedef struct
{
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
} color32;